Подключение arduino к интернету: настройка режима клиент-сервер, обработка get и post запросов

– Web – server на Arduino с авторизацией доступа – Микроконтроллеры STM32 и AVR. Андроид и управление голосом. Беспилотные летательные аппараты

“));

          client.println(F(“”));

          client.println(F(” Web-server на Arduino MEGA 1280
и контроллере w5500(enc28j60)
с авторизацией доступа”));

          client.println(F(“
“));    

          client.println(F(“”));          

     client.println(F(“”));

     client.println(F(“Красный светодиод:
“));

     client.println(F(“ON
“));

     client.println(F(“OFF

“));

     client.println(F(“Зеленый светодиод:
“));

     client.println(F(“ON
“));

     client.println(F(“OFF

“));

     client.println(F(“Синий светодиод:
“));

     client.println(F(“ON
“));

     client.println(F(“OFF
“));

     client.println(F(“”));

     client.println(F(“”));

     client.println(F(“”));

     client.println(F(“
“));

       sensors.requestTemperatures(); 

       dtostrf(sensors.getTempCByIndex(0),7,1,buf); 

     client.print(F(“Температура вне помещения “)); 

     client.print(buf); 

     client.println(F(” градусов C
“));

         float tin = bmp.readTemperature()-1.0; // Датчик bmp280 дает превышение

         // температуры примерно на 1 град. С

         dtostrf( tin,7,1,buf); 

     client.print(F(“Температура в помещении “)); 

     client.print(buf); 

     client.println(F(” градусов C
“));      

         float pr = 0.00750062*bmp.readPressure(); 

         dtostrf(pr,7,1,buf); 

     client.print(F(“Атмосферное давление “)); 

     client.print(buf); 

     client.println(F(” мм.рт.ст
“));

        float alt = bmp.readAltitude(1013.25); 

         dtostrf(alt,7,1,buf); 

     client.print(F(“Приблизительная высота
над уровнем моря “)); 

     client.print(buf); 

     client.println(F(” м

“));     

        if (digitalRead(3)){ client.println(F(“Красный светодиод ВКЛЮЧЕН
“)); }

             else{ client.println(F(“Красный светодиод ВЫКЛЮЧЕН
“)); }

        if (digitalRead(5)){ client.println(F(“Зеленый светодиод ВКЛЮЧЕН
“));}

             else{ client.println(F(“Зеленый светодиод ВЫКЛЮЧЕН
“)); }

        if (digitalRead(7)){client.println(F(“Синий светодиод  ВКЛЮЧЕН
“)); }

             else{ client.println(F(“Синий светодиод  ВЫКЛЮЧЕН
“)); }

     client.println(“”);

   client.print(F(“Свободно памяти: “));

   client.println(freeRam());

   client.print(F(“
Index: “));

   client.println(passwd);

        client.println(F(“”)); 

          client.println(F(“”));

}

void html_doc_index(EthernetClient client) {

          client.println(F(“HTTP/1.1 200 OK”));

          client.println(F(“Content-Type: text/html; charset=windows-1251”));

          client.print(F(“Connection: close

“));  

          client.println(F(“”));

          client.println(F(“”));

          client.println(F(“”));

          client.println(F(“”)); 

          client.print(F(“Ваш index: “));

          client.println(passwd);

          client.println(F(“”)); 

          client.println(F(“”));

}

void onoff(String buffer)  {

if(buffer.indexOf(“r=1”) >= 0) {digitalWrite(3, HIGH);}

if(buffer.indexOf(“r=0”) >= 0) {digitalWrite(3, LOW);}

if(buffer.indexOf(“g=1”) >= 0) {digitalWrite(5, HIGH);}

if(buffer.indexOf(“g=0”) >= 0) {digitalWrite(5, LOW);}

if(buffer.indexOf(“b=1”) >= 0) {digitalWrite(7, HIGH);}

if(buffer.indexOf(“b=0”) >= 0) {digitalWrite(7, LOW);}  

}

int freeRam () {

 extern int __heap_start, *__brkval;  int v;  

 return (int) &v – (__brkval == 0 ? (int) &__heap_start : (int) __brkval); }

 void meter()

{

     sensors.requestTemperatures();

     float cel=sensors.getTempCByIndex(0); 

     float cel1 = bmp.readTemperature()-1.0;

     float pr = 0.00750062*bmp.readPressure();      

       lcd.setCursor(0, 0);

       lcd.print(“To=”);

       lcd.print(cel,1);

       lcd.print(” Ti=”);

       lcd.print(cel1,1);

       lcd.print(“C “);

       lcd.setCursor(0, 1);

       lcd.print(”   P=”);

       lcd.print(pr,0);

       lcd.print(“mm Hg          “);     

}

Источник: https://sites.google.com/site/webstm32/web-server-avtorizaciej

Программирование Arduino – библиотека Ethernet

Ethernet library – библиотека для работы с Ethernet-шилдом

– это дополнительная плата, которая подключается к ардуино и позволяет этой замечательной плате посылать и получать данные через локальную сеть и даже работать с Интернетом.

Работа с протоколами TCP/IP в шилде реализована аппаратно на микросхеме W5100.

Для работы с данным шилдом ничего дополнительно скачивать не нужно, т.к. в составе Arduino IDE уже есть удобная библиотека (librariesEthernet).

Библиотека содержит три класса: EthernetClass ,Client и Server.

Чтобы начать работать с библиотекой – её нужно сначала подключить; для этого можно написать#include или выбрать в меню Arduino IDE: Sketch – Import Library… — Ethernet и в Ваш скетч автоматически добавятся строчки:#include #include #include Библиотека позволяет выступать не только в качестве клиента, но и как сервер и поддерживает до четырёх одновременных подключений (входящих или исходящих). Рассмотрим функции, которые реализуют этот функционал.

Первым делом необходимо инициализировать работу с библиотекой функцией begin, которая принимает от двух до четырёх параметров:

void begin(uint8_t *, uint8_t *);

Описание: Инициализирует работу с библиотекой Ethernet и устанавливает сетевые настройки. Синтаксис:Ethernet.begin(mac, ip); Ethernet.begin(mac, ip, gateway); Ethernet.

