image

В этой статье я опишу ситуацию с которой столкнулся во время разработки своего проекта Arduino Mega Server. Суть дела заключается в том, что существует такая библиотека Arduino Ethernet Library, написанная для поддержки сетевой платы Ethernet Shield на чипе W5100. Это стандартная плата и стандартная библиотека, которая многие годы поставляется в комплекте со средой разработки Arduino.

И эта библиотека является основой для всех проектов, использующих обмен информацией по проводной сети. Так вот, оказалось, что эта библиотека попросту профнепригодна. На ней в принципе невозможно построить нормальное сетевое взаимодействие. Можно только «баловаться» одиночными запросами и ответами. Ни о каком построении серверов на базе этой библиотеки речь не может идти. Почему?

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

Тут нужно понимать, что библиотека, поставляемая с официальной средой разработки является неким стандартом и если у вас не работает проект, то вы будете искать дефект где угодно, только не в стандартной библиотеке, ведь ей много лет и ею пользуются сотни тысяч, если не миллионы людей. Не могут же они все ошибаться?

Почему в природе не существует серверов на Arduino


Разработка проекта шла своим чередом и дело, наконец, дошло до оптимизации кода и увеличения скорости работы сервера и тут я столкнулся с такой ситуацией: приходящие запросы от браузера принимались и «подвешивались» на время от трёх до десяти секунд, в среднем и до двадцати и более секунд при более интенсивном обмене. Вот скриншот, на котором видно, что аномальная задержка ответов сервера «гуляет» по различным запросам.

аномальная задержка

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

Подобные наблюдения повергли меня в глубокую задумчивость и я перекопал весь код сервера (заодно размялся) но дефектов не обнаружил и вся логика вела к «святая святых» библиотеке Arduino Ethernet Library. Но крамольную мысль, что виновата стандартная библиотека я отбрасывал, как неадекватную. Ведь с библиотекой работают не только пользователи, но и огромное количество профессиональных разработчиков. Не могут же они все не видеть столь очевидных вещей?

Забегая вперёд, скажу, что когда выяснилось, что дело именно в стандартной библиотеке, стало понятно почему в природе не существует (нормальных) серверов на Arduino. Потому, что на базе стандартной библиотеки (с которой работает большинство разработчиков) построить сервер в принципе невозможно. Задержка ответа в десять секунд и более выводит сервер из категории собственно серверов и делает его просто (тормозной) игрушкой.

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

Анатомия проблемы


Теперь от лирики давайте перейдём к техническому описанию проблемы и её практическому решению. Для тех, кто не в курсе, стандартное место расположения библиотеки (в Windows):

arduino\libraries\Ethernet

И первое, что мы рассмотрим, это функция из файла EthernetServer.cpp

EthernetClient EthernetServer::available() {
  accept();

  for (int sock = 0; sock < MAX_SOCK_NUM; sock++) {
    EthernetClient client(sock);
    if (EthernetClass::_server_port[sock] == _port &&
        (client.status() == SnSR::ESTABLISHED ||
         client.status() == SnSR::CLOSE_WAIT)) {
      if (client.available()) {
        // XXX: don't always pick the lowest numbered socket.
        return client;
      }
    }
  }
  return EthernetClient(MAX_SOCK_NUM);
}

Когда я преодолел психологический барьер (под давлением логики) и начал искать дефект в Ethernet Library я начал именно с этой функции. Заметил я и странный комментарий автора, но не придал ему значения. Перелопатив всю библиотеку, я опять, но уже через пару дней и сильно продвинувшись в сетевых технологиях, вернулся к этой функции потому, что логика подсказывала, что проблема именно здесь и более внимательно посмотрел на комментарий.


        // XXX: don't always pick the lowest numbered socket.


Друзья, там всё написано открытым текстом. В вольном переводе это звучит примерно так «это работает, но не всегда». Подождите минуточку, что значит «не всегда»? У нас же не воскресный клуб по игре в лото. А когда не работает, то что? А вот когда «не работает» и начинаются проблемы с задержкой в десять секунд.

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

Для тех, кто плохо разбирается в коде поясню суть проблемы простыми словами. Цикл перебирает сокеты и, как только находит подходящий, возвращает клиента, а остальных просто игнорирует. И они висят по десять секунд, пока «карты благоприятно не лягут».

