Перейти к публикации
iT4iT.CLUB

Kitsum

Пользователи
  • Публикации

    424
  • Зарегистрирован

  • Посещение

  • Дней в лидерах

    234

Все публикации пользователя Kitsum

  1. Kitsum

    Метеостанция на ESP8266 от it4it.club

    Доброе время суток. Давайте начнем с самого главного - DHT22 не работает с i2c шиной, для него требуется отдельный порт микроконтроллера, поэтому работа с ним НЕ может быть такой же, как работа с BME280. По моему субъективному мнению, их не стоит ставить на одном уровне, BME280 более выгодный и надежный вариант. Теперь о проблеме, причин может быть несколько: Порт микроконтроллера уже используется чем-то Ошибка в коде Плохой контакт i2c шины с микроконтроллером Плохой контакт i2c шины с одним из датчиков Один из датчиков вносит хаос в работу всей шины Меня очень настораживает перевод одного из стандартных портов i2c шины на другую "ногу" микроконтроллера, т.к это не даст совершенно ничего кроме физического переезда на другую группу контактов, но это было сделано, значит для чего то было нужно. Начните по порядку, возьмите оригинальную программу и оставьте только i2c шину с датчиками на оригинальных портах, проверьте работоспособность. Так станет ясно имеется ли проблема в самих датчиках или шине. Если проблема ушла, то пробуйте сменить порты шины (программно и аппаратно), если проблема не проявляется, то добавляйте поэтапно все используемые модули, сенсоры и т.п с поэтапным изменением в коде. Что явно бросается в глаза так это массовый вызов callswitch в callback с последующим присвоением ошибочных значений для переменных. Функция callback вызывается каждый раз, когда приходит сообщение и этот факт ставит нас в строгие рамки. Например, пришло сообщение для субтопика switch0, что при этом произойдет? А произойдет следующее, всем переменным, кроме одной будет присвоено неопределенное логическое значение, возвращаемое функцией callswitch т.к проверки описанные в этой функции предусматривают совпадение только с одним топиком, в противном случае переменная sw остается явно не заданной, то есть нам вообще неизвестно её значение. Аналогичная ситуация должна прослеживаться в случае поступления в любой топик, на который оформлена подписка, значения отличного от тех, что участвуют в проверках. И также она будет воссоздана для всех топиков в случае если во время работы программы был удален конфигурационный параметр отвечающий за корневой топик. Что сразу можно сказать по данному фрагменту кода sw_on_0 = callswitch(top, msg, 0); sw_on_12 = callswitch(top, msg, 12); sw_on_13 = callswitch(top, msg, 13); sw_on_14 = callswitch(top, msg, 14); sw_on_15 = callswitch(top, msg, 15); Он не допустим в функции callback, по крайней мере до тех пор, пока функция callswitch будет возвращать ошибочные значения во всех случаях кроме одного, это совпадение имени топика. Вообще я бы рекомендовал изменять за раз только одну переменную, ту к которой адресовано сообщение и улучшить проверки поступающих значений. Позвольте дать Вам еще пару советов по поводу кода, это поможет не наступить на грабли в будущем. Вы ввели дополнительную переменную, как я понимаю, для контроля наличия соединения. /* вырезка из кода */ connect_OK = true; К сожалению, я не увидел, когда происходит определение обрыва соединения и ее значение меняется на false. Взамен этой переменной воспользуйтесь уже готовым методом объекта mqttAPI mqttAPI.connected() Он возвращает логическое значение, соответствующее наличию или отсутствию соединения с MQTT брокером. Вы можете оптимизировать описанную ниже конструкцию //gpio 0 D3 нежелательно if (sw_on_0 == true and digitalRead(0) == !gpio_enable) { digitalWrite(0, gpio_enable); mqttPublish("switch/on","gpio_0_is_ON"); } else if (sw_on_0 == false and digitalRead(0) == gpio_enable) digitalWrite(0, !gpio_enable); до такого вида if (digitalRead(0) != sw_on_0) { digitalWrite(0, !digitalRead(0)); mqttPublish("switch/on", sw_on_0 ? "gpio_0_is_ON" : "gpio_0_is_OFF"); } Теперь о главном. Я бы поставил под сомнение стоит ли использовать в функции callswitch ответ в виде вызова mqttPublish. На эту операцию тратится очень много времени, тем более, что ответ отправляется, когда планировщик задач вызывает функцию проверки соответствия состояния портов. Функция callswitch вызывается в функции callback, что не очень хорошо из-за описанной ситуации. В функции callswitch объявлена переменная sw использующаяся с оператором return. boolean sw; Остается не ясным, что вернет функция callswitch в случае если конфигурационная переменная mqtt_path не была задана, по сути не указан корневой топик в web интерфейсе. Или поступило любое сообщение отличное от ON или OFF в различных регистровых вариациях, например, "BlaBlaBla". Переменная sw должна иметь определенное начальное значение или это значение должно явно определяться в ходе выполнения функции, особенно когда функция должна вернуть результат в случае несовпадения топиков и этот результат должен быть в различных ситуациях разный, как true так и false (опять отсылка к массовому вызову callswitch в callback). В общем Ваша проблема кроется в двух функциях, это callswitch и callback, думаю, что Вы уже догадались как реализовать задуманное.
  2. Kitsum

    Метеостанция на ESP8266 от it4it.club

    @PulFred график метеостанции, это опорная точка. Нам наверняка известно, что график начинает строиться через 10 минут после старта микроконтроллера. Я могу сделать вывод, что примерно в 9 часов вечера микроконтроллер начал выполнять свою работу. Также может быть так, что у контроллера сработал сторожевой таймер, что привело к перезапуску и сбросу всех данных в памяти, в том числе и графика. Куда стоит обратить внимание: В первую очередь проверьте качество питания. Все модификации должны корректно отрабатывать в любом режиме работы микроконтроллера AP/STA, особенно если они контактируют с внешним миром. Убедитесь, что в коде нет утечки памяти. Эта проблема проявляется в версии 2.4.1 ядра ESP8266. Также эта проблема может быть вызвана модификациями. Если к метеостанции есть доступ из интернета, его необходимо закрыть т.к web сервер микроконтроллера не предназначен для массового наплыва клиентов, а ходить на веб сервер буду 100%. Среди клиентов сразу появятся различные сканеры и т.п программы. Зайдите в Настройки, раздел Система. Убедитесь, что объем свободной памяти сразу после запуска микроконтроллера примерно совпадает с объемом через, допустим, час или два после запуска. Заодно проверьте версию ядра (2.4.0 или 2.4.2). В самом конце этого раздела проверьте время беспрерывной работы. В моем случае таймер указывает на 9 дней и 4 часа, но на самом деле, через каждые 40 с лишним дней происходит переполнение millis и таймер начинает отсчет с нуля. Но для понимания происходящего этого вполне достаточно. По своему варианту метеостанции (опубликованный исходник с выбранными датчиками + один программный датчик) с отправкой данных на три разные площадки в интернете, я делаю вывод, что в течении последних 9-и дней нет проблем с питанием и переполнением памяти. Постарайтесь провести аналогичный анализ, только в Вашем случае перезапустите микроконтроллер и запомните сколько оперативной памяти было свободно. Понаблюдайте в течении дня за памятью и внутренним таймером. На крайний случай воспользуйтесь, для сравнения, стоковой прошивкой с модификациями кода микроконтроллера и web интерфейса только под свои датчики. Буду надеяться, что проблему получится выявить сразу.
  3. Kitsum

    Метеостанция на ESP8266 от it4it.club

    Доброе время суток. К сожалению, мне довольно сложно ответить на данный вопрос т.к я не сторонник загрузки данных через данную программу. Знаю, что необходимо указать несколько скомпилированных файлов с указанием соответствующих им адресов. Адреса могут меняться в зависимости от используемой микросхемы флеш памяти. Обратитесь к официальной документации или используйте Arduino IDE для загрузки данных. В пользу среды разработки в качестве программы загрузки могу сказать, что она дает простой способ произвести тонкие настройки для ESP8266 благодаря которым, начиная с версии ядра 2.4.2 можно разогнать скорость работы с сетевым трафиком в несколько раз. У меня получилось добиться загрузки самого тяжелого файла проекта (css файл с изображениями облаков) за 1.4 секунды внутри локальной сети. Полагаю, что график взять с "Народного мониторинга". Эти пробелы наблюдаются на собственном графике метеостанции?
  4. Kitsum

    Метеостанция на ESP8266 от it4it.club

    @Devilisimo доброе время суток. Если мы говорим о переменном токе, то можно собрать собственную схему на симисторе и подобрать его по требуемым характеристикам. Вот вполне полное видео по данной теме. А вот для постоянного тока. В любом случае, все упирается в характеристики элементной базы и нагрузку. PS: соблюдайте предельную осторожность при работе с абсолютно любой нагрузкой, даже не большие токи могут привести к летальному исходу!
  5. Kitsum

    Метеостанция на ESP8266 от it4it.club

    Всем доброе время суток. Допустил опечатку при указании версий ядра ESP8266 для Arduino IDE. Поправил свой пост. Теперь еще раз и о главном - в ядре версии 2.4.1 имеется баг с утечкой памяти при работе с объектом WiFiClient. В версии 2.4.2 данный баг исправлен, по крайней мере об этом гласит ветка на GitHub. Обновитесь до 2.4.2 или откатывайтесь до 2.4.0 в зависимости от Ваших изменений в проекте.
  6. Kitsum

    Метеостанция на ESP8266 от it4it.club

    Вы всегда можете изучить возможности библиотеки, никакой магии там нет, просто откройте в Arduino IDE любой пример идущий в комплекте с библиотекой. Далее в меню "Скетч" выберите пункт "Показать папку скетча" и в открывшемся каталоге достаточно перейти в корень библиотеки, обычно не более двух переходов на каталог выше. Там Вы увидите список файлов и каталогов среди которых будет каталог src с исходными кодами библиотеки. Нас интересуют файлы заголовков, в данном случае файл PubSubClient.h Открываем его любым удобным текстовым редактором, желательно с поддержкой перевода строки по ASCII 0x0A (в народе просто '\n'). И нам станет доступно описание всех методов интересующего класса. Теперь можно изучить методы, а при необходимости посмотреть их реализацию в файле с расширением .ccp В нашем случаем метод subscribe принимает в качестве первого аргумента указатель на переменную с типом const char В программе реализовано сохранение настроек в список которых входят данные для подключения к домашней базовой станции. Далее, если связь будет разорвана, то программа переведет контроллер из режима клиента (STA) в режим самостоятельной точки доступа (AP) и через небольшие интервалы времени будет производить сканирование эфира в поиске домашней базовой станции. Во время поиска все клиенты, подключенные к точке доступа контроллера, будут отключены, это связано с переводом контроллера в режим STA при сканировании. Если домашняя точка доступа будет найдена, то контроллер попытается к ней подключиться. Также при удачном подключении контроллер запомнит MAC адрес домашней точки доступа. В последствии он будет использован для сравнения MAC адресов у скрытых точке доступа в поиске "дома". Этот механизм нуждается в доработке из-за некоторых специфических ситуаций, но вполне работоспособен и на данный момент. В первую очередь необходимо загрузить программу в микроконтроллер, делается этот как и всегда через зугрузку программы. После этого необходимо залить файлы web сервера на flash через "ESP8266 Sketch Data Upload". При этом консоль (Serial монитор) должна быть закрыта т.к занимает порт. Ваша ошибка связана с использованием одной из Beta версий библиотеки ArduinoJson. Возьмите любую версию из 5.13.x, это упоминалось в инструкции. Также хочу напомнить, что не каждая версия ядра ESP8266 для Arduino IDE подойдет нам, я использую 2.4.0, а вот в версии 2.4.1 есть баг с утечкой памяти который приведет к серьезным проблемам! Будьте очень внимательны и следуйте рекомендациям. Если Вы говорите о плате от RobotDyn с двумя контроллерами на борту, то её хватит для решения большинства задач и подключения кучи датчиков, дисплеев и т.д и т.п, тут только фантазия может стать ограничивающим фактором. Но я бы отказался от встроенного способа связи между ними через UART в пользу I2C или SPI. Значение 32 относится к ESP8266, а к ATmega2560 можно подключить все, что Вам нравится. Но я не сторонник SD карт из-за их низкой надежности и возможных проблемах при выходе карты из строя. Для ведения журналов есть множество других способов, один из которых, это сторонний скрипт на домашнем сервере в роли которого может выступить подготовленный домашний маршрутизатор. Оно так и есть на самом деле, 8bit = 1byte. Вопрос только в том, как эффективно использовать эту память чтобы быстро не сократить её срок службы. Если у Вас есть удаленный сервер, то лучше возложить на него все задачи, связанные с сохранением полученных данных. Это максимально эффективно и правильно.
  7. Удалите из проекта вызов сторожевого таймера, я указывал ранее на нужные строки. Проверьте будет ли зависание, возможно Ваша проблема совсем не связана с программой.
  8. Kitsum

    Метеостанция на ESP8266 от it4it.club

    @Devilisimo еще раз доброе время суток. Озадачился я Вашим последним вопросом, пришлось найти микроконтроллер и все протестировать в живую. Что получилось в итоге - была выявлена проблема хранения адреса MQTT сервера. Точнее даже не проблема, просто моя не внимательность т.к библиотека PubSubClient обращается к переменной с адресом через указатель то хранить данную переменную в функции setupMQTT не представляется возможным из-за освобождения памяти после ей выполнения. Соответственно, к тому моменту, как планировщик переходит к заданию по контролю соединения с брокером, адреса сервера уже не существует. Я упустил этот момент, когда подгонял в голове работу издателя и подписчика в рамках services.h Что по существу изменилось, так это перенос переменной с именем сервера в глобальное пространство имен. Я обновил предыдущий свой пост и указал на этот факт чтобы другие тоже могли воспользоваться этой инструкцией. Код функций может чуть отличаться, например, именем топика, т.к я взял его из кода залитого для теста в микроконтроллер. Все проверил на живом контроллере и получил положительный результат. Ошибка, скорее всего, была связана с не невозможностью подключиться к серверу. Всегда будет вызываться функция, указанная в качестве аргумента для метода setCallback. В функцию будут переданы параметры, среди которых имя топика и его новое значение. Отталкиваясь от этих данных Вы можете сделать обработку для каждого топика. Вы можете указывать практически сколько угодно субтопиков в имени топика. Например, использовать топик с полным физическим адресом и указанием страны, города, улицы и т.д. Слэш в данном случае играет роль разделителя и не более того. Вот как это выглядит на практике. Синим выделены отправленное на брокер mqtt.it4it.club в топик test/esp8266/work сообщение.
  9. Kitsum

    Метеостанция на ESP8266 от it4it.club

    Это отдельная история, связанная с реализацией функции callback. Если Вы безоговорочно доверяете пришедшим данным от брокера, то в контексте описанной ранее функции можно преобразовать String в Int с помощью метода toInt msg.toInt(); Но так лучше не делать, особенно в интернете. Я бы посоветовал составить список дополнительных проверок для каждого интересующего Вас топика. При этом проверки должны быть не только связаны с типом данных, но и с их значением, особенно если контроллер управляет внешними устройствами.
  10. Kitsum

    Метеостанция на ESP8266 от it4it.club

    @Devilisimo доброе время суток. Боюсь, что у Вас все перемешалось. Давайте разбираться подробнее. В первую очередь необходимо понять, что из себя представляет MQTT протокол. Работает он по схеме "издатель-подписчик" и подразумевает, что подписчик после подключения передает брокеру (центральному сервере) список интересующих его топиков. После данной операции подписчик переходит в режим ожидания в котором только поддерживает связь с брокером. После того как в каком-либо топике происходит публикация сообщения, центральный сервер берет список всех клиентов, подписанных на него и сообщает им об изменениях. Подписчикам приходит оповещения, ради которого они и поддерживали связь. Если смотреть со стороны издателя, то поддерживать постоянную связь нет необходимости. Когда требуется опубликовать новые данные издатель подключается к брокеру и передает адрес топика и полезную нагрузку. Далее просто отключается. Таким образом издатели и подписчики совершенно не знают ничего друг о друге. Да им это и не требуется. Всем занимается центральный сервер. Изначально данный проект метеостанции работает с MQTT протоколом только в роли издателя. Как вижу решения я В первую очередь создаем функция вызываемую при публикации сообщений в топиках, на которые мы подписаны. void callback(char* topic, byte* payload, unsigned int length) { String msg; for (unsigned int i = 0; i < length; i++) msg += (char)payload[i]; #ifdef console console.printf("\nСообщение[%s]: %s\n", topic, msg.c_str()); #endif } Описать её можно в файле services.h, по хорошему её нужно назвать иначе, но мы уже начали использовать это имя поэтому я буду его придерживаться. У нас есть обработчик, теперь необходимо его задействовать. Для большего порядка создадим дополнительную функцию. void setupMQTT() { if (conf.param("mqtt_server").length()) { /* Указываем сервер и порт для подключения. Сервер можно указать через WEB интерфейс, порт измените на свой. */ mqttServer = conf.param("mqtt_server"); mqttAPI.setServer(mqttServer.c_str(), 1883); /* Устанавливаем обработчик */ mqttAPI.setCallback(callback); /* Задача для восстановления соединения */ cron.add(cron::time_1m, [&](){ if (!mqttAPI.connected() and wifi.transferDataPossible()) { if(mqttAPI.connect(WiFi.hostname().c_str(), (conf.param("mqtt_login").length() ? conf.param("mqtt_login").c_str() : 0), (conf.param("mqtt_pass").length() ? conf.param("mqtt_pass").c_str() : 0) )) { /* Список топиков на которые необходимо оформить подписку */ mqttAPI.subscribe("test/esp8266/work"); } #ifdef console console.printf("Connecting to MQTT server\nanswer: %s\n", mqttCodeStr(mqttAPI.state()).c_str()); #endif } }, false); } /* end if */ } Думаю, тут все понятно. Функция описывает к какому серверу подключаться, устанавливает обработчик и добавляет в планировщик задачу для подключения к серверу в случае разрыва связи. В функции используется переменная объявленная в глобальном пространстве имен. String mqttServer; Объявить переменную можно прямо в файле services.h Вынос её за пределы функции обусловлен необходимостью сохранения имени MQTT сервера т.к библиотека PubSubClient использует обращается к ней через указатель. Все это очередное напоминание о необходимости доработки модуля хранения настроек конфигурации микроконтроллера. Данную функцию мы будем единожды вызывать при старте контроллера поэтому добавим её в конец функции setup в основном файле. void setup() { /* ... */ setupMQTT(); } Но этого все еще недостаточно чтобы мы начали получать сообщения. Необходимо добавить обработчик MQTT для завершения реализации режим "подписчика". void loop() { /* ... */ /* Обработчик MQTT для режима "подписчика" */ mqttAPI.loop(); } Можно считать основную работу законченной, НО мы помним, что ранее ESP работал только в режиме издателя, а это значит, что мы можем попасть на ошибки, связанные с добавлением нового режима. Давайте все перепроверим и избавимся от них. Идем в функцию, отвечающую за публикацию данных с сенсоров метеостанции и удаляем из ней все, что связанно с подключением к брокеру т.к теперь эта задача возложена на плечи планировщика задач. /* mqtt.it4it.club */ void sendDataToMQTT() { if (wifi.transferDataPossible() and conf.param("mqtt_server").length() and mqttAPI.connected()) { #ifdef console console.println(F("services: send data to MQTT server")); #endif mqttPublish("light", sensors.get("out_light")); mqttPublish("temperature", sensors.get("out_temperature")); mqttPublish("humidity", sensors.get("out_humidity")); mqttPublish("pressure", sensors.get("out_pressure")); mqttPublish("co2", sensors.get("out_co2")); mqttPublish("absoluteHumidity", sensors.get("out_absoluteHumidity")); #ifdef console console.printf("answer: %s\n", mqttCodeStr(mqttAPI.state()).c_str()); #endif } } Также обязательно убираем вызов метода отвечающего за разрыв соединения с брокером. mqttAPI.disconnect(); А в основное условие с проверками возможности передачи данных добавляем проверку наличия подключения к MQTT брокеру. mqttAPI.connected(); На этом можно считать модернизацию законченной. Я не описывал подробности реализации функции callback о которых говорил в предыдущих постах т.к это напрямую зависит от потребностей каждого, но напоминаю о варианте с накоплением данных и выводом их на дисплей через планировщик задач. PS: если в ваших модификация для проекта присутствует дополнительный код, связанный с работой MQTT протокола, он должен быть упразднен или модифицирован в соответствии с описанной реализацией механизма "издатель-подписчик". Говорю об этом т.к в теме уже есть упоминания о таких модификациях от других форумчан и их использование будет приводить к постоянному разрыву соединения. Ну и как всегда, все проверяйте, т.к мои мысли могут быть ошибочны.
  11. @marsergei76 доброе время суток. Какой загрузчик залит в той или иной плате сказать не так просто. Но можно посмотреть какой загрузчик используется платформой Arduino в родной IDE. В корне среды разработки (windows) по адресу hardware/arduino/avr/boards.txt располагается файл с описанием всех настроек для той или иной платы. NANO nano.name=Arduino Nano # ... nano.menu.cpu.atmega328=ATmega328P # ... nano.menu.cpu.atmega328.bootloader.file=atmega/ATmegaBOOT_168_atmega328.hex # ... nano.menu.cpu.atmega168=ATmega168 # ... nano.menu.cpu.atmega168.bootloader.file=atmega/ATmegaBOOT_168_diecimila.hex UNO uno.name=Arduino/Genuino Uno # ... uno.bootloader.file=optiboot/optiboot_atmega328.hex Так что в теории, с UNO быть проблем не должно, но это не точно. А вот с NANO проблемы будут однозначно. Да конечно, для этого эта тема и создавалась. Я сам "обжегся" несколько раз на этом при попытке использовать сторожевой таймер. Именно это и послужило поводом к созданию упомянутой Вами темы. Смею заверить, что если у Вас проблемы с загрузчиком, то это все решаемо. Для начала, до подключения платы к компьютеру, зажмите Reset и не отпуская его подключите плату. Это должно остановить выполнение основного кода программы где активируется сторожевой таймер, при этом UART TTL контроллер определиться в системе и для него будет установлен драйвер. После этого запустите IDE, выберите Вашу плату и начните загрузку Blink. В тот момент, когда программа будет собираться (ближе к концу процесса) отпустите Reset. С этого момента начнется отсчет сторожевого таймера, TTL контроллер должен сбросить плату и начать загрузку программы. После этого обновите загрузчик или удалите его активацию в программе. Но отмечу, что лучше первый вариант, т.к в случае не нормальных ситуаций в ходе эксплуатации замка, контроллер будет перезапущен, в противном случае можно остаться у заблокированной двери. Хоть на моей практике (эксплуатация замка коллегами) такого еще не происходило (по крайней мере, не было замечено перезапусков во время активного использования), но все же хочется иметь козырь в рукаве.
  12. Kitsum

    Метеостанция на ESP8266 от it4it.club

    @pasha413 Судя по документации это flash на 8Mb, но в интернете есть упоминания, что с P25Q80H много проблем. Вопрос досконально не изучал, но вот интересная тема на Хабре: https://habr.com/post/409911/
  13. Kitsum

    Метеостанция на ESP8266 от it4it.club

    @pasha413 esp01 отличается от, например, esp12 только количество портов разведенных на плате и которыми Вы можете пользоваться. Во всем остальном это один и тот же контроллер. Все, что Вам нужно проконтролировать, так это чтобы на плате esp01 была распаяна flash память объемом не менее 4Mb.
  14. Доброе время суток К сожалению, упустил этот момент. Кнопка подтягивается к земле. Вообще обе кнопки в данном проекте коммутируют землю с указанными портами, таким образом можно довольно сильно увеличить длину проводов и отдалить кнопки от микроконтроллера. Обратите внимание, что в программе задействован сторожевой таймер wdt_disable(); wdt_enable(WDTO_8S); Если в Ваших платах не используется загрузчик Optiboot это будет приводить к зависанию т.к сторожевой таймер попросту не поддерживается другими загрузчиками для Вашей платы. Также стоит исключить ошибку подключения всей обвязки. Разберите схему, оставьте только плату с микроконтроллером. После подключения её к компьютеру у Вас будет 8 секунд для загрузки другой программы, например, Blink. Оттолкнитесь от этой информации, все внимательно проверяйте.
  15. Kitsum

    Метеостанция на ESP8266 от it4it.club

    Используйте возможности библиотеки PubSubClient, в её примерах есть интересующий Вас код. Сама библиотека используется метеостанцией и объект, через который необходимо работать, уже объявлен в файле services.h PubSubClient mqttAPI(wifiClient); Создайте функцию, отвечающую за обработку данных преступаемых от брокера (mqtt сервера) и опишите в ней весь необходимый функционал для обработки сообщений. Опишите её в основной (.ino) файле или в фале services.h, что более правильно. void callback(char* topic, byte* payload, unsigned int length) { /* Ваш код, подсказки смотрите в библиотеке PubSubClient */ } В функции setup, описанной в основном файле, необходимо добавить вызвать два метода объекта mqttAPI с помощью которых укажем к какому серверу подключиться и какую функцию вызывать при наличии входящего сообщения от брокера. void setup() { /* ... */ mqttAPI.setServer("mqtt.it4it.club", 1883); mqttAPI.setCallback(callback); } В функции loop необходимо добавить вызов обработчика, который будет отслеживать появление новых сообщений void loop() { /* ... */ /* Тут не хватает одной функции для подключения/переподключения к брокеру */ /* Обработчик MQTT */ mqttAPI.loop(); } Также Вам необходимо реализовать функцию, отвечающую за подключение и переподключение к брокеру. Без неё связь не будет установлена. Не стоит использовать функцию переподключения описанную в примерах библиотеки т.к в случае отсутствия связи с сервером вы получите практически постоянно висящий контроллер, что явно убьет весь остальной функционал. Я советую использовать планировщик задач с интервалом в 1, а лучше в 5 минут, который будет вызывать функцию проверки связи и подключаться к серверу если это необходимо. cron.add(cron::time_5m, [&](){ if (!mqttAPI.connected() and wifi.transferDataPossible()) { if(mqttAPI.connect(WiFi.hostname().c_str())) { mqttAPI.subscribe("weather_station/lcd/topic_name"); } } }, false); Топики, на которые необходимо оформить подписку указываются через метод subscribe mqttAPI.subscribe("weather_station/lcd/topic_name_1"); mqttAPI.subscribe("weather_station/lcd/topic_name_2"); mqttAPI.subscribe("weather_station/lcd/topic_name_3"); Обратите внимание, что я указал false в качестве последнего параметра метода add. Это запрет холодного старта, хоть он по умолчанию и не используется, мы оставляем явное указание для себя в будущем, чтобы не допустить вызова этой задачи до того момента пока контроллер не перейдет к циклическому вызову всех обработчиков. Ведь на раннем этапе выполнения кода ESP8266 даже не имеет подключения к базовой станции. Для аналогичной защиты используется проверка с вызовом функции wifi.transferDataPossible() Данный код я описываю без его проверки и в нем могут содержаться ошибки. Все внимательно проверяйте без лишней спешки. Если у Вас будет иная реализация, не стесняйтесь делиться кодом. PS: Забыл упомянуть. Я бы советовал Вам не выводить на дисплей данные сразу после их поступления. Лучше их накапливать. Далее в планировщик задач добавить функция вызываемую, например, каждую минуту и проверяющую отличаются ли поступившие данные от тех, что уже выведены на дисплей. Если да, то выводить новые данные. Таким образом Вы будите экономит процессорное время и избавите контроллер от лишних задач по выводу одинаковых данных на дисплей.
  16. Kitsum

    Метеостанция на ESP8266 от it4it.club

    Да, Вы совершенно правы, порт 1883. Я не добавлял выбор порта через web интерфейс т.к не видел в этом необходимости, но это легко можно исправить. О том, как добавлять свои параметры так чтобы ESP8266 их "запоминал" уже упоминалось в теме, но если вдруг будут сложности, дайте мне знать об этом и я постараюсь описать как это сделать. Если это не требуется, то просто замените в коде порт 1883 на тот, который Вам предоставит CloudMQTT. https://www.cloudmqtt.com/docs.html Помните, что шифрование не поддерживается метеостанцией (но возможно) и выбирайте соответствующий порт. Все остальные настройки производятся через Web интерфейс ESP8266. PS: прошу Вас не пренебрегать разметкой, в частности блоком "Код", когда публикуете части исходников, а то совсем не удобно читать без подсветки синтаксиса.
  17. Доброе время суток @marsergei76 Да, с этим не должно быть проблем. Найдите все места в коде где используется цикл такого вида for (byte b = 0; b < 4; b++) И замените его на for (byte b = 0; b < 7; b++) Перед загрузкой программы очистите EEPROM микроконтроллера удалив тем самым все записанные ранее ключи, в том числе и Master Key.
  18. Kitsum

    Метеостанция на ESP8266 от it4it.club

    @Devilisimo К сожалению, Вы не предоставили схему подключения датчика или подробное фото. Мне кажется, что проблема может скрываться как раз в подключении. Возможно не подключен порт 7 он же nWAKE (на платах часто отмечен как WAK). В официальной документации к датчику ccs811 на четвертой странице указано, что порт nWAKE должен быть подтянут к низкому логическому уровню до начала передачи данных по I2C шине. Я не стал занимать порт микроконтроллера для этих целей т.к у меня не автономное устройство, а просто кинул перемычку с nWAKE к соседнему GND.
  19. Kitsum

    Метеостанция на ESP8266 от it4it.club

    @post125 Это хороший и довольно интересный вариант. Вам будут доступны несколько интерфейсов для связи. Разработчик заложил связь через UART, но Вы вполне можете связать ATmega 2560 и ESP8266 через I2C, порты GPIO4 и GPIO5 доступны и выведены на колодку #1. Указано, что на плате распаяна флешь на 32 мегабайта, это хорошо т.к на старых ревизиях с 1-м мегабайтом было бы совсем грустно и пришлось бы облегчать оформление web интерфейса ESP. Из особенностей отмечу, что управление внешними исполнительными механизмами полностью ложиться на ATmega 2560, если вообще этот функционал будет востребован.
  20. Kitsum

    Метеостанция на ESP8266 от it4it.club

    @Devilisimo давайте разбираться. Для начала исправим ошибки. У Вас все перемешалось поэтому предлагаю разобрать процесс объявления нового сенсора на каком ни-ть примере. Я опять возьму за основу программный сенсор для сбора и отображения данных по уровню сигнала базовой станции к которой подключается ESP8266. Это очень простой пример, и он не перегружен лишним кодом. В коде метеостанции сенсор описан небольшим блоком. Он совсем маленький и записать его можно вообще в одну строчку, но это полноценный, законченный сенсор со всем необходимым списком параметров для его автоматической визуализации на странице web сервера микроконтроллера. sensors.add(new knob_t(-100, 0, "1", "RSSI", "dbm"), device::in, "rssi",[&](){ return wifi.isConnected() ? WiFi.RSSI() : 0; }); Выделим в отдельные элементы компоненты, указанные в качестве параметров. Первым будет идти код описывающий все необходимо для построения круговой шкалы с указанием визуального имени сенсора и подписи с единицами измерения. knob_t *R = new knob_t(-100, 0, "1", "RSSI", "dbm"); Объект knob_t представляет из себя небольшой контейнер в котором хранятся все характеристики Вашего сенсора. Его можно создать один для целой группы сенсоров, например, датчиков DS18B20. Но в данном случае нам это не интересно. Посмотрим, что из себя представляют все параметры, кстати, посмотреть их можно в файле sensors.h knob_t(int min, int max, const char *step, const char *title, const char *unit) Параметры: min - минимальное значение шкалы max - максимальное значение шкалы step - шаг с которым будет произведена визуализация изменения показаний (это не числа!): "1" - единица, ".1" - одна десятая, ".01" - одна сотая и т.д title - заголовок, по сути название сенсора, не используется нигде кроме визуальной составляющей unit - описание, задумывался как индикатор единиц измерения Теперь опишем функцию, которая будет вызываться каждый раз, когда требуется обновить данные по текущему сенсору. float get_rssi() { return wifi.isConnected() ? WiFi.RSSI() : 0; } Вообще её можно упростить до следующего вида, но только для примера float get_rssi() { return WiFi.RSSI(); } К данной функции есть очень строгие требования и это не просто так: Функция обязана возвращать числовое значение с типом float Функция не может принимать никаких параметров. Все с чем она работает должно быть объявлено в глобальной области видимости (в основном файле и ВНЕ функций setup и loop, для простоты понимания) или в самой функции. С чем связаны эти тонкости. В первую очередь мы работаем с числовыми данными, мы можем использовать их для каких-либо расчетов и т.п. Позволю себе небольшое отступление - вообще использование типа float это плохой тон, но в первой версии метеостанции, где использовался тип int и ему подобные, люди сталкивались с большими трудностями и много путались. Все данные, в том числе и с плавающей точкой хранились как целые числа и на определенном этапе работы с ними требовалось произвести математические действия, по сути умножение и деление на нужное для каждого сенсора значение - 10, 100, 1000 и т.д Хранимые и обрабатываемые данные микроконтроллером преобразовывались в целочисленные, это позволяло производить все операции максимально быстро и требовало меньше затрат памяти, а в web интерфейсе производилось их преобразование в значения с типом float, если вообще это преобразование требовалось. Перейдя в дальнейшем на тип float мы усложнили жизнь микроконтроллеру, но лично мое субъективное мнение, что это допустимая жертва в пользу упрощения кода для других людей. И замечу, что все вопросы по ошибкам преобразования и хранения данных ушли. Что касаемо параметров функции. Их нет потому что не реально предсказать какие данные захочет передать человек. Конечно есть различного рода хитрости, но они не тянут на полноценное решение. Возможно более опытные товарищи смогут задать вектор мысли, но на мой взгляд, проще придерживаться простых правил. Осталось затронуть метод add принадлежащий объекту sensors, но т.к метод имеет много переопределений, которые можно посмотреть в том же файле sensors.h, мы рассмотрим его совместно с описанным выше кодом. /* Описание сенсора для его визуализации плагином knob в web интерфейсе */ knob_t *R = new knob_t(-100, 0, "1", "RSSI", "dbm"); /* Функция, описывающая как получить полезные данные от сенсора */ float get_rssi() { return wifi.isConnected() ? WiFi.RSSI() : 0; } /* Так мы объявляем новый сенсор и указываем основной программе, что это и как с этим работать */ sensors.add(R, device::in, "rssi", get_rssi); Что мы передаем в параметрах метода add: R - указатель на объект knob с описанием всего необходимого для отрисовки сенсора в web интерфейсе одноименным плагином device::in - идентификатор указывающий к какой группе сенсоров относится этот rssi - идентификатор датчика, может содержать только латинские буквы, цифры и знак подчеркивания. Используется java скриптами web интерфейса. get_rssi - имя функции которая будет вызываться для обновления данных Когда нет необходимости в создании отдельной функции для сбора данных с сенсора, как с данным сенсором ведь его код очень мал и не требует дополнительных библиотек или математических преобразований, можно заменить имя функции на лямбда-выражение. [&](){ return wifi.isConnected() ? WiFi.RSSI() : 0; } И получим что-то похожее на начальный код /* Описание сенсора для его визуализации плагином knob в web интерфейсе */ knob_t *R = new knob_t(-100, 0, "1", "RSSI", "dbm"); /* Так мы объявляем новый сенсор и указываем основной программе, что это и как с этим работать */ sensors.add(R, device::in, "rssi", [&](){ return wifi.isConnected() ? WiFi.RSSI() : 0; }); Это один из множеств вариантов как добавить новый датчик или что-то еще в код метеостанции. Я настоятельно советую просмотреть Примеры использования плагина knob http://anthonyterrien.com/demo/knob/ Исходники с описанием плагина knob https://github.com/aterrien/jQuery-Knob Немного С++ с описанием лямбда-выражений https://msdn.microsoft.com/ru-ru/library/dd293608.aspx И обязательно изучите файл sensors.h в исходниках метеостанции, там много важной информации. Уверен, что теперь Вы увидите ошибки и сможете их поправить. Силами плагина Knob никак, он предназначен только для визуализации числовых данных, но Вы можете схитрить. Смотрите в сторону обработки вашей функции на стороне браузера. В файле index.htm имеется описание функции, вызываемой каждый раз, когда требуется обновить данные сенсоров в web интерфейсе. Простите за давнишнюю опечатку в имени функции, но это тот момент, когда исправление только навредит. function chenge(fast) { if(allowAjaxConnection || fast) { $.ajax({ dataType: "json", url: domain + "api/sensors" + ($(".settings #sl-system").is(":visible") ? "?system=true" : ""), type: "GET", cache: false, timeout: 3000, success: function(data) { $.each(data, function(name, value) { if (name !== 'system') animate("." + name, value); }); if (data.system) apiSetSystemInfo(data.system, true); //$('.out_temperature').trigger('configure', {"fgColor":"#FF0000"}); } }); } setTimeout(chenge, 5000); } Это примитивная функция, в которой нас интересует цикл во время работы которого происходит обращение к каждому графическому элементу, отвечающему за отображение данных. Я выделю её визуально чуть подробнее. $.each(data, function(name, value) { if (name !== 'system') animate("." + name, value); }); В данной коде мы получаем имя (идентификатор) каждого сенсора и его последние показания. Вы можете видеть, что имеется проверка на имя, совпадающее с 'system', если совпадение найдено, то функция animate вызвана НЕ будет. Это прекрасный пример того, как можно выловить нужный Вам сенсор. $.each(data, function(name, value) { if (name !== 'system') animate("." + name, value); /* Ищем нужный нам сенсор */ if (name === 'rssi') { var description; if (value > 50) description = 'плохой'; else description = 'хороший'; /* Выводим текст куда ни-ть */ $("input." + .name).parent(".sensor").find(".unit").text(description); } }); В теории текст должен появиться в области описания единиц измерения, но это нужно перепроверять т.к код написан в слепую. В идеале было бы лучше создать отдельный вид сенсоров для визуализации текстовой информации, но это тема для полноценного поста и обновления, поэтому не будем пока это затрагивать. Ну и наконец я дам Вам еще одну идею. Не всегда текст бывает наглядным выводом информации, особенно если он на определенном удалении от наблюдателя. Воспользуйтесь цветовой индикацией. Цвета от зеленого до красного прекрасно сигнализируют о качестве воздуха и очень наглядны. А в коде функции chenge (опять извиняюсь за её имя) имеется подсказка как менять цвет визуального элемента сенсора в web интерфейсе. //$('.out_temperature').trigger('configure', {"fgColor":"#FF0000"}); Все, что Вам требуется, это изменить указанный чуть ранее код таким образом, чтобы можно было заменить "#FF0000" на переменную содержащую HEX код цвета необходимого для индикации показаний, попадающих в установленный придел для конкретного сенсора. var color = "#FF0000"; $('.' + name).trigger('configure', {"fgColor":color});
  21. Kitsum

    Метеостанция на ESP8266 от it4it.club

    Доброе время суток. @post125 Я не вижу причин не позволяющих реализовать то, что Вы задумали. Конечно есть нюансы, но они будут всегда. В первую очередь стоит разбить весь перечень датчиков на группы соответствующие той шине которую будет использовать тот или иной датчик. Это даст представление о количестве необходимых портов микроконтроллера. В Вашем случае используется: I2C (2 порта) 1-Wire (1 порт) NRF (зависит от реализации подключения) С первыми двумя все понятно, главное помнить что на шине I2C не могут работать два устройства с одним адресом. А вот с NRF все не так просто т.к используется SPI шина и она подразумевает наличие 4-х свободных портов, но если мы будем только слушать, то в теории можно задействовать только 2. Также скорее всего понадобится еще один порт для IRQ сигнала, так мы будем работать с NRF только в том случае, если что-то есть в эфире. При такой реализации Вам придется отказаться от управления нагрузкой со стороны ESP8266. Другой вариант подключения NRF24 и ESP8266, который я бы использовал в рамках данного проекта, это отказ от SPI шины в пользу I2C. Но для этого понадобится контроллер посредник, например ATmega328 к которому по SPI шине подключается NRF24, а сам контроллер ATmega висит в качестве Slave устройства на I2C шине ESP8266. Логику работы вижу в виде сбора данных контроллером посредником со всех устройств в эфире которые передают телеграмму определенного формата. В телеграмме должны передаваться как минимум: Уникальный идентификатор устройства, например значение с типом uint8_t Уникальный идентификатор сенсора (uint8_t), если их несколько, например гирлянда из датчиков DS18B20 Данные с сенсора, пусть это будет int16_t Дополнительно можно передавать: Тип сенсора, но необходимо заранее составить таблицу типов и придерживаться ею в будущем при добавлении новых устройств в эфир, при необходимости расширять таблицу Информацию о заряде аккумулятора, если таковой используется Контрольную сумму Сам контроллер посредник при получении телеграммы обновляет в оперативной памяти данные по передающему сенсору. Если сенсор раньше не появлялся в эфире, то под него выделяется память. Если сенсор долгое время не передает показания, допустим три дня, он удаляется из памяти. Конечно понадобится ограничение на размер самой "таблицы", допустим 100 передатчиков, а при достижении этого порога игнорировать новые устройства, а то оперативная память может закончиться. Далее уже в ESP8266 реализовать обмен данными с ATmega по I2C шине и просто запрашивать данные из таблицы, благо все идентификаторы нам и так известны. Читать данные, двигать запятую, если требуется и получаем удовольствие. В таком варианте весь текущий функционал проекта останется в работоспособном состоянии, в том числе и управление нагрузкой. Дополнительных портов выделять не потребуется, как и освобождать уже задействованные. Программу для посредника обновлять не потребуется, а добавление новых устройств также сведется к созданию самих устройств и добавлению их со стороны ESP. Добавление можно автоматизировать, но это кому как удобно. Что касаемо хранения логов, то от SD карты я бы посоветовал отказаться в пользу центрального сервера, который Вы упомянули в п.9. Тем более, при наличии сервера, можно хранить данные в полноценной СУБД, той же MySQL, с удобными выборками и онлайн доступом откуда угодно. А вот SD карта опять потребует использования SPI, возвращаемся к дележке портов, на обработку логов потребуется время, да и сама карточка может выйти из строя, что само по себе не приятно и может привести к сбоям в работе программы ESP8266. В общем памяти у Вас на все это хватит, при условии, что Вы разумно подойдете к логированию показаний для которых строятся графики силами самой метеостанции. И присмотритесь ко второму варианту подключения NRF, он интереснее и намного более практичнее в долгосрочной перспективе. @Devilisimo рад, что у Вас все получилось. @Devilisimo Вам потребуется модифицировать интерфейс web страницы, в принципе это не сложно, главное придумать как визуализировать выбор списка датчиков. Но для начала давайте разберемся как реализован выбор в коде микроконтроллера. Вот пример одного из программных сенсоров метеостанции, отображающих уровень WiFi сигнала. sensors.add(new knob_t(-100, 0, "1", "RSSI", "dbm"), device::in, "rssi",[&](){ return wifi.isConnected() ? WiFi.RSSI() : 0; }); За выбор страницы где будет отображен индикатор отвечает значение одного из параметров, в данном случае это device::in Что указывает на принадлежность сенсора к внутренней группе датчиков. Список доступных обозначений описан в классе device в файле sensors.h как тип list_t class device { public: typedef enum list_t {out = 1, in = 2}; /* ... */ }; это сделано для того, чтобы исключить ошибку с указанием порядкового номера для не существующего списка сенсоров в самом web интерфейсе. Вам необходимо расширить его с указанием порядковых номеров для новых групп (помните, что они должны быть описаны в файле index.htm). Теперь переходим к самому web интерфейсу, описанному в файле index.htm Слои (группы) на которых располагаются индикаторы в первую очередь описаны в секции с html кодом в блоке div с классом mainContainer <div class="mainContainer"> <!-- лишнее удалено --> <div class="sensorsContent" hidden> <!-- лишнее удалено --> <div id="list1"></div> <div id="list2" hidden></div> <!-- лишнее удалено --> </div> <!-- лишнее удалено --> </div> В данном случае числовая часть имен list1 и list2 соответствует числовому значению, которое скрыто за именами out и in см. чуть выше. Если вы добавите новое значение, например, какую ни-ть комнату, пусть это будет ванная typedef enum list_t {out = 1, in = 2, bathroom = 3}; то необходимо добавить новый слой для визуализации <div id="list1"></div> <div id="list2" hidden></div> <div id="list3" hidden></div> Далее отработает java функция sensorsStructure которая разместит сенсоры помеченные как device::bathroom на слое с идентификатором list3 Это реализовано через обновление содержимого div $(".sensorsContent #list" + param.list).append(sensor); В текущем проекте используются две группы для визуализации и переключение между ними реализовано по событию клика по соответствующей иконки $(".menu #sensors").click(function() { var list = $(this).attr("class"); switch (list) { case 'list1': $("#list1").fadeToggle('slow', function(){ $("#list2").fadeToggle('slow'); }); break; case 'list2': $("#list2").fadeToggle('slow', function(){ $("#list1").fadeToggle('slow'); }); break; } $(this).toggleClass("list1", !$(this).hasClass("list1")).toggleClass("list2", !$(this).hasClass("list2")); }); Но это вариант Вам не подойдет и необходимо придумать иной способ визуализации. Или модифицировать имеющийся переключатель с добавлением нового пункта и реализовать это все в виде циклического перебора всего списка.
  22. Kitsum

    Метеостанция на ESP8266 от it4it.club

    Доброе время суток Обратите внимание, что используемые Вами порты для SoftwareSerial уже задействованы под управление нагрузкой при превышение определенных показаний. Найти их можно в файле gpio.h и в настройках web интерфейса, раздел "Контроль состояния GPIO". Для начала уберите управление нагрузкой с этих портов, закомментируйте в основном файле программы вызов функции gpio_12_13(); Далее я порекомендую проконтролировать что приходит в ответ на запрос данных с сенсоров. Для этого в браузере откройте режим разработчика и загрузите страницу метеостанции. Смотрите на запрос "sensors". Выглядеть это должно примерно так. Можно вывести в консоль данные о поэтапной работе функции чтения данных с сенсора mh-z19 readCO2(); Также можно упростить инициализацию датчика CO2 и выбросить лямбда-выражение указав в качестве последнего аргумента функцию чтения данных с сенсора. sensors.add(PPM, device::in, "co2_ppm", readCO2); И не используйте пробельные символы для задания внутреннего имени датчика в web интерфейсе. В Вашем случае замените "CO2 ppm" на "co2_ppm", как это было показано выше при инициализации датчика. Допустимо использовать пробельные символы только для указания видимого имени сенсора, это делается через объект knob_t knob_t *PPM = new knob_t(-400, 5000, ".1", "CO2", "ppm"); Идентификатор датчика указывается как класс для объекта сенсора в web интерфейсе, а имена классов не допускают наличия пробельных символов т.к они являются разделителями имен. Таким образом задав имя "CO2 ppm" у нашего сенсора появятся два отдельных класса, это "CO2" и "ppm", что не позволит найти интересующий нас объект. Внесите эти поправки, и я уверен, что данные появятся. В первую очередь за ведение логов с сенсора отвечает последний параметр метода add от класса sensors, посмотрите файл sensors.h class sensors { public: bool add(knob_t *knob, device::list_t list, byte address, const char *name, device::initFn_t init, device::dataFn_t data, bool log); bool add(knob_t *knob, device::list_t list, byte address, const char *name, device::dataFn_t data, bool log); bool add(knob_t *knob, byte address, const char *name, device::initFn_t init, device::dataFn_t data, bool log); bool add(knob_t *knob, byte address, const char *name, device::dataFn_t data, bool log); bool add(knob_t *knob, device::list_t list, const char *name, device::dataFn_t data, bool log); bool add(knob_t *knob, const char *name, device::dataFn_t data, bool log); /* ... */ byte logSize = 144; } sensors; Если параметр bool log принимает значение true, то будет выделена память для массива типа float с размером, указанным в переменной logSize. Каждый новый сенсор является объектом типа device. По умолчанию память не выделяется. class device { public: /* ... */ device(knob_t *knob, list_t list, byte address, const char *name, initFn_t init, dataFn_t data, byte log, device *next) { /* ... */ this->log = log ? new float[log]{0} : 0; /* ... */ } /* ... */ float *log; /* ... */ }; За автоматическое наполнение массива данных отвечает задача в планировщике вызывающая метод logUpdate класса sensors. cron.add(cron::time_10m, [&](){ sensors.logUpdate(); }, "httpSensorsLog"); // Обновление журнала (httpSensorsLog - не обязательный уникальный ID для быстрого поиска задания другими программными модулями) По сути происходит перебор всех сенсоров, запись новых значений в логический конец массива и смещение логического конца массива. Теперь переходим к самому сложному, это web интерфейс и построение суточного графика. В файле index.htm имеется функция описывающая модель графика с помощью плагина Highcharts function chart() { graph = Highcharts.chart('graph24h', { yAxis: [ /* ... */ ], series: [ /* ... */ ] }); } По аналогии с уже описанными линиями данных для других сенсоров можно добавить новый параметр. Обратите внимание на параметр yAxis для объекта series, он уникален для каждой линии данных и содержит порядковый номер соответствующего ему объекта yAxis описанного в начале функции. Это может выглядеть сложно, но это не так. Вы можете найти всю документацию по плагину на официальном сайте https://www.highcharts.com/ Теперь останется только наполнить данными суточный график. За это отвечает обработчик висящий на событии клика по иконке суточного графика. $("#graph").click(function() { /* ... */ }); Добавление массива данных для всех сенсоров идентичны и выглядит примерно так, я приведу пример из своей домашней метеостанции для датчика eCO2 с идентификатором out_co2 graph.series[4].update({ animation: animation, data: obj.out_co2, pointStart: pointStart, pointInterval: pointInterval }, false); Самое главное, на что стоит обратить внимание, это порядковый номер series для которого предназначены эти данные. В данном случае series[4] Нумерация начинается с 0 и описывалась в упомянутой ранее функции chart() в секции series PS: отмечу, что в коде я не умышленно оставил опечатки, за что искренне прошу прощения и советую внимательно все перепроверять.
  23. Kitsum

    Мониторинг триггеров в GUI под Windows

    Если Вы имеете в виду интервал между запросами информации, то в файле config.ini, который располагается в корне самого клиента, имеется параметр, отвечающий за интервал между запросами данных в секундах. update="60" Но имеется еще и ограничение в серверной части т.к данные кэшируются для уменьшения нагрузки при массовом обновлении информации на клиентах. Управлять временем жизни кэша на сервере можно с помощью параметра в файле index.php $cacheInterval = 60; Время жизни кэша также указывается в секундах.
  24. Kitsum

    Мониторинг триггеров в GUI под Windows

    @mrmarkalex в используемой Вами версии Zabbix отсутствует возможность построения изображений, в частности карт сетей, в виде растровой графики, что делает "парсинг" картинок посредством curl не актуальным. Стоит поискать в сети упоминания об актуальных способах для Zabbix v3.4 и выше, возможно есть экспорт графиков и карт в API или альтернативные способы описывались в интернете, это нужно проверять, просмотреть актуальную документацию.
  25. Kitsum

    Мониторинг триггеров в GUI под Windows

    @mrmarkalex каталог на который Вы ссылаетесь используется самим Zabbix, хранить там что-то постороннее не стоит. Для теста используйте каталог, прописанный в VirtualHost начальной конфигурации Apache, если конечно Вы используете Apache, я буду думать, что так оно и есть. Например, для Ubuntu Server путь можно посмотреть в /etc/apache2/sites-enabled/000-default.conf а интересующий нас каталог прописан как DocumentRoot /var/www/html Вот по этому адресу и создайте каталог с любым именем и в нем разместите index.php с содержимым указанным Выше. Также у Вас должен быть установлен PHP и модуль к нему pdo_mysql PS: Помните, что в каждой системе могут быть свои пути и конфигурационные файлы.
×
×
  • Создать...