begin(mac, ip, gateway, subnet);Параметры: mac — MAC-адрес — физический адрес устройства (массив из 6 байт) ip — IP-адрес – сетевой адрес Вашего устройства (массив из 4 байт) gateway – IP-адрес Вашего сетевого шлюза (массив из 4 байт) (по-умолчанию – IP-адрес устройства с 1 в последнем октете) subnet – маска подсети. (массив из 4 байт) (по-умолчанию 255.255.255.0) если Вы не помните свои сетевые параметры, то на компьютере под управлением ОС Windows их можно посмотреть через Пуск – Панель управления – Сетевые подключения Щёлкнуть правой кнопкой мышки на «Подключение по локальной сети» и выбрать «Свойства» В появившемся окошке выделить в списке «Протокол Интернета TCP/IP» и нажать кнопку «Свойства»или же просто набрать в консоли командуipconfig /allВозвращаемое значение: ничего Пример:#include byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; byte ip[] = { 10, 0, 0, 177 }; void setup() { Ethernet.begin(mac, ip); }Как уже отметили – библиотека позволяет работать в двух режимах – серверном или клиентском.

Рассмотрим серверные функции.

Server(uint16_t);

Описание: Это конструктор класса Server – при вызове данной функции создаётся объект типа Server, для обработки входящих подключений по указанному порту.

Синтаксис:Server(port);Параметры: port: номер порта сервера (int) Возвращаемое значение: ничего Пример:#include // задаём сетевую конфигурацию (шлюз и маска подсети – не обязательно) byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; byte ip[] = { 10, 0, 0, 177 }; byte gateway[] = { 10, 0, 0, 1 }; byte subnet[] = { 255, 255, 0, 0 }; // telnet на стандартном порту 23 Server server = Server(23); void setup() { // инициализация Ethernet-модуля Ethernet.begin(mac, ip, gateway, subnet); // запускаем сервер server.begin(); } void loop() { Client client = server.available(); if (client) { server.write(client.read()); } }

void begin();

Описание: Запускает сервер на приём входящих соединений. Синтаксис:server.

begin();Параметры: нет Возвращаемое значение: ничего Пример:#include // задаём сетевую конфигурацию (шлюз и маска подсети – не обязательно) byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; byte ip[] = { 10, 0, 0, 177 }; byte gateway[] = { 10, 0, 0, 1 }; byte subnet[] = { 255, 255, 0, 0 }; // telnet на стандартном порту 23 Server server = Server(23); void setup() { // инициализация Ethernet-модуля Ethernet.begin(mac, ip, gateway, subnet); // запускаем сервер server.begin(); }

Client available();

Описание: Возвращает объект типа Client, который представляет клиентское подключение к серверу и имеет данные для считывания (запрос). Объект сохраняется при выходе из области видимости; его можно закрыть вызовом client.stop(). Синтаксис:server.

available();Параметры: Нет Возвращаемое значение: ничего Пример:void loop() { Client client = server.available(); if (client) { server.write(client.

read()); } }

virtual void write(uint8_t); virtual void write(const char *str);

virtual void write(const uint8_t *buf, size_t size);

Описание: Запись данных для передачи подключенному клиенту. Синтаксис:server.write(data);Параметры: data – байт или строка символов Возвращаемое значение: ничего Пример:void loop() { Client client = server.available(); if (client) { server.write(client.read()); } }Т.к. класс Server наследуется от класса Print возможен так же вызов функций

print()
println()

Печатает данные для всех подключённых клиентов. Числа печатаются, как последовательность цифр, в виде ASCII-символов (например, число 123 будет передано как три символа: '1', '2', '3'). Функции println печатают данные с последующим переводом на новую строчку. Синтаксис:server.print(data); server.print(data, BASE); server.

println(); server.println(data); server.println(data, BASE);Параметры: data – данные для печати (char, byte, int, long или строка) BASE (опционально): основание представления числа: BIN -двоичное (основание 2), DEC десятичное (основание 10), OCT — восьмеричное (основание 8), HEX — шестнадцатеричное(основание 16).

Теперь рассмотрим клиентские функции.

Client(uint8_t);
Client(uint8_t *, uint16_t);

Источник: http://robocraft.ru/blog/arduino/203.html

Как использовать Arduino в качестве веб-сервера

“); client.println(“”); client.println(”

A Webserver Tutorial

“); client.println(”

Observing State Of Switch

“); client.print(”

Switch is: “); if (digitalRead(8)) { client.println(”

ON

“); } else { client.println(”

OFF

“); } client.println(“”); client.println(“”);

Эта программа будет отображать веб-страницу в веб-браузере при обращении к IP адресу, присвоенному Arduino. Следующая строка указывает браузеру на необходимость обновления страницы:

client.println(“”);

Когда страница будет запрошена снова, Arduino снова считает состояние кнопки и отобразит его.

Помните, вы всегда может посмотреть исходный код отображаемой веб-страницы. Нажав кнопку, вы может наблюдать изменение состояния кнопки, как показано на видео ниже.

Также вы можете собрать всё без роутера. Для этого необходим перекрестный ethernet кабель. Адрес шлюза в этом случае можно оставить пустым.

Полный текст программы:

#include #include /******************** НАСТРОЙКИ ETHERNET ********************/ byte mac[] = { 0x90, 0xA2, 0xDA, 0x0D, 0x85, 0xD9 };// физический mac адрес byte ip[] = { 192, 168, 0, 112 }; // ip в lan byte subnet[] = { 255, 255, 255, 0 }; // маска подсети byte gateway[] = { 192, 168, 0, 1 }; // шлюз по умолчанию EthernetServer server(80); // порт сервера void setup() { Ethernet.begin(mac,ip,gateway,subnet); // инициализировать Ethernet устройства server.begin(); // начать прослушивание клиентов pinMode(8, INPUT); // входной вывод для кнопки } void loop() { EthernetClient client = server.available(); // искать клиента // послать стандартный заголовок http ответа client.println(“HTTP/1.1 200 OK”); client.println(“Content-Type: text/html”); client.println(“Connnection: close”); client.println(); /* Эта часть – это веб-страница, которая будет послана веб-браузеру клиента, которая может использовать html, javascript и какой-либо другой язык веб-разметки, чтобы скомпоновать конкретную веб-страницу. */ client.println(“”); //web страница создана с помощью html client.println(“”); client.println(“”); client.println(“”); client.println(”

A Webserver Tutorial