Решение проблемы


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

  • запросы не будут зависать
  • «последовательные» запросы превратятся в «параллельные», что значительно ускорит работу

Итак, код новой функции:

EthernetClient EthernetServer::available_(int sock) {
  accept_(sock);
  EthernetClient client(sock);
  if (EthernetClass::_server_port[sock] == _port &&
      (client.status() == SnSR::ESTABLISHED ||
       client.status() == SnSR::CLOSE_WAIT)) {
    if (client.available()) {
      return client;
    }
  }
  return EthernetClient(MAX_SOCK_NUM);
}

Убираем цикл, явным образом указываем сокет и ничего не теряем — если он свободен, то мы гарантированно получаем клиента (если он нам подходит).

То же самое «по цепочке» проделываем с кодом функции accept, убираем цикл и явно указываем сокет.

void EthernetServer::accept_(int sock) {
  int listening = 0;
  EthernetClient client(sock);

  if (EthernetClass::_server_port[sock] == _port) {
    if (client.status() == SnSR::LISTEN) {
      listening = 1;
    } 
    else if (client.status() == SnSR::CLOSE_WAIT && !client.available()) {
      client.stop();
    }
  } 

  if (!listening) {
    //begin();
    begin_(sock); // added
  }
}

И не забываем поправить файл EthernetServer.h

class EthernetServer : 
public Server {
private:
  uint16_t _port;
  //void accept();
  void accept_(int sock);
public:
  EthernetServer(uint16_t);
  //EthernetClient available();
  EthernetClient available_(int sock);
  virtual void begin();
  virtual void begin_(int sock);
  virtual size_t write(uint8_t);
  virtual size_t write(const uint8_t *buf, size_t size);
  using Print::write;
};

Вот, собственно и всё. Мы внесли изменения в стандартную библиотеку и поведение сервера кардинально изменилось. Если раньше всё работало очень медленно, за гранью любых представление о юзабилити, то теперь скорость загрузки страниц значительно возросла и стала вполне приемлемой для нормального использования.

скорость загрузки возрасла

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

Полный код изменённого EthernetServer.cpp
/*
Mod for Arduino Mega Server project
fix bug delay answer server
*/

#include «w5100.h»
#include «socket.h»
extern «C» {
#include «string.h»
}

#include «Ethernet.h»
#include «EthernetClient.h»
#include «EthernetServer.h»

EthernetServer::EthernetServer(uint16_t port) {
_port = port;
}

void EthernetServer::begin() {
for (int sock = 0; sock < MAX_SOCK_NUM; sock++) {
EthernetClient client(sock);
if (client.status() == SnSR::CLOSED) {
socket(sock, SnMR::TCP, _port, 0);
listen(sock);
EthernetClass::_server_port[sock] = _port;
break;
}
}
}

void EthernetServer::begin_(int sock) {
EthernetClient client(sock);
if (client.status() == SnSR::CLOSED) {
socket(sock, SnMR::TCP, _port, 0);
listen(sock);
EthernetClass::_server_port[sock] = _port;
}
}

/*

void EthernetServer::accept() {
int listening = 0;

for (int sock = 0; sock < MAX_SOCK_NUM; sock++) {
EthernetClient client(sock);

if (EthernetClass::_server_port[sock] == _port) {
if (client.status() == SnSR::LISTEN) {
listening = 1;
}
else if (client.status() == SnSR::CLOSE_WAIT && !client.available()) {
client.stop();
}
}
}

if (!listening) {
begin();
}
}

*/

void EthernetServer::accept_(int sock) {
int listening = 0;
EthernetClient client(sock);

if (EthernetClass::_server_port[sock] == _port) {
if (client.status() == SnSR::LISTEN) {
listening = 1;
}
else if (client.status() == SnSR::CLOSE_WAIT && !client.available()) {
client.stop();
}
}

if (!listening) {
//begin();
begin_(sock); // added
}
}

/*

EthernetClient EthernetServer::available() {
accept();

for (int sock = 0; sock < MAX_SOCK_NUM; sock++) {
EthernetClient client(sock);
if (EthernetClass::_server_port[sock] == _port &&
(client.status() == SnSR::ESTABLISHED ||
client.status() == SnSR::CLOSE_WAIT)) {
if (client.available()) {
// XXX: don't always pick the lowest numbered socket.
return client;
}
}
}
return EthernetClient(MAX_SOCK_NUM);
}

*/