“); client.println(”

Observing State Of Switch

“); client.print(”

Switch is: “); if (digitalRead(8)) { client.println(”

ON

“); } else { client.println(”

OFF

“); } client.println(“”); client.println(“”); delay(1); // даем время, чтобы принять данные /* Следующая строка важна, так как она остановит клиента, чтобы при следующей итерации цикла искать новое соединение с помощью EthernetClient client = server.available(); */ client.stop(); }

Оригинал статьи:

  • Editorial Team. How to Use an Arduino as a Web Server

Источник: https://radioprog.ru/post/109

Ethernet Shield и Arduino – основы

Ethernet Shield дает вам возможность подключать Arduino к интернету. Этот шилд расширяет возможности Arduino и позволяет отсылать и принимать данные из любой точки мира, где есть интернет.

Например, можно удаленно управлять вашим роботом с веб-сайта или реализовать какой-то сигнал, когда приходит новое сообщение в ваш твиттер. Ethernet Shield открывает перед вами бесконечное количество новых возможностей.

Ссылки для заказа необходимого оборудования, которое использовалось в статье из Китая

  • КУПИТЬ Ethernet Shield W5100;
  • КУПИТЬ Arduino Uno R3;

Установка Ethernet шилда

Устанавливается все предельно просто. Как и любой другой шилд, Ethernet Shild просто садится коннекторами на Arduino сверху.

Обратите внимание, что некоторые шилды могут быть несовместимы с более ранними версиями Arduino. Так что рекомендуется использовать именно платы Arduino версии Rev 3.

Ethernet Shield основан на чипе W51000, который имеет внутренний буфер на 16К. Скорость подключения достигает 10/100Мб. Это не самое быстрое соединение, но этого вполне достаточно, поверьте.

Шилд работает с использованием библиотеки Arduino Ethernet library, которая по умолчанию интегрирована в оболочку Arduino IDE.

На Ethernet шилде есть слод для установки micro SD карты, с помощью которой можно хранить большие массивы информации и загружать веб-сайты непосредственно с Arduino. Не забудьте, что в этом случае надо использовать дополнительную библиотеку. Более детально про: использование SD карты.

Кроме того, можно запитывать Arduino с помощью Ethernet соединения. Для этого надо использовать Power over Ethernet (PoE) модуль, место для установки есть на Ethernet шилде.

Сводный список технических характеристик Ethernet шилда:

  • Для работы необходима плата Arduino
  • Рабочее питание – 5 В (питается от платы Arduino)
  • Ethernet контроллер: W5100 с буфером 16Kб
  • Скорость подключения: 10/100Мб
  • Подключается к Arduino через SPI порт

Первые шаги

Подключите Arduino к персональному компьютеру с помощью USB кабеля, а Ethernet Shield к вашему роутеру (или непосредственно вашему интернет-кабелю).

После этого откройте Arduino IDE. В версиях Arduino IDE после 1.0 есть встроенная поддержка DHCP и нет необходимости в ручной настройке IP адреса.

Для того, чтобы определить какой IP адрес присвоен вашей плате, откройте скетч DhcpAddressPrinter. Найти его можно в меню:

File –> Examples –> Ethernet –> DhcpAddressPrinter

После открытия скорее всего придется сменить мак-адрес. На более новых официальных версиях Ethernet шилда, адрес указан на стикере, прикрепленном к шилду. Если стикера нет, можно просто сгенерировать новый уникальный мак-адрес. Если вы используете одновременно несколько шилдов, мак-адреса для каждого з них должны быть уникальными.

После настройки мак-адреса, можно загружать скетч на плату Arduino и открывать серийный монитор. В результате должен отобразится используемый IP адрес.

Сервер

Можно использовать Arduino Ethernet shield в качестве веб-сервера для загрузки HTML страницы или функции. Можно отслеживать (парсить) запросы, которые отсылаются клиентом через веб-браузер. В следующих двух примерах показано как использовать наш “пирог” для обслуживания HTML страниц и парсинга URL строк.

Важно помнить: надо внести IP адрес вашей платы Arduino, чтобы приведенные ниже примеры корректно отрабатывали.

Приведенный ниже код изменяет содержимое веб страницы при нажатии кнопки:

/*

Web Server с использованием Ethernet шилда – пример

Простой пример веб-сервера, который изменяет страницу после нажатия кнопки.

Схема подключения

* Ethernet shield подключен к пинам 10, 11, 12, 13

* кнопка подключается между пинами D2 and 5V

* резистор на 10 КОм подключается между пином D2 и землей

*/

#include<\p>

#include<\p>

// ниже необходимо ввести MAC адрес и IP адрес вашего контроллера.

// IP адрес будет зависеть от вашей локальной сети:

byte mac[] = { 0x00, 0xAA, 0xBB, 0xCC, 0xDA, 0x02 };

IPAddress ip(191,11,1,1); //

Источник: http://arduino-diy.com/arduino-ethernet-shield-osnovi

Передача файлов и данных на веб-сервер из 1С методами GET и POST

 +24 

   При интеграции 1С с веб-сайтами всегда встает вопрос о передачи некоторых данных на веб-сервер. Будь то это передача параметров запроса для получения данных от веб-сервера в 1С или же передача данных из 1С, которые должны быть сохранены или каким-то образом обработаны на веб-сервере. Передаваться могут как простые данные в виде строк, чисел, так и целые файлы (изображения, XML-файлы и прочее). Для передачи и получения файлов и данных на веб-сервер в 1С используется объект HTTPСоединение.

Создание и инициализация HTTP соединения в 1С

Для инициализации HTTP соединения в 1С необходимо создать объект HTTPСоединение и в конструкторе указать параметры HTTP соединения. (обязательный) – адрес сервера, с которым необходимо установить соединение.

(необязательный) – порт сервера, с которым устанавливается соединение. Значение по умолчанию зависит от защищенности соединения (80 для незащищенного и 443 для SSL-соединения). (необязательный) – имя пользователя на указанном сервере.

(необязательный) – пароль пользователя на указанном сервере. (необязательный). Тип – ИнтернетПрокси. Прокси, используемый для соединения с сервером. (необязательный). Тип – Булево. Определяет используемый протокол – http или https. По умолчанию Ложь.

Ниже приведен примеры создания HTTPСоединения с сайтом http://www.mysite.ru/.

Передача данных на веб-сервер из 1С методом GET.

Для передачи данных на веб-сервер из 1С методом GET используется процедура Получить() объекта HTTPСоединение. (обязательный). Тип – Строка. Адрес ресурса на сервере. (обязательный). Тип – Строка. Имя файла на диске, в который помещаются данные, полученные от сервера (ответ сервера). (необязательный). Тип – Строка. Заголовки, добавляемые к запросу на сервер.

Текстовые пары вида :, разделенные комбинацией ВК + ПС. (подробнее о заголовках будет сказано ниже). Рассмотрим параметры процедуры Получить() более подробно: В качестве источника указывается строка с адресом запроса, идущая после названия домена и символа “/”. Так, если необходимо отправить данные на адрес https://www.mysite.com/getusers.

php, то при создании HTTP соединения в конструкторе HTTPСоединение в поле “Сервер” указывается “www.mysite.com”, признак защищенного соединения устанавливается в Истина, а в процедуре Получить() в параметре Источник указывается “getUsers.php”.

В поле ИмяВыходногоФайла указывает имя файла на диске, в который будут сохранены данные, полученные от сервере в результате запроса. Так, например, если сервер возвращает список пользователей в формате XML, то на диск в указанный файл будет сохранен XML файл со списком пользователей. О заголовках более подробно будет сказано ниже.

Так же, при запросе к веб-серверу зачастую передаются дополнительные данные (параметры) для этого запроса. Параметры от адреса источника отделяются символом “?”. Каждый параметр задается в формате =. Параметры от адреса источника отделяются символом “?”. Сами же параметры отделяются друг от друга символом “&”.

В результате строка адреса источника может выглядеть следующим образом: getUsers.php?owner_id=263544&count=100. Ниже приведен пример, поясняющий все выше сказанное.

Заголовки HTTP
Ниже приведена общая информация о HTTP заголовках из википедии.

Заголовки HTTP (англ. HTTP Headers) — это строки в HTTP-сообщении, содержащие разделённую двоеточием пару имя-значение. Формат заголовков соответствует общему формату заголовков текстовых сетевых сообщений ARPA. Заголовки должны отделяться от тела сообщения хотя бы одной пустой строкой. Все заголовки разделяются на четыре основных группы: General Headers (рус.

Основные заголовки) — должны включаться в любое сообщение клиента и сервера. Request Headers (рус. Заголовки запроса) — используются только в запросах клиента. Response Headers (рус. Заголовки ответа) — только для ответов от сервера. Entity Headers (рус. Заголовки сущности) — сопровождают каждую сущность сообщения. Именно в таком порядке рекомендуется посылать заголовки получателю.

Более подробно о заголовках HTTP можно прочитать здесь. Так же можно ознакомится со списком заголовков HTTP. От себя лишь добавлю, что, если это явно не указано в требованиях к отправке данных веб-серверу заголовки HTTP для метода GET можно не указывать.

Для метода POST обычно нужно указать заголовки Content-Type (тип передаваемых данных, например: “Content-Type: text/html;charset=utf-8”) и Content-Length (размер передаваемых данных в байтах, например: “Content-Length: 1348”). Напомню, что HTTP заголовки в 1С указываются строкой в виде текстовых пар “:”, разделенных комбинацией символов ВК+ПС.

Также заголовки можно задать типом Соответствие, где в качестве ключа указывается заголовок, а в качестве значения – значение заголовка. Ниже приведены поясняющие примеры:

Передача данных на веб-сервер из 1С методом POST.

Общие сведения. Для передачи данных на веб-сервер из 1С методом POST используется процедура ОтправитьДляОбработки() объекта HTTPСоединение. (обязательный) – Имя файла-источника, который будет отправлен на сервер для обработки. (обязательный). Тип – строка. Адрес ресурса на сервере, в который посылаются данные из источника.

(обязательный) – Имя файла на диске, в который записываются полученные с сервера данные. (необязательный). Тип – строка. Заголовки, добавляемые к запросу на сервер. Текстовые пары вида :, разделенные комбинацией ВК + ПС. (подробнее о заголовках будет сказано ниже).

Рассмотрим параметры процедуры ОтправитьДляОбработки() подробнее: В качестве источника указывается файл, содержимое которого необходимо отправить на сервер для обработки. Подробнее о формировании содержимого файла-источника будет сказано ниже. Поле АдресРесурса аналогично полю Источник процедуры Получить(), т.е.

указывается строка с адресом запроса, идущая после имени домена и символа “/”. Поле ИмяВыходногоФайла также аналогично одноименному полю процедуры Получить(), т.е. содержит имя файла, в котором будут сохранены данные, полученные от сервера в результате обработки исходных данных. О заголовках было упомянуто выше.

Напомню лишь, что для метода POST обычно указываются заголовки Content-Type и Content-Length. В качестве параметра заголовка Content-Length указывается размер файла-источника, преобразованный с помощью функции XMLСтрока(). Ниже приведен пример, поясняющий все выше сказанное.

Передача параметров методом POST.

Для передачи параметров, аналогично методу GET, можно сформировать строку параметров, записать их в текстовый файл и отправить этот файл на сервер для обработки. Ниже приведен пример аналогичный примеру отправки методом GET, но теперь те же данные отправляются методом POST.

Передача файлов методом POST.

Зачастую данные для обработки задаются не виде строки параметров разделенных “&”, как в рассматриваемых выше примерах, а виде файла определенного формата, например XML или JSON. Рассмотрим пример отправки данных на веб-сервер для обработки методом POST, которые задаются в формате XML.

Например, сервер может добавить ваш комментарий к материалу. В описании процедуры добавлении сказано, что данные необходимо отправлять по адресу www.mysite.com/addComment.php.

Сами данные должны быть переданы в следующем виде: где: – id пользователя на сайте, от имени которого добавляется комментарий; – id материала на сайте, к которому добавляется комментарий; – текст комментария.

Предположим, что нам уже известны id пользователя и материала и они хранятся в переменных user_id и post_id. Ниже приведен пример, решающий нашу задачу.

Загрузка файлов (изображений, документов и т.п.) на веб-сервер методом POST.

Зачастую возникает необходимость загрузки файлов на веб-сервер. Это может быть, например, изображение к статье на сайте, или фотография для альбома, или архив для файлообменника. Ранее мы рассматривали передачу методом POST параметров или просто файлов. Таким же образом можно и передавать двоичные файлы.