EthernetClient EthernetServer::available_(int sock) {
accept_(sock);
EthernetClient client(sock);
if (EthernetClass::_server_port[sock] == _port &&
(client.status() == SnSR::ESTABLISHED ||
client.status() == SnSR::CLOSE_WAIT)) {
if (client.available()) {
return client;
}
}
return EthernetClient(MAX_SOCK_NUM);
}

size_t EthernetServer::write(uint8_t b) {
return write(&b, 1);
}

size_t EthernetServer::write(const uint8_t *buffer, size_t size) {
size_t n = 0;
//accept();

for (int sock = 0; sock < MAX_SOCK_NUM; sock++) {
accept_(sock); // added
EthernetClient client(sock);

if (EthernetClass::_server_port[sock] == _port &&
client.status() == SnSR::ESTABLISHED) {
n += client.write(buffer, size);
}
}
return n;
}

Полный код изменённого EthernetServer.h
/*
Mod for Arduino Mega Server project
fix bug delay answer server
*/

#ifndef ethernetserver_h
#define ethernetserver_h

#include «Server.h»

class EthernetClient;

class EthernetServer:
public Server {
private:
uint16_t _port;
//void accept();
void accept_(int sock);
public:
EthernetServer(uint16_t);
//EthernetClient available();
EthernetClient available_(int sock);
virtual void begin();
virtual void begin_(int sock);
virtual size_t write(uint8_t);
virtual size_t write(const uint8_t *buf, size_t size);
using Print::write;
};

#endif



Оставшиеся проблемы


В таком виде сервер из демонстрации идеи переходит в категорию вещей, которыми можно пользоваться в повседневной жизни, но остались некоторые проблемы. Как вы видите на скриншоте ещё присутствует не принципиальная, но неприятная задержка в три секунды, которой не должно быть. Библиотека написана так, что мест, где код работает не так, как нужно, очень много и если вы квалифицированный разработчик, то ваша помощь в установлении причины трёхсекундной задержки будет очень ценной. И для проекта Arduino Mega Server и для всех пользователей Arduino.

Последний момент


Поскольку мы изменили код стандартной библиотеки, то и вызывать её функции нужно несколько иным способом. Здесь я привожу код, который реально работает и который обеспечивал работу AMS на скриншоте выше.

  for (int sock = 0; sock < MAX_SOCK_NUM; sock++) {
    EthernetClient sclient = server.available_(sock);
    serverWorks2(sclient);
  }

Здесь задача перебора сокетов перенесена на уровень клиентского скетча и, что самое главное, и в чём смысл всего вышесказанного, не происходит «подвисания» запросов. И функция собственно сервера:

void serverWorks2(EthernetClient sclient) {
...
}

С полным кодом сервера вы можете ознакомиться на сайте MajorDoMo, где на форуме можно скачать последнюю актуальную версию Arduino Mega Server. Осталось решить последнюю проблему трёхсекундной задержки и у нас будет настоящий, быстро работающий сервер на Ардуино. Кстати, скоро выйдет новая версия AMS со всеми исправлениями и улучшениями в которой решена одна из самых актуальных проблем — автономная работа без поддержки сервера MajorDoMo.

Arduino Mega Server

И возможным это стало во многом благодаря тем исправлениям стандартной библиотеки Arduino Ethernet Library о которых я вам сейчас рассказал.