Но как быть, если файлы необходимо отправлять вместе с параметрами? Для возможности отправки файлов в этом случае используется HTTP заголовок ContentType:multipart/form-data. Следует заметить, что обычно таким способом передаются файлы через веб-браузеры. Т.е.

когда на сайте вы выбираете файл и нажимаете кнопку “Загрузить”, то файл передается способом описанным ниже. При таком способе сам файл также задается как переменная, т.е., например, файл передается через параметр file или image. Однако, мы не можем просто передать file=. А вот как все таки передать файл мы и рассмотрим ниже.

Для возможности вместе с параметрами передавать и двоичные данные (файлы) необходимо сформировать HTTP заголовок Content-Type следующим образом: Content-Type: multipart/form-data, boundary= где – это любой набор цифр и/или символов, который будет служить для отделения значений друг от друга.

Значение boundary должно быть уникальным в пределах пересылаемой информации, т.е. таких символов не должно встречаться в пересылаемых файлах и переменных. Bounday можно сформировать, например, таким образом Все данные отделяются друг от друга разделителем boundary.

Начинать разделитель нужно с “–“: В конце данных нужно закрыть разделитель, добавили в конце разделителя “–“, т.е. вид будет “—-“. Итак, например, нам нужно передать на веб-сервер текстовый файл через параметр “text”, его описание через параметр “desc” и id пользователя через параметр “uid”, для которого будет загружен наш файл.

Предположим, что файл содержит следующий текст:

Мороз и солнце; день чудесный! Еще ты дремлешь, друг прелестный – Пора, красавица, проснись: Открой сомкнуты негой взоры Навстречу северной Авроры,

Звездою севера явись!

Источник: https://helpf.pro/faq/view/1298

Мониторинг температуры через интернет. Урок 3. | LAZY SMART

В предыдущем уроке мы собрали устройство, которое будет измерять температуру и передавать эту информацию на сервер. Теперь мы переходим к разбору алгоритма работы управляющего контроллера, его взаимодействию с другими узлами передающего устройства. Этот урок будет посвящён теоретическому разбору программы контроллера, без рассмотрения самого кода.

Некоторым читателям может показаться, что теория без практики слишком скучна. В этом случае можете переходить сразу к следующему уроку, «залить» программу в контроллер и испробовать его в работе, а потом вернутся сюда и изучить теорию.

Алгоритм работы передающего устройства

На представленной ниже диаграмме последовательности показан общий алгоритм работы передающего устройства:

Рис. 1. Общий алгоритм работы передающего устройства

После  включения устройства контроллер производит начальную инициализацию всех программных структур и переменных. Затем он посылает модему последовательности команд, выполняя которые, SIM900 сначала подключается к GPRS, а после открывает встроенный HTTP-сервис.

Все последующие инструкции программы выполняются в бесконечном цикле:

  • Контроллер даёт модему команду «Отправить запрос на сервер» и указывает содержание запроса. Модем посылает запрос и ждёт ответ от сервера.
  • После того, как ответ от сервера получен, модем передаёт его контроллеру.
  • В ответе от сервера, кроме служебной информации, содержится текущая команда для выходного реле. Контроллер принимает эту команду и выполняет её.
  • Далее контроллер производит цифровой обмен с термодатчиком и получает от него текущее значение температуры.
  • Если параметры системы (состояние выходного реле или температура) изменились по сравнению с предыдущим кругом цикла, контроллер передаст эти параметры в следующем запросе на сервер.

Настройка COM-порта Arduino

Обмен контроллера и модема происходит через последовательный порт.

Рис. 2. Соединение контроллера и модема через последовательный порт

Заводские настройки порта модема следующие:

  • Скорость обмена: 19200 бит/с
  • 8 бит данных
  • Проверка чётности : нет
  • 1 стоп-бит

Подключение SIM900 к GPRS

Для того чтобы модем выполнил подключение к интернету по GPRS, контроллер посылает ему следующие команды:

Команда Описание
1 AT+SAPBR=3,1,“CONTYPE“,“GPRS“ Тип подключения : GPRS
2 AT+SAPBR=3,1,“APN“,“internet“ Точка доступа (APN). Для большинства операторов подходит “internet“ (в противном случае нужно запросить APN у Вашего оператора)
3 AT+SAPBR=1,1 Выполнить подключение

Таб. 1. Команды для подключения модема к GPRS

Если команда выполнена успешно, модем отвечает «ОК», в противном случае – «ERROR».

Инициализация HTTP-сервиса SIM900

Модем SIM900 имеет реализованный его внутренней логикой протокол HTTP. Это «своеобразный браузер», встроенный в чип модема. Пользователю остаётся  инициализировать его, после чего можно передавать через него GET- и POST-запросы, так же, как это происходит в обычном браузере.

Для инициализации HTTP-сокета, контроллер посылает модему следующие команды:

Команда Описание
1 AT+HTTPINIT Инициализация HTTP сервиса
2 AT+HTTPPARA=“CID“,1 Установка CID параметра для HTTP сессии оператора.

Таб. 2. Команды для инициализации HTTP

Если команда выполнена успешно, модем отвечает «ОК», в противном случае – «ERROR».

Отправка GET-запроса на сервер

Для реализации обмена данными с сервером используются GET-запросы  (один из типов запроса стандарта HTTP).

GET-запрос имеет следующий вид:

«GET /device_status.php?LOG= 1111&PAS=2222 HTTP/1.1»
«HOST: t.lazysmart.ru»

В запросе:

  • «GET» – тип запроса
  • «/device_status.php» – URI (путь к запрашиваемому скрипту на сервере)
  • После знака «?» идут передаваемые на сервер параметры и их значения. В данном примере параметры LOG и PAS – это логин и пароль для авторизации устройства на сервере. Эти параметры присваиваются устройству при его регистрации на сервере и не могут быть изменены. Посмотреть их можно через веб-приложение LS Cloud по адресу t.lazysmart.ru в меню «Настройки» этого устройства. В процессе работы устройства в запрос могут добавляться другие параметры, отражающие состояние системы (текущую температуру и состояние выходного реле).
  • «HTTP/1.1» — версия протокола
  • «HOST:…» — адрес сервера, к которому адресован запрос

Этот же запрос можно выразить в виде URL:

«http://t.lazysmart.ru /device_status.php?LOG=1111&PAS=2222»

Чтобы передать температуру на сервер, контроллер добавляет к запросу параметр «BT», а для передачи состояния выходного реле параметр «CSt». BT содержит значение температуры, умноженное на 10, а CSt принимает значение 0 или 1, где 0 – реле выключено, а 1 – включено.

Например, в запросе  «http://t.lazysmart.ru/device_status.php?LOG=1111&PAS=2222&BT=127&CSt=1»  передаваемые параметры означают, что температура равна 12,7 °С, а реле включено.

Передача запроса на сервер

Для отправки запроса на сервер, контроллер посылает модему следующие команды:

Команда Описание
1 AT+HTTPPARA=“URL“,“http:// t.lazysmart.ru /device_status.php?LOG=1111&PAS=2222“ Указание содержание запроса
2 AT+HTTPACTION=0 Старт обмена даннымиПараметр, метод запроса: 0 – GET 1 – POST2 – HEAD

Таб. 3. Команды для передачи запроса на сервер

Если команда выполнена успешно, модем отвечает «ОК», в противном случае – «ERROR».

Получение ответа от сервера

Как только ответ от сервера получен, модем посылает контроллеру строку вида:

+HTTPACTION:0,200,   ,

где  0 – тип запроса GET, 200 – код успешного ответа,    — количество полученных байт.

Если код ответа не 200 – значит, при передаче запроса произошла ошибка.

Если от сервера получен «успешный» ответ, контроллер посылает модему команду «AT+HTTPREAD». В ответ на эту команду модем начинает передавать контроллеру содержание ответа сервера.

Ответ от сервера состоит из заголовков, содержащих служебную информацию, и тела ответа.

Тело представляет собой строку вида:

“COMMAND EOC”,

где   — команда для выходного реле (1 – включить, 0 – выключить).

Анализ состояния системы

После того, как команда для реле от сервера получена, контроллер выполняет её. Если команда реле поменялась,  — контроллер добавляет к новому запросу на сервер соответствующий параметр (см. «GET-запрос»). Благодаря этому сервер получит подтверждение о том, что устройство получило и выполнило команду.

Затем контроллер производит информационный обмен с датчиком температуры DS18B20. Если температура изменилась – эта информация также добавляется в новый запрос на сервер.

Алгоритм «выживания»

Алгоритм выживания используется для предотвращения непредвиденных ситуаций в обмене с модемом.

Сбои в программной логике модема, «мусор» полученный от сети и другие ситуации — могут привести к зависанию модема или его неадекватной работе.

Применяется простейший алгоритм «выживания» в таких ситуациях: если в течение трёх минут от сервера не получено никаких полезных данных – контроллер перезагружает модем.

Предотвращение зависания

Для предотвращения зависания контроллера в самом начале программы инициализируется сторожевой таймер. Этот таймер должен быть сброшен программно, раньше, чем он переполнится. Для этого на каждом цикле программы выполняется оператор его сброса. При зависании программы таймер не будет сброшен и произойдёт аппаратная перезагрузка контроллера.

Облачный сервис для мониторинга «LS Cloud»

Данные, передаваемые устройством на сервер, сохраняются в базе данных и доступны пользователю через веб-приложение “LS Cloud” по адресу  t.lazysmart.ru.

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

Основные элементы интерфейса приложения показаны на рисунках 3 и 4.

Рис. 3. Экран мониторинга основных параметров устройства

На экране мониторинга основных параметров устройства (рис. 3) отображается информация о текущей температуре, а так же исторические данные о температуре за весь период работы устройства. Панель «Реле» позволяет управлять выходным реле устройства, а в «Журнал» заносятся события, происходящие с устройством.

Рис. 4. Экран настроек прибора

На экране настроек прибора (рис. 4) можно изменить основные настройки прибора:

  • Имя
  • Верхний предупредительный (тревожный) порог температуры – при его превышении генерируется тревожное событие в журнал.
  • Верхний аварийный порог температуры – при его превышении генерируется аварийное событие в журнал.
  • Нижний предупредительный (тревожный) порог температуры – если температура опустится ниже него, будет сгенерировано тревожное событие в журнал.
  • Верхний аварийный порог температуры – если температура опустится ниже него, будет сгенерировано аварийное событие в журнал.
  • Таймаут (задаётся в секундах) – если в течение этого времени устройство ни разу не вышло на связь, генерируется событие «потеря связи с устройством».
  • Оповещение при тревоге — при активации этой настройки пользователь будет получать сообщения о тревожных событиях по email и SMS.
  • Оповещение при тревоге — при активации этой настройки пользователь будет получать сообщения о тревожных событиях по email и SMS.
  • Оповещение при обрывах связи с устройством — при активации этой настройки пользователь будет получать сообщения о событиях обрыва связи с устройством по email и SMS.

Заключение

На этом мы заканчиваем третий урок! Надеемся, что он был полезен! В следующем уроке мы прошьём программу в контроллер и запустим устройство. До скорой встречи на LAZY SMART

Источник: http://lazysmart.ru/avtomatika-v-by-tu/monitoring-temperatury-cherez-internet-s-pomoshh-yu-gsm-modulya-sim900-urok-4/

Простое управление arduino через интернет

Всем добрый день.

Около года назад я написал небольшую обзорную статью для управления Arduino через интернет, с помощью сервера NinjaBlocks.

Это было довольно хорошее и удобное решение и оно отлично работало, пока в один прекрасный момент не начались проблемы с соединением.

Попытки уговорить разработчиков через форум решить проблемы были напрасны — они просто игнорировали мои просьбы и не удосужились даже ответить, что было очень печально.

С того момента был просканирован весь интернет в поисках замены — и было найдено много очень интересных проектов, но они либо были слишком сложными в реализации и требовали значительных знаний в области программирования, либо были попросту неудобны.

И вот тут и пришла мысль почему бы не сделать все самому.

Конечно очень хотелось использовать современные протоколы передачи данных websockets или mqtt, которые позволили бы контролировать все процессы в реальном времени, но если с клиентом для arduino дела обстояли хорошо — наличие неплохих библиотек радовало, то вот с серверной стороной дела обстояли хуже — нужны были серверы с поддержкой нужных протоколов, которых у обычного хостера не было. А заводить свой сервер ради зажигания светодиода не хотелось. И выбор пал на старый и добрый http.

1. Как это всё работает.

У нас имеется: — сервер на php расположенный на хостинге который привязаный к доменному имени — клиент в виде arduino

— панель управления