Комментарии (67)


  1. Ogoun
    07.08.2015 13:32

    Спасибо за работу! Как раз начинаем проект где будет задействован и чип и эта библиотека.


  1. Frimen3
    07.08.2015 14:04

    +1
    Полезная вещь, респект автору за работу!


  1. roller
    07.08.2015 14:36
    +4

    Сотни мух не могут ошибаться!!! (выбирая говно) Спасибо за работу!!!


  1. Syzd
    07.08.2015 14:37

    на оффициальном сайте Ардуино есть и другие библиотеки реализующие или не весь функционал шилдов или с ошибками, хотя есть библиотеки на github.com с лучшим кодом, который охватывает больше функционала железа. Чтобы попасть на оффициальный сайт есть какие то трудности? Или просто никто не отслеживает на оффициальном сайте лучшие реализации библиотек?


    1. smart_alex
      07.08.2015 15:27

      Я совершенно не фанат официальной библиотеки, мне нужно, чтобы AMS работал и если есть нормальная библиотека то я с удовольствием ею воспользуюсь. Все, что я протестировал были не лучше.


  1. shpaker
    07.08.2015 14:46
    +9

    Ведь с библиотекой работают не только пользователи, но и огромное количество профессиональных разработчиков.

    Не холивара ради, а любопытства. А правда есть профессиональные разработчики на Ардуино? Пытался найти недавно примеры коммерческих Ардуино-продуктов, но как-то поиски не на что не навели…
    И по посту. Если все равно приходится ковыряться в библиотеках то не проще ли сразу перейти на обычную атмегу?


    1. aronsky
      07.08.2015 14:53
      +3

      Нет, что вы, это же адский ад, писать на атмеге или, не дай Бог, на любом другом микроконтроллере.


      1. MaxAlekseev
        07.08.2015 15:02
        +1

        Я вообще сейчас ужас напишу, нет не так… УЖАСЪ!!! Ассемблер.


        1. aronsky
          08.08.2015 11:07
          +2

          На всякий случай побрызгал святой водой на монитор.


          1. MaxAlekseev
            08.08.2015 11:09

            Воистину, коллега!!!


      1. OnYourLips
        07.08.2015 21:53
        +3

        shpaker: Не холивара ради, а любопытства. А правда есть профессиональные велосипедисты на детских пластиковых трехколесных велосипедах?

        aronsky: Нет, что вы, это же адский ад, велосипедисту велосипед использовать.


    1. svd71
      07.08.2015 15:13
      +1

      Профессиональный — это в контексте ВУЗов с недостатком финансирования. Коммерческий проект в Ардуино — это сама Ардуино и шильды к ней. Например атмеловские чипы нельзя использовать в оборудовании медицинского направления — они вроде как отказались лицензировать.

      Что касается самих веб серверов на атмеле, то проектов куча. Начиная с цепляния эзернетовской карточки на rtl8239, полноценного web с ftp на mega644 и закачнчивая микросервером на attiny2313.


      1. shpaker
        07.08.2015 15:27
        +2

        Как-то не убедительно. Сама Ардуина как пример успешного проекта на Ардуинке тоже не засчитано. Имхо преподов принимающих работы на дуинке не должно быть, только если на вводных дисциплинах.
        пс: Вы не подумайте у меня у самого их три штуки, для целей быстрого прототипирования.


      1. locutus
        07.08.2015 16:34

        Не защитник Ардуино, но нам на экскурсии в Rice University, весьма небедном месте, показывали, что вообще все электронное прототипирование студентами ведется с использованием ардуино…


        1. svd71
          08.08.2015 09:03

          На сколько вижу по информации из поисковика, в этом универе ардуиной проповедуют с 2014 года. Зато прекрасно помню их страницу студенческих разработок под атмел с 2002 года. Да оно и сейчас не дурно отображается по запросе rise univeryity atmel.

          Идея стандартизировать модуль разработки не нова и даже хорошо, что на это кто-то выделил денег под рекламу, чтоб сделать некий «стандарт», отметающий кучу самолепных велосипедов. Самый навоз идет от прилагаемого фреймворка, от которого у начинающих пучит мозг (что напрямую относится к данному топику). Благо для программирования можно не легко, но отказаться от фремворка.


    1. smart_alex
      07.08.2015 15:32

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

      В библиотеке пришлось ковыряться по необходимости, до сих пор как-то обходилось без этого.


    1. barabanus
      07.08.2015 17:19
      -1

      Недавно я задал тот же вопрос Винфилду Хиллу, автору знаменитой книги «Искусство схемотехники». Он выслал схему своего недавнего проекта — драйвера электропорации — под управлением Arduino Nano. Удобство Arduino в том, что клиенту будет легко обновлять программный код.


      1. olartamonov
        07.08.2015 22:25
        +2

        Удобство Arduino в том, что клиенту будет легко обновлять программный код


        Это достигается заливкой в любую конструкцию бутлоадера от Ардуины, если вы хотите именно из Arduino IDE заливать прошивки (не представляю, зачем покупателю серийного коммерческого устройства этого хотеть). Во всех остальных случаях это будет очень странным решением.

        Он выслал схему своего недавнего проекта — драйвера электропорации


        Он его производит? Нет? Тогда, боюсь, лично он Arduino не использует.


        1. barabanus
          07.08.2015 22:41
          -4

          Авторы книги обедают с самыми продвинутыми схемотехниками Силиконовой Долины, создают приборы для научных лабораторий по всему США, поэтому я бы к их мнению прислушался. Я понимаю, что принято думать, что Ардуино — это такая игрушка для моргания светодиодами, но достаточно одного примера, чтобы это опровергнуть.


          1. olartamonov
            07.08.2015 23:00
            +1

            Я рад за них, наверняка питаются хорошо.

            Но не могли бы вы всё-таки пояснить, какой практический смысл в использовании Arduino в серийно производимом устройстве?


            1. barabanus
              07.08.2015 23:08
              +1

              В крупносерийном производстве использовать Ардуино смысла нет, но про это не было и речи. Вопрос был «используют ли Ардуино профессионалы». Ответ — используют, в частности — Arduino Nano. Удобный маленький модуль со смешной ценой.


              1. olartamonov
                07.08.2015 23:12
                +1

                Вопрос был про коммерческие продукты. Коммерческий продукт — это серийный продукт.

                А профессионалы его используют как удобную вещь для быстрого прототипирования, чтобы на коленке быстренько что-то собрать. Иное, повторюсь, не имеет практического смысла.


                1. Alexeyslav
                  08.08.2015 01:03
                  -2

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


                  1. olartamonov
                    08.08.2015 01:04
                    +3

                    У вас ардуина куда впаивается? На некоторую плату, на которой нужная вам обвязка стоит?

                    Ну так вам к производству её готовить что с атмегой на борту, что без неё — одинаково стоит.


                1. ezh213b
                  10.08.2015 09:29

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

                  PS: сам не использую ардуино и против его использования в проектах с сериями > 500 шт.


                  1. olartamonov
                    10.08.2015 09:54
                    +1

                    Использование технологий быстрого прототипирования в таких проектах вполне оправдано


                    Извините, полная чушь.

                    У вас 90 % научной установки — это интерфейсы к датчикам, как правило, весьма специфическим, причём интерфейсы с максимально понятными характеристиками, линейностью, ошибками. У вас просто стоимость одних только нужных АЦП и ОУ (и да, на ардуиновских ширпотребных шилдах ничего близкого к ним не будет) запросто перекроет стоимость самой ардуины в разы, равно как и сложность разводки печатки под них по сравнению с печаткой под атмегу.

                    P.S. Помнится, в начале нулевых мы в лабе делали себе на атмеге оптоэлектронный интерфейс к спектрометру, не то чтобы сильно страдали от отсутствия ардуины.


                    1. Meklon
                      10.08.2015 10:28

                      Ну фиг его знает. В моей установке обвеса примерно на 200$ датчиков и тому подобного. Но с этим прекрасно справляется Arduino Nano за 2.5$


                      1. olartamonov
                        10.08.2015 10:30

                        Вы её себе на коленке делали, а не продавали сторонним людям.

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


                        1. Meklon
                          10.08.2015 11:08

                          А в чём проблема для одиночных вещей? Сама плата сделана очень качественно, щтампуют их тоннами. Софт? Вероятно. Библиотеки Arduino могут содержать проблемы. Но в моих задачах это не проявляется. Где надо я руками запускал аналоговый коммутатор, который обычным фреймворком не охватывается. Мне остаётся только воткнуть готовую железяку в плату и работать. Меньше возни с разводкой. Какая мне разница — голый там чип или сразу с обвязкой и usb? В одиночных изделиях большая часть цены- моё время. Тупо дешевле не отвлекать меня совсем низким уровнем.


                          1. olartamonov
                            10.08.2015 11:23
                            +1

                            Меньше возни с разводкой


                            Если разводка AVR8 для вас — это возня, которая заслуживает хоть какого-то отдельного упоминания, то на уровень разработчика электронных устройство вы вообще, совсем, никак не тянете. Для меня, например, развести на плате атмегу и её обвязку — это быстрее, чем рисовать библиотечный компонент с какой-либо ардуиной.

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

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

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


                            1. Meklon
                              10.08.2015 11:42

                              Убедили, согласен. Я профессионал в другой области.


                            1. Alexeyslav
                              13.08.2015 14:17

                              Ох уж эти специалисты, которые разводят цифровую схему за 5 минут…
                              У меня как раз сомнения возникают именно эти 5-минутные платы.
                              Потратить час времени на разводку платы — сколько говорите у вас стоит час времени?
                              Примерно столько времени уйдет чтобы развести плату уровня ардуины с учетом всех требований разводки а не скопировать уже готовое решение.


                1. IVAN2001
                  13.08.2015 13:16
                  +1

                  Коммерческий продукт — это серийный продукт


                  Откуда взято такое определение?
                  Бывают индивидуальные проекты, для которых да же плату разводить не имеет смысла. Как пример — производство архитектурных макетов. Есть фирма (без имен, рекламой заниматься не буду), которая занимается именно этими макетами. В каждый макет втыкается ардуинка, которая мигает лампочками («ночная» подсветка, светофоры), крутит сервы (шлагбаумы, ворота, модельки машин), обрабатывает внешние запросы (в т.ч. сетевые) на запуск сценария. Каждый макет — индивидуальный проект под конкретного заказчика.

                  В моем понимании «Коммерческий продукт» — это продукт, приносящий прибыль. Каждый макет — это продукт, за который платят достаточно что бы кормить небольшую фирму, которая их производит. Им важна скорость разработки (чем больше выполненных заказов, тем больше прибыль), а в этом ардуине нет равных.


                  1. olartamonov
                    13.08.2015 13:23

                    Это фирма со всей очевидностью не занимается разработкой и производством электроники ни в каком виде. Она является потребителем готового изделия.

                    Как только они захотят чего-то минимально большего и, например, придут с этим запросом к собственно разработчикам электроники, ардуина бодро пойдёт лесом.


                    1. IVAN2001
                      14.08.2015 15:06
                      +1

                      Я написал, что эта фирма занимается производством интерактивных архитектурных макетов. Вообще, как и любая коммерческая фирма, она занимается зарабатыванием денег, а не продвижением своей религии. Если производить универсальные блоки им покажется выгоднее, то она это сделает, а пока использует ардуино в своих вполне коммерческих проектах, не претендуя на инновации, не нанимая армию дорогих специалистов, не закупая дорогое ПО и аппаратуру. У них своя ниша и их это, видимо, устраивает.
                      Напомню, что вопрос был про коммерческий продукт. И я поддерживаю ezh213b в его утверждении, что «Коммерческий продукт не всегда крупносерийный.». В приведенном примере продуктом, который фирма производит, является сам макет. Для его производства закупаются комплектующие, в составе которых Ардуина, которая используется как управляющий блок.


                      1. Meklon
                        14.08.2015 18:26

                        Типа чем Ардуина хуже, чем просто gps или wi-fi чип. Причём этот чип может содержать более сложную структуру и мощные мозги, чем центральный модуль.


    1. mark_ablov
      07.08.2015 19:32
      +1

      Тоже подумалось что професиионал скорее всего не возьмёт ардуионо для любого более-менее серьезного проекта.


      1. barabanus
        07.08.2015 21:53

        Да вот берут (см. комментарий выше)


      1. Meklon
        07.08.2015 23:08
        +1

        У меня в лаборатории весьма успешно трудится. Контролирует процесс обработки органа перед засеванием стволовых клеток.


        1. mark_ablov
          08.08.2015 08:22
          +1

          Неужели, профессионально занимаетесь разработкой железок? Или всё же на хлеб зарабатываете другими навыками? ;)


          1. Meklon
            08.08.2015 10:30
            +2

            Хм. Уели. Но тем не менее, благодаря сниженному порогу вхождения, специалисты получили возможность использовать железо в профессиональных смежных областях.


      1. barabanus
        07.08.2015 23:56

        Тут еще вопрос, что вы называете ардуино. Официальные железки? Ардуино как прообраз ОС?
        Например, вот знаменитый ArduPilot — отточенный опенсорсный автопилот, под него сначала сделали свою железку, а позже портировали на PixHawk.


      1. Alexeyslav
        08.08.2015 01:00

        О да, профессионал обязательно пойдет в гараж, вытравит плату и будет пол года писать прошивку на ассемблере. Такие вот суровые профессионалы.


        1. mark_ablov
          08.08.2015 08:21
          +3

          Для макетирования пойдёт и wire-wrapped макетки, и девкиты. Да, и арудино тоже.
          Но неужели вы будете утверждать что делать продукт на девките это нормально?
          Прототипирование и разработка готового изделия — разные вещи.


    1. olartamonov
      07.08.2015 22:21
      +2

      Пытался найти недавно примеры коммерческих Ардуино-продуктов, но как-то поиски не на что не навели…


      А смысл? Arduino — это фактически референсный дизайн атмеги, которая в применении проста настолько, что своя плата с нужным функционалом разводится за вечер студентом-третьекурсником. Результат будет значительно компактнее, надёжнее и дешевле.

      Ардуино в коммерческих разработках нужно использовать, если изделие — это какой-то конструктор, который покупатель сам собирать будет.


    1. ProLimit
      07.08.2015 23:55
      +2

      Как только дело доходит до более-менее серьезной задачи, Arduino ни на что не годится. Хотя сам проц нормальный, библиотеки в проекте слишком уж универсальны, и иза-за этого очень неоптимальны для узких задач. Да и написаны абы как. С этим проектом работают в основном начинающие разработчики, и это сказывается на уровне кода, и от багов проект избавляется очень медленно.

      Но для старта он очень хорош. Начав освоение микропроцессоров с Ардуино, очень скоро я перешл в AVR studio и переписал нужные библиотеки под свой проект.


  1. aronsky
    07.08.2015 14:52
    +9

    Так вот, оказалось, что эта библиотека попросту профнепригодна. На ней в принципе невозможно построить нормальное сетевое взаимодействие. Можно только «баловаться» одиночными запросами и ответами.

    В принципе этим можно охарактеризовать Arduino в целом.


  1. mifki
    07.08.2015 15:22
    +1

    Не очень понятны ваши рассуждения на счет комментария и XXX. Вы разобрались, почему оно стало лучше работать?


    1. smart_alex
      07.08.2015 15:41

      Конечно, и подробно описал в статье. Если кратко, то те запросы, которые игнорировались и просто отбрасывались стали обрабатываться, что кардинально (3 — 5 раз) уменьшило время загрузки файлов. Если бы я не разобрался в проблеме, то как бы я перекисал библиотеку и заставил всё работать как минимум в три раза быстрее?


      1. smart_alex
        07.08.2015 15:50

        Пардон, переписал, естественно.


      1. mifki
        07.08.2015 16:22
        +4

        //XXX это стандартная практика обозначения комментариев, которые поясняют какой-то неочевидный момент в коде. В данном случае, правда больше по смыслу подошло бы обозначение //TODO. Комментарий говорит о том, что в дальнейшем надо обратить внимание на это место и переписать так, чтобы функция не возвращала всегда первый попавшийся сокет, а не забывала про другие тоже. Не знаю, откуда у вас вольные перевод «работает, но не всегда», возможно, спутали с «doesn't always pick the lowest numbered socket».

        Вы не совсем исправили библиотеку, ибо перенесли логику на верхний уровень, где по-хорошему её быть не должно.

        Еще, я подозреваю, что изначально проблема из-за того, что сокеты не закрываются сразу после обслуживания запроса. Иначе и со старой логикой не было бы задержек. Задержка в три секунды тоже, по-моему, из-за этого — MAX_SOCK_NUM равен четырём, а старые сокеты висят, вот четвертый (на графике он третий, фиг знает, куда еще один делся) запрос и ждет. Так что надо смотреть, почему не закрываются сокеты.


        1. smart_alex
          07.08.2015 19:57

          Я проверял закрытие сокетов и никаких проблем не нашёл, у меня складывается подозрение, что проблема глубже — в работе с буфером 2х8 килобайт в W5100. Было бы здорово, если кто-нибудь из действительно компетентных людей осветил этот вопрос.


          1. smart_alex
            07.08.2015 20:22

            Кстати, кто-нибудь может сказать почему именно 3 секунды? Не 2 и не 4, а именно 3. Или кратное этому значению 9 секунд? Здесь явно есть какой-то смысл и какая-то связь. Таймаутов я не обнаружил.


            1. mifki
              08.08.2015 01:49

              Вы пробовали открывать другим браузером, что-нибудь меняется?


              1. smart_alex
                08.08.2015 05:42

                Конечно пробовал. Ничего не меняется.


            1. mifki
              08.08.2015 04:53

              Или увеличить max_sock_num и посмотреть, что будет.


              1. smart_alex
                08.08.2015 05:45

                Увеличивать нельзя. У W5100 аппаратное ограничение. А при уменьшении всё становится только хуже, что предсказуемо.


            1. ToSHiC
              10.08.2015 13:18

              Похоже на дефолтовый таймаут tcp syn retry. Вообще, вам надо было начать с дампа траффика хотя бы тем же wireshark, а дальше уже разбираться, где именно не работает.


              1. smart_alex
                10.08.2015 15:23

                Да, мы эту проблему обсуждали на форуме АМС с дампами и графиками и пришли к выводу, что запросы уходят в ретрансмиссию на 3 секунды, затем на 6. Но всё равно, на мой взгляд, библиотека работает не на 100% корректно и там есть, что исправлять.

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


    1. Eklykti
      09.08.2015 05:25
      +1

      > рассуждения на счет комментария и XXX

      Осторожно, здесь какая-то порнография:


  1. smart_alex
    08.08.2015 05:57
    +3

    Мне прислали ссылку forum.arduino.cc/index.php?topic=154157.0, оказывается не только я пытаюсь решить эту проблему. (Обсуждение на итальянском)

    Ещё высказано предположение, что 3 секунды связаны с TCP retransmission. Это попытка повторной отправки пакета через определенный таймаут. 3 сек — это Default Retransmission Timeout в Windows msdn.microsoft.com/en-us/library/aa922362.aspx?f=255&MSPPError=-2147217396


  1. alecv
    10.08.2015 11:26

    У вас отлично получается, может посмотрите чип W5500?
    Вот тут я про него писал полтора года назад. С тех пор шилдов на нем появилось изрядно.
    geektimes.ru/post/255132


    1. smart_alex
      10.08.2015 15:16

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

      Я смотрю вы разбираетесь в теме — было бы неплохо если бы вы помогли разобраться. Скачав дистрибутив к себе или «теоретически» обсудив проблему на форуме АМС.


      1. alecv
        10.08.2015 23:36

        Коллеги к счастью уже давно сделали и сдали железку. Там было все на штатной библиотеке wiz-io на одном фиксированном сокете, а не на пуле сокетов. Задержки были минимальные просто по той причине, что TCP HTTP быстро открывалось и быстро закрывалось. Долгоживущие HTTP сокеты не поддерживались, даже на просьбу Connection: keep-alive. Параллельные соединения от броузера (например IMG SRC) теоретически могли бы мешать, но чип как-то корректно информировал клиента, что сокет уже занят (подробности не смотрел) и запросы приходили последовательно, но в хаотичном порядке, особенно при работе через proxy. Это что помню.


  1. Acuna
    12.08.2015 17:03

    Вот именно поэтому я как правило пишу библиотеки сам на основе известных и популярных. Не люблю котов в мешках. Иногда их приходится практически переписывать заново. Сейчас пишу для Amazon S3. Стандартный SDK вполне рабочий, только во-первых там ноги переломаешь на коде, а во вторых столько абстракций просто не нужно. Все хорошо в меру. В итоге все необходимые функции для работы с файлами уместились в один файл. Один! Времени занимает много, соглашусь, я до сих пор ее пишу согласно нужным задачам, однако я более чем уверен, что она будет работать так, как мне надо, без подводных камней и каких-то сюрпризов, имеющих обыкновение появляться прямо на дедлайне. Ну и наконец это просто интересно и полезно для практики.


  1. CodeDriller
    13.08.2015 11:22

    Поясните, пожалуйста, это место: «Цикл перебирает сокеты и, как только находит подходящий, возвращает клиента, а остальных просто игнорирует. И они висят по десять секунд, пока «карты благоприятно не лягут».» Что за проблема была в ходе перебора? В ходе перебора сокеты не закрывались должным образом?


    1. smart_alex
      13.08.2015 11:37

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

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