Arduino подключается к серверу и отправляет GET запрос, где содержатся значения датчиков температуры.

Сервер принимает запрос, и записывает значения температур в текстовые файлы. При этом читает из текстового файла значение установленного выхода для arduino и отправляет в ответ на запрос контроллера.

Arduino принимает ответ от сервера и согласно ему устанавливает состояние своего выхода

Панель управления, используя Ajax, считывает значение температуры из текстовых файлов и обновляет показания датчиков. А также считывает их текстового файла состояние выхода и обновляет его на странице. С помощью того же Ajax через форму в текстовый файл записывается значение выхода контроллера, откуда потом будет брать значение сервер и отправлять контроллеру.

2. Клиент на Arduino

Скетч довольно простой всё что он делает это собирает значение датчиков и отправляет их на сервер, получает ответ, влючает или отключает выход.

Скетч Arduino#include #include #include

#include

#define ONE_WIRE_BUS 2 OneWire oneWire(ONE_WIRE_BUS);

DallasTemperature sensors(&oneWire);

byte mac[] = { 0x54, 0x34, 0x41, 0x30, 0x30, 0x31 };

EthernetClient client; char server[] = “*************”; // имя вашего сервера int buff=0;

const int led=5;

void setup() { Ethernet.begin(mac); sensors.begin(); pinMode( led, OUTPUT); digitalWrite(led, LOW);

}

void loop()
{

sensors.requestTemperatures();

if (client.connect(server, 80))
{

client.print( «GET /add_data.php?»); client.print(«temperature=»); client.print( sensors.getTempCByIndex(0) ); client.print(“&”); client.print(“&”); client.print(«temperature1=»); client.print( sensors.getTempCByIndex(1) ); client.println( ” HTTP/1.1″); client.print( «Host: » ); client.println(server); client.println( «Connection: close» ); client.println();

client.println();

delay(200);

while (client.available()) { char c = client.read(); if ( c=='1') { buff=1; } if ( c=='0') { buff=0; } } client.stop(); client.flush(); delay(100); } else { client.stop(); delay(1000); client.connect(server, 80);

}

if ( buff==1) { digitalWrite (led1, HIGH); } else { digitalWrite(led1, LOW); } delay(500); }

3. Сервер и панель управления

Сервер состоит всего из нескольких файлов:

index.php — панель управления
add_data.php — файл обрабатывающий запросы с контроллера и отсылающий ответ обратно на arduino
style.

css — определяет внешний вид панели
Папка transfer — содержит файлы с помощью котрых происходит считывание и запись значений из текстовых файлов.
led.php — записывает состояние выхода в файл out-1.

txt, отправленное через форму в панели управления
ledstate.php — считывает состояние из текстового файла out-1.txt и выводит на пенели в виде «ON» или «OFF»
temp-1.php и temp-2.php — считывают значения температуры из файлов in-1.txt и in-2.

txt и отправляют на панель управления.
Папка txt — своего рода база данных для хранения информации.

Сервер на самом деле очень простой и его сможет установить себе любой человек с минимальными познаниями, например, как я. До работы над этим проектом у меня был опыт работы только с arduino поэтому php, ajax, html и css пришлось изучать, буквально с нуля.

Установка очень простая. Просто скопируйте файлы на сервер и загрузите скетч в контроллер, при этом в скетче подправьте доменное имя, подключите датчики и светодиод и у вас все должно работать.

Уверен, что матерые программисты будут пинать меня и тыкать носом в те места где можно было бы написать код более лаконично и правильно. Я это только приветствую!!!
Если вы увидели, что некоторые вещи можно сделать проще и быстрее, то сообщите мне.

Что в итоге мы имеем?

Плюсы: — все просто и понятно — можно настроить под свои нужды и задачи — хорошая стабильность

— сервер можно развернуть на любом бесплатном хостинге

Минусы: — большое количество запросов на сервер ( некоторым хостерам это может не понравиться, в этом случае нужно увеличить паузу между запросами в скетче) — кушает много трафика со стороны клиента ( при 1 запросе в секунду выходит около 300 Мб в сутки)

— существует небольшая задержка на включение выходов ( может быть критично для некоторых случаев)

Планы на будущее: — добавить кнопку на контролере для влючения и выключения реле с изменением состояния на сервер — добавить авторизацию — добавить идентификационные ключи в запросах — организовать работу нескольких плат одновременно с одной панелью управления — добавить подтверждения от контроллера о включении выхода

— очень хотелось бы использовать протоколо websockets или mqtt, но всё же склоняюсь к использованию websockets c использованием socket.io

Возможно, если будет интересно, напишу статью об управлении через интернет wifi модулем esp8266. Его я уже успел успешно опробовать и убедился что все работает, правда там есть свои нюансы в работе.

А если наберется достаточное количество желающих напишу будет подробная статья, где мы рассмотрим добавление новых блоков с датчиками и управлением дополнительными выходами в панель управления.

Прошу дать совет как лучше реализовать авторизацию в панели управления что бы была относительно простая и понятная установка и приемлемый уровень безопасности.

Все желающие могут сами посетить страницу моего сервера и проверить в действии arduino.zhodinovel.com
!!! Для изменения выхода контроллера поставьте маркер на нужное значение и нажмите «ОТПРАВИТЬ» !!!

Смотрим видео

Качаем файлы
1. Сервер
2. Скетч для arduino

Всем спасибо за внимание!

UPD. Добавил обратную связь в панель в виде фоторезистора. Когда лампочка выключена показания около 130, когда включена — 900.

This entry passed through the Full-Text RSS service – if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.

Источник: http://habrparser.blogspot.com/2015/05/arduino.html

Ссылка на основную публикацию
Adblock
detector
",css:{backgroundColor:"#000",opacity:.6}},container:{block:void 0,tpl:"
"},wrap:void 0,body:void 0,errors:{tpl:"
",autoclose_delay:2e3,ajax_unsuccessful_load:"Error"},openEffect:{type:"fade",speed:400},closeEffect:{type:"fade",speed:400},beforeOpen:n.noop,afterOpen:n.noop,beforeClose:n.noop,afterClose:n.noop,afterLoading:n.noop,afterLoadingOnShow:n.noop,errorLoading:n.noop},o=0,p=n([]),h={isEventOut:function(a,b){var c=!0;return n(a).each(function(){n(b.target).get(0)==n(this).get(0)&&(c=!1),0==n(b.target).closest("HTML",n(this).get(0)).length&&(c=!1)}),c}},q={getParentEl:function(a){var b=n(a);return b.data("arcticmodal")?b:(b=n(a).closest(".arcticmodal-container").data("arcticmodalParentEl"),!!b&&b)},transition:function(a,b,c,d){switch(d=null==d?n.noop:d,c.type){case"fade":"show"==b?a.fadeIn(c.speed,d):a.fadeOut(c.speed,d);break;case"none":"show"==b?a.show():a.hide(),d();}},prepare_body:function(a,b){n(".arcticmodal-close",a.body).unbind("click.arcticmodal").bind("click.arcticmodal",function(){return b.arcticmodal("close"),!1})},init_el:function(d,a){var b=d.data("arcticmodal");if(!b){if(b=a,o++,b.modalID=o,b.overlay.block=n(b.overlay.tpl),b.overlay.block.css(b.overlay.css),b.container.block=n(b.container.tpl),b.body=n(".arcticmodal-container_i2",b.container.block),a.clone?b.body.html(d.clone(!0)):(d.before("
"),b.body.html(d)),q.prepare_body(b,d),b.closeOnOverlayClick&&b.overlay.block.add(b.container.block).click(function(a){h.isEventOut(n(">*",b.body),a)&&d.arcticmodal("close")}),b.container.block.data("arcticmodalParentEl",d),d.data("arcticmodal",b),p=n.merge(p,d),n.proxy(e.show,d)(),"html"==b.type)return d;if(null!=b.ajax.beforeSend){var c=b.ajax.beforeSend;delete b.ajax.beforeSend}if(null!=b.ajax.success){var f=b.ajax.success;delete b.ajax.success}if(null!=b.ajax.error){var g=b.ajax.error;delete b.ajax.error}var j=n.extend(!0,{url:b.url,beforeSend:function(){null==c?b.body.html("
"):c(b,d)},success:function(c){d.trigger("afterLoading"),b.afterLoading(b,d,c),null==f?b.body.html(c):f(b,d,c),q.prepare_body(b,d),d.trigger("afterLoadingOnShow"),b.afterLoadingOnShow(b,d,c)},error:function(){d.trigger("errorLoading"),b.errorLoading(b,d),null==g?(b.body.html(b.errors.tpl),n(".arcticmodal-error",b.body).html(b.errors.ajax_unsuccessful_load),n(".arcticmodal-close",b.body).click(function(){return d.arcticmodal("close"),!1}),b.errors.autoclose_delay&&setTimeout(function(){d.arcticmodal("close")},b.errors.autoclose_delay)):g(b,d)}},b.ajax);b.ajax_request=n.ajax(j),d.data("arcticmodal",b)}},init:function(b){if(b=n.extend(!0,{},a,b),!n.isFunction(this))return this.each(function(){q.init_el(n(this),n.extend(!0,{},b))});if(null==b)return void n.error("jquery.arcticmodal: Uncorrect parameters");if(""==b.type)return void n.error("jquery.arcticmodal: Don't set parameter \"type\"");switch(b.type){case"html":if(""==b.content)return void n.error("jquery.arcticmodal: Don't set parameter \"content\"");var e=b.content;return b.content="",q.init_el(n(e),b);case"ajax":return""==b.url?void n.error("jquery.arcticmodal: Don't set parameter \"url\""):q.init_el(n("
"),b);}}},e={show:function(){var a=q.getParentEl(this);if(!1===a)return void n.error("jquery.arcticmodal: Uncorrect call");var b=a.data("arcticmodal");if(b.overlay.block.hide(),b.container.block.hide(),n("BODY").append(b.overlay.block),n("BODY").append(b.container.block),b.beforeOpen(b,a),a.trigger("beforeOpen"),"hidden"!=b.wrap.css("overflow")){b.wrap.data("arcticmodalOverflow",b.wrap.css("overflow"));var c=b.wrap.outerWidth(!0);b.wrap.css("overflow","hidden");var d=b.wrap.outerWidth(!0);d!=c&&b.wrap.css("marginRight",d-c+"px")}return p.not(a).each(function(){var a=n(this).data("arcticmodal");a.overlay.block.hide()}),q.transition(b.overlay.block,"show",1*")),b.overlay.block.remove(),b.container.block.remove(),a.data("arcticmodal",null),n(".arcticmodal-container").length||(b.wrap.data("arcticmodalOverflow")&&b.wrap.css("overflow",b.wrap.data("arcticmodalOverflow")),b.wrap.css("marginRight",0))}),"ajax"==b.type&&b.ajax_request.abort(),p=p.not(a))})},setDefault:function(b){n.extend(!0,a,b)}};n(function(){a.wrap=n(document.all&&!document.querySelector?"html":"body")}),n(document).bind("keyup.arcticmodal",function(d){var a=p.last();if(a.length){var b=a.data("arcticmodal");b.closeOnEsc&&27===d.keyCode&&a.arcticmodal("close")}}),n.arcticmodal=n.fn.arcticmodal=function(a){return e[a]?e[a].apply(this,Array.prototype.slice.call(arguments,1)):"object"!=typeof a&&a?void n.error("jquery.arcticmodal: Method "+a+" does not exist"):q.init.apply(this,arguments)}}(jQuery)}var debugMode="undefined"!=typeof debugFlatPM&&debugFlatPM,duplicateMode="undefined"!=typeof duplicateFlatPM&&duplicateFlatPM,countMode="undefined"!=typeof countFlatPM&&countFlatPM;document["wri"+"te"]=function(a){let b=document.createElement("div");jQuery(document.currentScript).after(b),flatPM_setHTML(b,a),jQuery(b).contents().unwrap()};function flatPM_sticky(c,d,e=0){function f(){if(null==a){let b=getComputedStyle(g,""),c="";for(let a=0;a=b.top-h?b.top-h{const d=c.split("=");return d[0]===a?decodeURIComponent(d[1]):b},""),c=""==b?void 0:b;return c}function flatPM_testCookie(){let a="test_56445";try{return localStorage.setItem(a,a),localStorage.removeItem(a),!0}catch(a){return!1}}function flatPM_grep(a,b,c){return jQuery.grep(a,(a,d)=>c?d==b:0==(d+1)%b)}function flatPM_random(a,b){return Math.floor(Math.random()*(b-a+1))+a}