API для передачи показаний
Общие сведения и ограничения передачи показаний датчиков
Передавать показания датчиков можно посредством протоколов TCP/UDP (в большинстве случаев) или HTTP(S) GET/POST (для начинающих или с шифрованием), а также MQTT (для приборов с обратной связью) и JSON для одновременной передачи данных сразу нескольких приборов и интеграции с другими системами мониторинга. Максимальный размер пакета данных 4 КБ для TCP/POST, 2 КБ для GET, 512 байт для UDP (ограничение MTU).
Если с момента TCP подключения прошло 10 секунд (кроме MQTT), то такие подключения закрываются принудительно, поэтому настоятельно рекомендуем сперва опросить все датчики на вашем приборе, записать их показания в буфер, а только потом устанавливать подключение и передать пакет данных на сервер.
Данные обрабатываются и загружаются в базу пакетно 1 раз в минуту (команды MQTT немедленно), соответственно и показания датчиков также обновляются ежеминутно. При отправке показаний чаще чем 1 раз в минуту прибор попадает в бан до устранения проблемы его владельцем.
Допустимый интервал записи показаний датчиков в историю (для построения графиков, выгрузки во внешние системы и CSV) составляет 5 минут и может быть уменьшен для партнеров и коммерческих клиентов.
Запрещается разглашать свои уникальные MAC-адреса приборов и датчиков на сторонних ресурсах и при публикации исходных кодов для передачи показаний на narodmon.ru следует их маскировать во избежание проблем слепого копирования чужого кода среди новичков и, как следствие, конфликтов уникальности MAC в проекте.
Как отладить отправку данных с прибора
В процессе разработки новых приборов нередко возникает необходимость отладить его протокол передачи показаний с целью обнаружения и исправления ошибок в нем, но как быть, если лимит приборов в проекте не позволяет вам это сделать ?
1. Если ваш прибор находится в вашей домашней/офисной сети и стало быть имеет тот же публичный IP адрес, что и ваш браузер, то для отладки вы можете воспользоваться разделом сайта Профиль \ Данные с моего IP (после авторизации) или же по короткой ссылке narodmon.ru/me
2. Если же вы отлаживаете прибор, подключенный к мобильному интернету (т.е. его публичный IP не совпадает с вашим браузером), то вы можете воспользоваться ссылкой вида:
narodmon.ru/dev/DEVICEMAC
* DEVICEMAC заменить на MAC вашего прибора (без : и -) в любом регистре. Если прибор уже зарегистрирован в проекте, то читаем далее п.3.
3. Для успешно зарегистрированных приборов отладочная информация находится в разделе сайта Датчики \ Настройка \ данные, полученные от прибора.
PS В отладочной информации доступны данные обо всех пакетах данных полученных сервером за последние пару часов от вашего прибора, а также ошибках в его протоколе (если таковые имеются). Если же этих данных нет, значит или IP/MAC прибора отличается от указанного вами или у прибора нет доступа в Интернет (неверно настроен или не оплачен).
Перечень типичных ошибок в ответе сервера:
* INTERVAL...<5m - прибор передает данные чаще, чем ему дозволено (по умолчанию 5 минут).
* Sensor...invalid value... - датчик передал на сервер недопустимое показание (например буквы вместо цифр).
* Sensor...out of range... - датчик передал показание за пределами допустимого диапазона для его типа данных.
* ...is too big - датчик передал слишком большое показание.
* UnixTime > NOW - указанное время в UnixTime (UTC+0) показания больше текущего.
* MAC_MISSED - пропущена метрика датчика или MAC (серийный номер) прибора.
* Device MAC...is invalid - недопустимый MAC (серийный номер) прибора.
* ##_MISSED_AT_THE_END - отсутствует признак конца пакета данных ## (пакет обрезался при отправке).
* BANNED - прибор заблокирован владельцем или администратором.
* IP binding enabled. Data from...is ignored - у прибора включена привязка к IP, но данные поступают с другого IP и поэтому игнорируются (возможно провайдер сменил Ваш IP или обнаружен конфликт уникальности MAC приборов).
Данные, необходимые для передачи на сервер проекта
Поле MAC (ID) - уникальный идентификатор прибора в проекте
Чаще всего состоит из 12-18 символов A-Z и 0-9 иногда разделенных '-' или ':'.
Предназначен для идентификации прибора (и поставщика по префиксу) в проекте и его привязки к владельцу и к карте в разделе Датчики.
Разработчикам приборов рекомендуется использовать персональный префикс для своих приборов для обеспечения уникальности в проекте и установления авторства, а также избегать часто повторяющихся знаков как в примере ниже.
TCP/UDP:
#00:00:00:00:00:00
...
##
GET/POST:
id=00:00:00:00:00:00&...
Поле NAME - название прибора в проекте
Необязательное к передаче название прибора в кодировке UTF-8 или Windows-1251 по факту переименования. Передается в TCP/UDP в 1й строке после MAC прибора и разделителя #, а в GET/POST передается отдельным параметром NAME. Рекомендуется для приборов с веб-интерфейсом или с утилитой конфигурации, в которых можно указать алиасы (названия).
TCP/UDP:
#MAC#Название
...
##
GET/POST:
ID=MAC&NAME=Название&...
Поле OWNER - владелец прибора в проекте
Необязательное к передаче поле (на выбор: USER, LOGIN, OWNER), содержащее логин или e-mail или мобильный номер владельца прибора в Профиле участника проекта для автоматической регистрации прибора. Передается в виде отдельной метрики виртуального датчика с текстовым значением. Учитывается 1 раз для автоматической привязки ничейных приборов к учетной записи в проекте и не подходит для смены текущего владельца прибора.
TCP/UDP:
#MAC
#OWNER#UserName
...
##
GET/POST:
ID=MAC&OWNER=UserName&...
Поля LAT,LON,ALT - широта, долгота, высота местоположения прибора
Необязательные к передаче геокоординаты местоположения прибора в десятичном виде!
Передаются отдельными метриками виртуальных датчиков LAT, LON, ALT.
Может быть полезно для мобильных приборов с GPS/ГЛОНАСС и подключенными к ним датчиками.
TCP/UDP:
#MAC
#LAT#27.102531
#LON#-72.796055
#ALT#262
...
##
GET/POST:
ID=MAC&LAT=27.102531&LON=-72.796055&ALT=262...
Для GSM и WiFi приборов можно использовать специальные метрики AP* и BS* для приблизительного местоположения по вышкам сотовой связи и/или точек доступа WiFi. Средняя погрешность 100м - 10км, что значительно точнее GeoIP.
Чем больше подобных метрик передадите в пакете данных, тем точнее определение местоположения.
TCP/UDP:
WiFi BSSID = 00:00:00:00:00:00 и RSSI = -70:
#AP:00:00:00:00:00:00#-70
GSM MCC(000h) + MNC(000h) + LAC(0000h) + CID(0000000h) и RSSI = -50:
#BS:000:000:0000:0000000#-50
Поля mac1..macN - уникальные метрики датчиков подключенных к прибору
Предназначены для идентификации датчиков и привязки их показаний к приборам.
Регистрация всех датчиков, подключенных к прибору, происходит автоматически при первой отправке их показаний на narodmon.ru.
Для датчиков температуры семейства DS18x20 метрика(серийный номер) представляет собой 16 знаков 0-F.
Для прочих датчиков рекомендуется использовать следующие метрики для автоматического определения типа данных (* - любое число):
* Температура: T*, TEMP*, BMPT*, DHTT*, DSW*, DS18T*, TEMPC, BATTEMP
* Влажность: H*, RH, RH*, DHTH*, HUM, HUMID
* Давление: BMPP*, MMHG, HPA, PRESS
* Осадки: RAIN, RAIN*
* Скорость(ветер): WS, WS*, KMH, WIND
* Азимут(направление): DEG, DIR
* Напряжение: U*, V*, VOLT, VCC, UACC, VBAT, BATVOLT
* Сила тока: I*
* Мощность: P, P*, W, W*
* Электроэнергия: WH, KWH, WH*, KWH*
* Водосчетчики: WM, WM* (ХВС=CWM, ГВС=HWM)
* Освещенность: L*, LUX, LIGHT
* Радиация: R*, RAD
* Логический(реле): S*, RL*, GPIO*, OUTPUT*, SIM*, RELAY
* Сетевой трафик: RX, TX, RX*, TX*
* Концентрация: CO, CO2, CO*, CH4, PPM
* Время(работы): NOW, TIME, UPTIME, CURTIME, WORKTIME
* Сигнал(уровень): DBM, RSSI, WIFI, GSM, SIGNAL
* Индекс УФ: UV, UV*
* Заряд батареи: MB2BAT, BATCHARGE
* Пыль(частицы): PM, PM*, DUST
* Точка росы: DP, DP*, DEW
* Местоположение: LAT, LON, ALT (широта, долгота, высота) размещения датчиков.
Можно указать в качестве метрики название датчика на латинице без пробелов и знаков, но в этом случае тип данных придется указать вручную в разделе Датчики \ Настройка.
TCP/UDP:
#MAC
#T1#00.00
...
##
GET/POST:
ID=MAC&T1=00.00&...
Поля value1..valueN - показания датчиков с точностью до сотых долей
Крайне не рекомендуется округлять показания дабы не получать ложные уведомления выходе из строя датчика и график показаний был более читабельным, дискретность у DS18B20 = 0.0625С
Десятичное значение со знаком с точностью до 0.01. Дробная часть отделяется точкой, хотя запятая тоже допускается. Пример показания: -13.54 или -13,54 или 760 (для атм.давления).
Атмосферное давление следует передавать в мм рт.ст. или в Па/гПа, в последнем случае показания будут автоматически переведены в мм рт.ст. для отображения на карте.
Сетевой трафик SNMP можно передавать как в Мбит/сек (Mbps) так и накопительный итог в байтах(октетах) выбрав тип датчика трафик, Rx/Tx будет автоматически пересчитан в Mbps.
TCP/UDP:
#MAC
#T1#00.00
...
##
GET/POST:
ID=MAC&T1=00.00&...
Поля time1..timeN - время актуальности показаний
Если показания датчиков передаются сразу после замера, то данный параметр передавать не нужно!
Необязательное к передаче целочисленное значение UnixTime или по стандарту ISO 8601.
Пример: 1438772570 или 2015-08-05T14:03:11+03:00 или в hex виде 55C1ED5A (для экономии).
При передаче UnixTime НЕ НАДО прибавлять свой часовой пояс, т.к. оно всегда по UTC+0.
Местное время передавать "как есть" НЕЛЬЗЯ ибо у сервера часовой пояс Europe/Moscow.
Время снятия показаний нужно передавать только в случае их кеширования перед отправкой или при массовой выгрузке показаний датчиков.
TCP/UDP:
#MAC
#T1#00.00#1710764591
...
##
GET/POST:
ID=MAC&T1=00.00&TIME=1710764591&...
Поля name1..nameN - названия датчиков
Необязательное к передаче название датчика в кодировке UTF-8 или Windows-1251 по факту переименования однократно. Передается только в TCP/UDP после показания датчика и timeN(если указано).
Рекомендуется для приборов с веб-интерфейсом или с утилитой конфигурации, в которых можно указать названия датчиков. В случае, если данный параметр не пустая строка и не является временем, то название датчика на сервере меняется на полученное от прибора.
TCP/UDP:
#MAC
#T1#00.00#ИмяДатчика
...
##
Передача показаний по протоколам TCP/UDP на narodmon.ru:8283
Если Ваш прибор допускает только ввод IP адреса или у Вас проблемы с DNS, то используйте любой IP из списка nslookup narodmon.ru до которого у Вас наименьший ping, но помните, что IP-адрес сервера может сменится, а DNS-имя - нет. TCP также можно использовать для массовой загрузки показаний на сервер "задним числом" путем передачи в одном пакете данных показаний датчика в разные моменты времени, но не более 4КБ на пакет для TCP и 512 байт для UDP. Предпочтительно отправлять показания всех датчиков в одном пакете данных для минимизации издержек на инициализацию соединения с сервером и импорт показаний датчиков.
Ответ сервера при успешной отправке будет OK (или текст ошибки или команда на исполнение), что рекомендуется использовать в качестве подтверждения получения данных, а при отсутствии ответа повторить отправку когда восстановится связь с сервером. При сообщениях об ошибках НЕ ПОВТОРЯТЬ!
Конец строки ответа сервера завершается спецсимволом \n код 10(0A). Для оперативного отслеживания состояния логических входов и выходов рекомендуется в ответ на получение команды от сервера возвращать новое состояние логических датчиков в уже открытый ранее сокет согласно протоколу, но только в случае изменений дабы не получить ошибку малого интервала показаний.
При использовании протокола UDP ответа сервера не последует.
Три датчика реалтайм: #F6-F1-78-D6-75-F1 #T1#28.35 #H1#32 #P1#726.52 ## |
Формат пакета данных: #MAC[#NAME]\n #mac1#value1[#time1][#name1]\n ... #macN#valueN[#timeN][#nameN]\n ## |
Загрузка истории показаний: #F6-F1-78-D6-75-F1 #T1#28.35#1710764591 #T1#-0.18#1710763991 #T1#28#1710763391 ## |
C названием и координатами: #F6-F1-78-D6-75-F1#Метео #OWNER#boss2 #T1#28.35#Улица #T2#28#Дом #P1#726.52#Барометр #LAT#27.102531 #LON#-72.796055 #ALT#755 ## |
\n - спецсимвол конца строки - код 10(0A).
## - признак окончания пакета данных (после него разрыв соединения), в [..] заключен необязательный параметр.
Пример передачи показаний по TCP на PHP
$fp = @fsockopen("tcp://narodmon.ru", 8283, $errno, $errstr);
if(!$fp) exit("ERROR(".$errno."):".$errstr);
fwrite($fp, "#07-21-75-3D-9C-FE\n#T1#-21.38\n#H1#78\n#P1#707.81\n##");
fclose($fp);
Пример передачи показаний по TCP на Bash
#!/bin/bash
# by Tuinov Andrey Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в браузере должен быть включен Javascript.
SERVER="narodmon.ru"
PORT="8283"
# MAC адрес прибора. Заменить на свой!
DEVICE_MAC="A0B1C2D3E4F5"
# идентификатор прибора, для простоты добавляется 01 (02) к MACприбора
SENSOR_ID_1=$DEVICE_MAC"01"
SENSOR_ID_2=$DEVICE_MAC"02"
# значения датчиков
sensor_value_1=20
sensor_value_2=-20.25
# устанавливаем соединение
exec3<>/dev/tcp/$SERVER/$PORT
# отсылаем единичное значение датчика
printf "#%s\n#%s#%s\n##" "$DEVICE_MAC" "$SENSOR_ID_1" "$sensor_value_1" >&3
# отсылаем множественные значения датчиков
#printf "#%s\n#%s#%s\n#%s#%s\n##" "$DEVICE_MAC" "$SENSOR_ID_1" "$sensor_value_1" "$SENSOR_ID_2" "$sensor_value_2" >&3
# получаем ответ
read -r MSG_IN <&3
echo "$MSG_IN"
# закрываем соединение
exec 3<&-
exec 3>&-
Пример передачи показаний по TCP на Python2
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
# by Roman Vishnevsky Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в браузере должен быть включен Javascript.
import socket
# MAC адрес прибора. Заменить на свой!
DEVICE_MAC = 'A0B1C2D3E4F5'
# идентификатор прибора, для простоты добавляется 01 (02) к mac прибора
SENSOR_ID_1 = DEVICE_MAC + '01'
SENSOR_ID_2 = DEVICE_MAC + '02'
# значения датчиков, тип float/integer
sensor_value_1 = 20
sensor_value_2 = -20.25
# создание сокета
sock = socket.socket()
# обработчик исключений
try:
# подключаемся к сокету
sock.connect(('narodmon.ru', 8283))
# пишем в сокет единичное значение датчика
sock.send("#{}\n#{}#{}\n##".format(DEVICE_MAC, SENSOR_ID_1, sensor_value_1))
# пишем в сокет множественные значение датчиков
# sock.send("#{}\n#{}#{}\n#{}#{}\n##".format(DEVICE_MAC, SENSOR_ID_1,
sensor_value_1, SENSOR_ID_2, sensor_value_2))
# читаем ответ
data = sock.recv(1024)
sock.close()
print data
except socket.error, e:
print('ERROR! Exception {}'.format(e))
Пример передачи показаний по TCP на Python3 для Domoticz
# Скрипт с помощью модуля Питона request и запроса json запрашивает
# данные избранного датчика у Domoticz и отправляет часть из них на
# сервис Народный мониторинг (narodmon.ru)
# Авторы tudimon, bigmak, Maker39 @ 4PDA
# подключаем модули
import requests
import socket
ip = '127.0.0.1' # ip-адрес Domoticz
port = '433' # порт
user = 'dz_user' # пользователь Dz
password = 'dz_user_password' # пароль пользователя
idx = 66 # номер датчика в Domoticz, который будем опрашивать
# Строка запроса если нужна авторизация
#get_url = 'http://'+user+':'+password+'@'+ip+':'+port+'/json.htm?type=devices&rid={}'.format(idx)
# Строка запроса если не нужна авторизация
# в случае если скрипт выполняется на том же приборе что и Dz и в
# Настройки - Настройки - Система
# Локальные сети (без имени/пароля) указан ip адрес
get_url = 'https://'+ip+'/json.htm?type=devices&rid={}'.format(idx)
# раскомментировать если нужно строку вывести в консоль для контроля
#print ('================================')
#print (get_url)
#print ('================================')
# запрос данных избранного датчика
get_data = requests.get(get_url, verify=False).json()
# ключ verify=False пришлось добавить потому что у меня Dz работает только на 433 порту
# а SSL сертификат самоподписанный, соответственно request ругался на ошибку сертификата
# ответ придет в виде JSON, где необходимо выбрать интересующее поле,
# например температура, влажность и уровень заряда батарейки
humidity = get_data['result'][0]['Humidity']
temperature = get_data['result'][0]['Temp']
batt_level = get_data['result'][0]['BatteryLevel']
#Выведем данные в консоль pi
# когда скрипт отлажен, следующие три строки необходимо закомментировать
print ("Влажность " + str(humidity))
print ("Температура " + str(temperature))
print ("Заряд батарейки " + str(batt_level))
# ============== передача данных в сервис narodmon ==================
# MAC адрес прибора. Заменить на свой!
DEVICE_MAC = 'ffffffffffffff' # MAC dz Raspberry Pi
# идентификатор прибора
SENSOR_ID_1 = 'dz_t'
SENSOR_ID_2 = 'dz_h'
# значения датчиков, тип float/integer
sensor_value_1 = temperature
sensor_value_2 = humidity
# создание сокета
sock = socket.socket()
# обработчик исключений
try:
# подключаемся к сокету
sock.connect(('narodmon.ru', 8283))
# формируем строку для сокета при единичном значении датчика
#s_sock = ("#{}\n#{}#{}\n##".format(DEVICE_MAC, SENSOR_ID_1, sensor_value_1))
# формируем строку для сокета при множественном значение датчиков
s_sock = ("#{}\n#{}#{}\n#{}#{}\n##".format(DEVICE_MAC, SENSOR_ID_1, sensor_value_1, SENSOR_ID_2, sensor_value_2))
# Пишем строку с консоль для контроля
# эти три строки после отладки закомментировать
print('======================================')
print(s_sock)
print('======================================')
#Пишем в сокет
sock.send(s_sock.encode('utf8'))
# читаем ответ
data = sock.recv(1024)
sock.close()
except socket.error as e:
print('ERROR! Exception {}'.format(e))
Передача показаний по протоколу HTTP GET/POST на http(s)://narodmon.ru/get (/post) и TLS шифрование
Рекомендуется использовать только в случае, если доступ в Интернет осуществляется через прокси-сервер, т.к. возможны проблемы с кеширующими прокси и выше риск перехвата / подмены данных без шифрования, а также увеличивается время обработки данных в "часы пик" из-за большого числа посетителей сайта и мобильных клиентов, что практически никак не влияет на наш протокол TCP/UDP (описанный выше). Максимальная длина запроса до 4КБайт (4096 знаков).
Предпочтительно отправлять показания всех датчиков в 1 запросе для минимизации издержек на инициализацию соединения и обработку показаний.
Ответ сервера при успешной отправке будет OK (или текст ошибки), что рекомендуется использовать в качестве подтверждения получения данных, а при отсутствии ответа повторить отправку когда восстановится связь с сервером. При сообщениях об ошибках НЕ ПОВТОРЯТЬ!
Шифрование: если Вы подозреваете, что враги хотят перехватить/подделать показания ваших датчиков, то следует использовать в строке адреса https://narodmon.ru/post и передавать данные с TLS шифрованием (SSL устарел).
Образец запроса передачи показаний методом HTTP GET
Следует знать, что это самый простой способ для новичков, но небезопасный и ненадежный в плане легкости перехвата/подделки данных без шифрования и зависимости от нагрузки на веб-сайт проекта и API для приложений. Максимальная длина запроса 2 КБайт (2048 знаков).
Для включения TLS шифрования используйте адрес https://narodmon.ru/get?...
http://narodmon.ru/get?ID=MAC&mac1=value1&...&macN=valueN[&time=UnixTime][&name=название]
[&owner=владелец][&lat=широта][&lon=долгота][&alt=высота_над_морем]
Образец запроса передачи показаний методом HTTP POST
Следует знать, что надежность данного метода зависит от нагрузки на веб-сайт проекта и API для приложений в отличии от TCP, UDP и MQTT.
Максимальная длина запроса до 4 КБайт (4096 знаков). Для включения TLS шифрования используйте адрес https://narodmon.ru/post
POST http://narodmon.ru/post HTTP/1.0\r\n
Host:
narodmon.ru\r\n
Content-Type: application/x-www-form-urlencoded\r\n
Content-Length: NN(кол-во байт в
строке данных ниже)\r\n
\r\n
ID=MAC&mac1=value1&...&macN=valueN[&time=UnixTime][&name=название]
[&owner=владелец][&lat=широта][&lon=долгота][&alt=высота_над_морем]
Пример передачи показаний по HTTP POST на Python2
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
# by Roman Vishnevsky
aka.x0x01 @ gmail.com
import urllib2
import urllib
# MAC адрес прибора. Заменить на свой!
DEVICE_MAC = 'A0B1C2D3E4F5'
# идентификатор прибора, для простоты добавляется 01 (02) к mac прибора
SENSOR_ID_1 = DEVICE_MAC + '01'
SENSOR_ID_2 = DEVICE_MAC + '02'
# значения датчиков, тип float/integer
sensor_value_1 = 28
sensor_value_2 = -12.34
# формирование POST запроса дляединичного датчика
data = urllib.urlencode({
'ID': DEVICE_MAC,
SENSOR_ID_1:
sensor_value_1
})
# формирование POST запроса для 2х датчиков
# data =
urllib.urlencode({
# 'ID': DEVICE_MAC,
# SENSOR_ID_1: sensor_value_1,
# SENSOR_ID_2:
sensor_value_2
# })
# формирование заголовков запроса headers =
{
'Content-Length': str(len(data)),
'Content-Type': 'application/x-www-form-urlencoded',
'Host':'narodmon.ru'
}
# непосредственно запрос
request = urllib2.Request('http://narodmon.ru/post.php', data, headers)
response = urllib2.urlopen(request)
printresponse.headers
Пример передачи показаний по HTTP POST на PHP с cURL
$data = array('ID'=>'F6-F1-78-D6-75-F1', 'T1'=>28.35, 'H1'=>32, 'P1'=>726.52);
$ch = curl_init("http://narodmon.ru/post");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch,CURLOPT_POSTFIELDS, http_build_query($data));
$reply = curl_exec($ch);
curl_close($ch);
Пример передачи показаний по HTTP POST на PHP без cURL
$data = array('ID'=>07-21-75-3D-9C-FE, 'T1'=>-21.38, 'H1'=>78, 'P1'=>707.81);
$context = stream_context_create(array('http' => array('method'=>'POST','content' => http_build_query($data))));
$fp = @fopen("http://narodmon.ru/post", 'r', false, $context);
if($fp) { fpassthru($fp); fclose($fp); }
Передача показаний в формате JSON протоколами TCP/UDP narodmon.ru: 8283 или http(s)://narodmon.ru/json
Данный вид протокола является наиболее функциональным и будет наиболее полезен для владельцев нескольких приборов и для интеграции с уже имеющейся системой мониторинга дома или в офисе, т.к. позволяет в одном пакете данных передать данные сразу с нескольких устройств со всеми их атрибутами избавив от большого объема ручной работы поочередной регистрации и настройки их в проекте.
Передавать пакет данных можно как по протоколам TCP или UDP на порт narodmon.ru:8283, так и использоваться HTTP(S) POST с шифрованием TLS или без него на http(s)://narodmon.ru/json. Ограничения по размеру пакета аналогичное другим способам передачи: 4 КБайт (для UDP 512 байт из-за MTU).
Ответ сервера при успешной отправке, ошибке или при получении команд тоже будет в формате JSON, что рекомендуется использовать в качестве подтверждения получения данных, т.е. при отсутствии ответа от сервера повторить отправку когда восстановится связь. При сообщениях об ошибках НЕ ПОВТОРЯТЬ!
Примеры ответов сервера:
{"error":"OK","errno":200} - данные успешно получены, ошибок нет;
{"error":"INTERVAL < 1 min","errno":429} - слишком частая отправка данных;
{"error":"JSON_ERROR_SYNTAX","errno":400} - данные получены, но в них была ошибка.
Формат передаваемых данных JSON
Ниже приведен пример развернутой структуры пакета JSON со всеми возможными параметрами при передаче показаний датчиков (для экономии трафика можно записать все в 1 строку и удалить лишние пробелы). Обязательные параметры выделены жирным, остальные опциональные и их рекомендуем слать только при их изменении. После // указаны комментарии к параметрам, отправлять их на сервер разумеется не нужно.
{
"devices":
[
{
"mac": "DEVICE_MAC", // уникальный для проекта серийный номер прибора;
"name": "DEVICE NAME", // название прибора в кодировке UTF-8;
"owner": "USERNAME", // логин или email или сотовый владельца прибора для авторегистрации;
"lat": 27.102531, // широта места установки прибора;
"lon": -72.796055, // долгота места установки прибора;
"alt": 124, // высота над уровнем моря места установки прибора;
"sensors":
[
{"id": "T1", // метрика датчика, уникальная для прибора;
"name": "SENSOR NAME", // название датчика в кодировкеUTF-8;
"value": 00.00, // показание датчика;
"unit": "C", // единица измерения для датчика в UTF-8;
"time": 1710764591// время актуальности показания датчика UnixTime (UTC+0);
},
{ // прочие датчики на приборе
}
]
},
{ // прочие приборы }
]
}
Образец передачи показаний в JSON методом HTTP POST
Максимальная длина запроса до 4 КБайт (4096 знаков).
Для включения TLS шифрования используйте адрес https://narodmon.ru/json
POST http://narodmon.ru/json HTTP/1.0\r\n
Host: narodmon.ru\r\n
Content-Type: application/x-www-form-urlencoded\r\n
Content-Length: NN(кол-во байт в строке данных ниже)\r\n
\r\n
{ "devices": [{ "mac": "MAC", "sensors": [{ "id": "..", "value": 00.00 }, {..} ]},
{..} ]}
Передача показаний в формате InfluxDB по протоколу HTTP POST на http(s)://narodmon.ru/post
Данный вариант передачи показаний является расширением протокола HTTP POST для прошивок приборов с поддержкой временных рядов InfluxDB, например luftdaten.info для измерения качества воздуха (кол-во частиц пыли).
В качестве ID/MAC для регистрации прибора в проекте следует использовать значение узла node.
Пример формата (набор метрик датчиков может отличаться):
device,node=MAC SDS_P1=15.55,SDS_P2=6.57,BME280_temperature=6.37,BME280_pressure=99535.03,BME280_humidity=40.34,interval=300000,signal=-44
PS С подробным описанием процедуры подключения приборов с прошивкой luftdaten.info к нашему проекту вы можете ознакомиться в статье Алексея Надёжина (ammo1) за что ему огромное спасибо!
Передача показаний по протоколу MQTT на narodmon.ru:1883 (бесплатно с ограничениями)
При бесплатном использовании сервер не будет поддерживать постоянные (keep-alive) соединения, т.е. будет постоянно сбрасывать подключение после приема пакета данных.
Данный способ передачи показаний достаточно сложен в реализации и требует более высокий уровень технической подготовки. Консультации и обучение по работе с ним не проводятся и при возникновении проблем с его использованием лучше перейдите на более простые протоколы описанные выше. Использование данного протокола оправдывает себя только со сложными устройствами с обратной связью, где требуется немедленная реакция на команды с сервера.
MQTT (Message Queuing Telemetry Transport) – открытый протокол, разработанный IBM специально для Интернета вещей и применяется для обмена данными между приборами. MQTT-сеть включает в себя MQTT-брокера, который служит посредником во взаимодействии MQTT-агентов – издателей и подписчиков. Издатели публикуют информацию, предназначенную для подписчиков. Подробное описание протокола изложено в спецификации MQTT Version 3.1.1.
MQTT является бинарным протоколом поверх TCP, что существенно сокращает объем передаваемых данных и крайне полезно в нестабильных низкоскоростных мобильных сетях. Кроме того, соединение с брокером(сервером) инициируется клиентским прибором, что позволяет работать и с "серыми" IP адресами (за NAT провайдера), при этом соединение с сервером как правило не разрывается (при стабильном канале), что позволяет максимально оперативно передавать показания датчиков и принимать команды на исполнение с сервера.
При настройке подключения по MQTT к нашему брокеру(серверу) следует указать хост narodmon.ru порт 1883. Интервал передачи показаний по умолчанию как и для других протоколов = 5 мин. При этом ваш прибор будет автоматически привязан к указанной вами учетной записи в проекте, если в CONNECT вы передали логин и пароль (или ваш код 10882) в проекте. В случае, если в настройках своего прибора вы указали неверный логин/пароль, то ваш IP будет заблокирован на 10 минут, после чего вы сможете повторить попытку.
Поддерживаемые команды нашего MQTT-брокера:
CONNECT (код 1)
Подключение к серверу, необходимые параметры:
Client Identifier (ClientID) = MAC Вашего прибора
UserName = Ваш логин в проекте (если нужна автопривязка)
Password = Ваш пароль или ваш код 10882 в проекте (если нужна автопривязка)
В ответ отправляется CONNACK (код 2) с результатом:
0 - подключение успешно;
2 - недопустимый MAC прибора (ClientID);
3 - технический сбой брокера / недоступность СУБД;
4 - неверный логин или пароль (если они передаются);
5 - в доступе отказано (например из-за неуплаты).
PUBLISH (код 3)
Публикация показаний датчиков, необходимые параметры:
Topic = логин/девайс/датчик (пример: username/devname/sensor1)
Value = показание датчика.
В ответ отправляется PUBACK (код 4) для QoS = 1 или PUBREC (код 5) для QoS = 2.
При использовании формата JSON:
Topic = логин/девайс/json (пример: username/devname/json)
Value = показания всех датчиков в одной строке (пример: {"sensor1":1,"sensor2":2}).
PUBACK (код 4)
Подтверждение приема данных клиентом с QoS = 1 после команды PUBLISH (код 3) с сервера.
PUBREL (код 6)
Подтверждение приема данных клиентом с QoS = 2, ответ на PUBREC (код 5).
В ответ отправляется PUBCOMP (код 7).
SUBSCRIBE (код 8)
Подписка на топики, команды UI и REST API.
В ответ отправляется SUBACK (код 9).
Если вам нужна отработка подписки на топики других приборов или иных событий, то для рассмотрения возможности её внедрения пишите в техподдержку проекта с подробным описанием вашего информационного обмена по MQTT и желаемого функционала нашего брокера.
UNSUBSCRIBE (код 10)
Отписка от топиков. Нет действий.
В ответ отправляется UNSUBACK (код 11).
PINGREQ (код 12)
Проверка активности клиента/сервера.
В ответ отправляется PINGRESP (код 13).
DISCONNECT (тип 14)
Завершение сеанса с сервером, параметры не требуются.
IoT API управления приборами Интернет вещей - Народный Мониторинг
Данное API предназначено для передачи с вебсайта проекта (и приложений использующих REST API) команд управления нагрузкой, а также для удаленного конфигурирования приборов мониторинга.
Передача команд происходит сразу после получения от прибора очередного пакета показаний датчиков в уже открытый сокет, что позволяет управлять приборами с "серыми" IP находящимися за роутерами (т.е. за NAT).
Для протоколов TCP, GET, POST вместо типичного "OK" и при отсутствии ошибок, сервер проекта в ответ на показания передает команды, начиная с символа "#" и разделяя команды через ";" без пробелов в хронологическом порядке во избежание переполнения буфера приема на слабых приборах до 5 за 1 сеанс.
Примеры TCP, GET, POST: gpio12=0 или две команды: gpio12=0;gpio14=1
Пример для JSON: {"devices":[{"mac":"DEVICE_MAC","commands":["gpio12=0","gpio14=1"]}]}
Возможность управления устройствами по протоколу MQTT доступна только для партнеров проекта и коммерческих клиентов!
Для протокола MQTT отправка команды происходит сиюминутно в связи с тем, что прибор всегда поддерживает активным соединение с сервером (брокером MQTT) при помощи PUBLISH с QoS=1, т.е. с ожиданием подтверждения приема команды - PUBACK.
При отправке команд дописывается префикс Username/Device/ (логин владельца и название прибора).
Пример для MQTT: output12=1 или system/restart=1 (для прошивок wifi-iot.com)
Команды на исполнение могут быть помещены в очередь его владельцем в Датчики \ Настройка датчиков \ отправить команду на прибор или же по клику на графическом переключателе для датчиков "вкл / выкл" и активном "Режиме управления" прибором.
Если прибор в течение часа после отправки команды так и не вышло на связь с сервером, то данная команда удаляется из очереди на исполнение.
На момент публикации статьи API управления приборами поддерживается на сайте проекта и в мобильных приложениях для Андроид 2019 и WinPhone/WinMobile.
Полный список поддерживаемых команд следует искать в инструкции к прибору или узнать у его разработчика
REST API JSON для IoT приложений, виджетов, сайтов - Народный Мониторинг
Форматы, кодировки, http-заголовки, ограничения
Запросы принимаются в кодировке UTF-8 по адресу http(s)://narodmon.ru/api в формате JSON (HTTP POST) или REST (HTTP GET).
Ответ сервера будет в формате JSON и кодировке UTF-8, в случае ошибки возвращается: {"error":"Error message","errno":N}
.
Следует знать, что запросы HTTP POST более безопасны, чем HTTP GET, т.к. параметры запроса не попадают в лог прокси и веб-серверов и не кешируются.
- Accept-Encoding: gzip, deflate - необязательный заголовок для экономии трафика, если ваше приложение поддерживает gzip-сжатие.
- User-Agent: MyAppName (название приложения на латинице) - обязательный заголовок, без которого веб-сервер сочтет ваш запрос за подделку.
Для доступа к данным приватных датчиков и веб-камер предварительно надо выполнить запрос авторизации userLogon, если это не было сделано ранее или при запуске Вашего приложения (а также 1 раз в сутки) appInit вернул логин авторизованного пользователя.
Ограничения в использовании нашего REST API:
- Доступ к API бесплатен только в личных некоммерческих целях.
- Использование данных проекта на сторонних ресурсах возможно только по согласованию с Администрацией и это не бесплатно.
- Для получения доступа к чужим публичным данным надо написать в техподдержку, для запроса только своих данных этого не требуется.
- Интервал опроса датчиков, приборов, веб-камер не чаще 1 раза в минуту для каждого клиента вашего приложения и для каждого IP, иначе сервер вернет ошибку HTTP 429, а при длительном её игнорировании заблокирует ваш ключ доступа к API.
Справочник кодов ошибок REST API (errno)
- 400 - ошибка синтаксиса в запросе к API;
- 401 - требуется авторизация;
- 403 - в доступе к объекту отказано;
- 404 - искомый объект не найден;
- 423 - ключ API заблокирован администратором;
- 429 - более 1 запроса в минуту;
- 434 - искомый объект отключен;
- 503 - сервер временно не обрабатывает запросы по техническим причинам.
Обязательные параметры, которые следует передавать в КАЖДОМ запросе.
- cmd название метода API;
- ang язык интерфейса приложения ISO 639-1 ("ru","en","uk");
- uuid уникальный идентификатор пользователя приложения, представляющий собой MD5-хеш в нижнем регистре однократно сгенерированный приложением в момент его установки. Используется для определения настроек локализации, местоположения и др.;
- pi_key ключ API для разработчика, представляющий собой уникальный идентификатор приложения, получаемый в разделе Мои Приложения и используемый для определения лимитов приложения и авторства.
appInit - проверка актуальности версии приложения при первом запуске и раз в сутки, проверка авторизации пользователя, его местонахождения, избранного и справочник типов датчиков.
Параметры запроса:
- version версия приложения пользователя для контроля, например: 1.1;
- platform версия платформы(ОС), например 6.0.1;
- model модель устройства, например Xiaomi Redmi Note 9;
- width ширина экрана клиентского устройства в пикселях для оптимизации размера загружаемых изображений;
- utc часовой пояс пользователя приложения в UTC (смещение в часах).
ОТВЕТ сервера:
- latest актуальная версия приложения указанная в Мои приложения;
- url скачивания обновления приложения указанный в Мои приложения;
- login имя авторизованного пользователя для данного uuid иначе "";
- vip = 1 признак партнера, донатора, разработчика, администрации, для остальных = 0;
- lat, lon широта и долгота текущего местонахождения пользователя в десятичном виде;
- addr ближайший адрес текущего местонахождения пользователя;
- timestamp текущее время сервера в UnixTime (для сверки);
- types[..] справочник типов датчиков;
- types[type] код типа датчика;
- types[name] название типа датчика;
- types[unit] единица измерения;
- favorites[..] массив из ID избранных датчиков у авторизованного пользователя.
Пример запроса REST(GET):
http://narodmon.ru/api/appInit?version=1.1&platform=6.0.1&uuid=UUID&api_key=API_KEY&lang=ru&utc=3
Пример запроса JSON(POST):
{"cmd":"appInit","version":"1.1","platform":"6.0.1","uuid":"UUID","api_key":"API_KEY","lang":"ru","utc":3}
Ответ сервера:
{"latest":"1.2","url":"http://mysite.ru/myapp.exe","login":"..","vip":0,"lat":55.747899,"lon":37.6171,"addr":"..","types":[{"type":0,"name":"..","unit":""},{..}],"favorites":[1,2,..],"timestamp":1711086535}
mapBounds - запрос списка датчиков и веб-камер в указанной прямоугольной области карты
* Для доступа к данным чужих публичных приборов требуется согласование, см. Профиль \ Мои приложения \ PubsLimit.
Параметры запроса:
- bounds массив координат углов области просмотра {широта-мин, долгота-мин, широта-макс, долгота-макс} в десятичном виде;
- metar опционально, если = 1, то включить в ответ сервера данные METAR в регионе (требуется авторизация);
- owmap опционально, если = 1, то включить в ответ сервера данные OWMap в регионе (требуется авторизация);
- types опционально массив кодов типов датчиков для фильтра отображения из справочника appInit.
ОТВЕТ сервера:
- devices массив с перечнем приборов и их датчиков в выбранной области просмотра;
- devices[id] целочисленный код прибора в проекте;
- devices[name] название прибора или его ID (если нет названия);
- devices[lat], devices[lon] широта и долгота прибора в десятичном виде;
- devices[time] время последнего показания датчика в UnixTime;
- devices[value] показание датчика для балуна прибора (с макс приоритетом);
- devices[type] код типа датчика (см. appInit);
- devices[unit] единица измерения;
- webcams массив с перечнем веб-камер в выбранной области просмотра;
- webcams[id] целочисленный код веб-камеры в проекте;
- webcams[name] название веб-камеры (как назвал владелец);
- webcams[lat], webcams[lon] широта и долгота веб-камеры в десятичном виде;
- webcams[time] время последней загрузки снапшота на сервер в UnixTime;
- webcams[image] URL последнего снимка с веб-камеры.
Пример запроса REST(GET):
http://narodmon.ru/api/mapBounds?bounds=10,20,11,21&uuid=UUID&api_key=API_KEY&lang=ru&limit=10
Пример запроса JSON(POST):
{"cmd":"mapBounds","limit":10,"bounds":[10,20,11,21],"uuid":"UUID","api_key":"API_KEY","lang":"ru"}
Ответ сервера:
{"devices":[{"id":0,"name":"..","lat":55.747899,"lon":37.6171,"time":1711086535,"value":0.0,"type":0,"unit":""},{..}],
"webcams":[{"id":0,"name":"..","lat":55.747899,"lon":37.6171,"time":1711086535,"image":"http://..."},{..}]}
sensorsNearby - запрос списка ближайших к пользователю датчиков + свои + избранные
* Для доступа к данным ваших приватных датчиков вне вашей локальной сети требуется однократная авторизация (userLogon). ** Для доступа к данным чужих публичных приборов требуется согласование, см. Профиль \ Мои приложения \ PubsLimit.
Параметры запроса:
- lat, lon опционально широта и долгота нового местонахождения пользователя в десятичном виде;
- my опционально, если = 1, то вывод датчиков только со своих приборов (требуется авторизация);
- pub опционально, если = 1, то вывод только публичных датчиков;
- radius опционально максимальное удаление от пользователя до датчиков в км, максимум ~111км (1°);
- metar опционально, если = 1, то включить в ответ сервера данные METAR в регионе (требуется авторизация);
- owmap опционально, если = 1, то включить в ответ сервера данные OWMap в регионе (требуется авторизация);
- types опционально массив кодов типов датчиков для фильтра отображения из справочника appInit;
- trends опционально, если = 1, то включить расчет тенденции показаний по МНК.
ОТВЕТ сервера:
- devices массив с перечнем приборов, к которым подключены публичные или свои датчики;
- devices[id] целочисленный код прибора в проекте;
- devices[name] название прибора или его ID (если нет названия);
- devices[my] = 1, если этот прибор авторизованного пользователя, иначе = 0;
- devices[owner] ID владельца прибора в проекте;
- devices[mac] серийный номер прибора (только для владельца);
- devices[cmd] = 1, если включен режим управления прибором, иначе = 0;
- devices[lat], devices[lon] широта и долгота расположения прибора в десятичном виде;
- devices[location] населенный пункт местонахождения прибора;
- devices[distance] расстояние в км от текущего местонахождения пользователя;
- devices[time] время последней активности прибора в UnixTime;
- devices[sensors] массив с перечнем публичных и своих датчиков, подключенных к данному прибору;
- devices[sensors][id] целочисленный код датчика в проекте;
- devices[sensors][mac] метрика датчика (только для владельца);
- devices[sensors][fav] = 1, если датчик в Избранном у пользователя и = 0, если нет или не авторизован;
- devices[sensors][pub] = 1, если датчик публичный и = 0, если датчик приватный;
- devices[sensors][type] код типа датчика (см. appInit);
- devices[sensors][name] название датчика или его ID (если нет названия);
- devices[sensors][value] последнее показание датчика;
- devices[sensors][unit] единица измерения;
- devices[sensors][time] время последнего показания датчика в UnixTime;
- devices[sensors][changed] время последнего изменения показаний датчика в UnixTime;
- devices[sensors][trend] коэффициент линейного роста показаний датчика за последний час, рассчитанный по МНК.
Пример запроса REST(GET):
http://narodmon.ru/api/sensorsNearby?lat=55.747899&lon=37.6171&radius=10&types=1,2&uuid=UUID&api_key=API_KEY&lang=ru
Пример запроса JSON(POST):
{"cmd":"sensorsNearby","lat":55.747899,"lon":37.6171,"radius":10,"types":[1,2],"uuid":"UUID","api_key":"API_KEY","lang":"ru"}
Ответ сервера:
{"devices":[{"id":0,"name":"..","my":0,"owner":"0","mac":"..","cmd":0,"lat":0.0,"lon":0.0,"location":"..","distance":0.0,"time":1711086535,"sensors":[{"id":0,"mac":"..","fav":0,"pub":0,"type":0,"name":"..","value":0.0,"unit":"","time":1711086535,"changed":1711086535,"trend":0.0},{..}]},{..}]}
sensorsOnDevice - запрос списка датчиков и их показаний по ID прибора
* Для доступа к данным ваших приватных датчиков вне вашей локальной сети требуется однократная авторизация (userLogon). ** Для доступа к данным чужих публичных приборов требуется согласование, см. Профиль \ Мои приложения \ PubsLimit.
Параметры запроса:
- devices массив ID приборов для запроса данных;
- trends = 1, необязательный параметр включающий расчет тенденций показаний;
- info = 1, необязательный параметр включает вывод полного описания прибора.
ОТВЕТ сервера:
- devices[id] ID прибора в проекте;
- devices[name] название прибора или его ID (если нет названия);
- devices[my] = 1, если этот прибор авторизованного пользователя, иначе = 0;
- devices[owner] ID владельца прибора в проекте;
- devices[mac] серийный номер прибора (только для владельца);
- devices[cmd] = 1, если включен режим управления прибором, иначе = 0;
- devices[lat], devices[lon] широта и долгота расположения прибора в десятичном виде;
- devices[location] населенный пункт местонахождения прибора;
- devices[distance] расстояние в км от текущего местонахождения пользователя;
- devices[time] время последней активности прибора в UnixTime;
- devices[site] ссылка на сайт владельца прибора, иначе https://narodmon.ru/id;
- devices[photo] ссылка на фото прибора (если владелец его загрузил), иначе пустая строка;
- devices[info] описание прибора (если info = 1), иначе длина описания в байтах или пустая строка;
- devices[sensors] массив датчиков подключенных к указанному прибору;
- devices[sensors][id] целочисленный код датчика в проекте;
- devices[sensors][pub] = 1, если датчик публичный и = 0, если датчик приватный;
- devices[sensors][type] код типа датчика (см. appInit);
- devices[sensors][name] название датчика или его ID (если нет названия);
- devices[sensors][value] последнее показание датчика;
- devices[sensors][unit] единица измерения;
- devices[sensors][time] время последнего показания датчика в UnixTime;
- devices[sensors][changed] время последнего изменения показаний датчика в UnixTime;
- devices[sensors][trend] коэффициент линейного роста показаний датчика за последний час, рассчитанный по МНК.
Пример запроса REST(GET):
http://narodmon.ru/api/sensorsOnDevice?devices=1,2&uuid=UUID&api_key=API_KEY&lang=ru
Пример запроса JSON(POST):
{"cmd":"sensorsOnDevice","devices":[1,2],"uuid":"UUID","api_key":"API_KEY","lang":"ru"}
Ответ сервера:
{"devices":[{"id":1,"name":"..","my":0,"owner":"0","mac":"","cmd":0,"lat":0.0,"lon":0.0,"location":"..","distance":0.0,"time":1711086535,
"site":"https://narodmon.ru/1","photo":"","info":"220B",
"sensors":[{"id":1,"mac":"","fav":0,"pub":1,"type":1,"name":"..","value":0.0,"unit":"",
"time":1711086535,"changed":1711086535,"trend":0},{..}]},{..}]}
sensorsValues - регулярное обновление показаний выбранных датчиков
* Для доступа к данным ваших приватных датчиков вне вашей локальной сети требуется однократная авторизация (userLogon). ** Для доступа к данным чужих публичных приборов требуется согласование, см. Профиль \ Мои приложения \ PubsLimit.
Параметры запроса:
- sensors массив кодов датчиков для запроса показаний;
- trends = 1, необязательный параметр включающий расчет тендеции показаний.
ОТВЕТ сервера:
- sensors массив показаний запрошенных датчиков;
- sensors[id] целочисленный код датчика в проекте;
- sensors[type] код типа датчика (см. appInit);
- sensors[value] последнее показание датчика;
- sensors[time] время последнего показания датчика в UnixTime;
- sensors[changed] время последнего изменения показаний датчика в UnixTime;
- sensors[trend] коэффициент линейного роста показаний датчика за последний час, рассчитанный по МНК.
Пример запроса REST(GET):
http://narodmon.ru/api/sensorsValues?sensors=1,2&uuid=UUID&api_key=API_KEY
Пример запроса JSON(POST):
{"cmd":"sensorsValues","sensors":[1,2],"uuid":"UUID","api_key":"API_KEY"}
Ответ сервера:
{"sensors":[{"id":1,"type":0,"value":0,"time":1711086535,"changed":1711086535,"trend":0},{..}]}
sensorsHistory - история показаний датчика за период (для графиков и тенденций)
* Для доступа к данным ваших приватных датчиков вне вашей локальной сети требуется однократная авторизация (userLogon).
Параметры запроса:
- id код датчика для запроса истории показаний (или sensors);
- sensors массив кодов датчиков для запроса показаний (или id);
- period название периода показаний: 'hour','day','week','month','year';
- offset смещение по выбранному периоду в прошлое, т.е. 1(day) = вчера, 1(month) = прошл.месяц.
ОТВЕТ сервера:
- sensors массив запрошенных датчиков;
- sensors[id] целочисленный код датчика в проекте;
- sensors[type] код типа датчика (см. appInit);
- sensors[name] название датчика или его ID (если нет названия);
- sensors[unit] единица измерения;
- data массив показаний запрошенного датчика;
- data[id] целочисленный код датчика в проекте;
- data[time] время показания датчика в UnixTime;
- data[value] показание датчика в указанный момент времени.
Пример запроса REST(GET):
http://narodmon.ru/api/sensorsHistory?id=1&period=day&offset=0&uuid=UUID&api_key=API_KEY
Пример запроса JSON(POST):
{"cmd":"sensorsHistory","id":1,"period":"day","offset":0,"uuid":"UUID","api_key":"API_KEY"}
Ответ сервера:
{"sensors":[{"id":1,"type":1,"name":"..","unit":".."}],"data":[{"id":1,"time":1711086535,"value":0.0},{..}]}
nameSensor - смена имени датчика (для владельца) или создание алиаса для остальных
Параметры запроса:
- id целочисленный код датчика в проекте;
- name новое название датчика, если пустое, то меняется на по умолчанию.
Пример запроса REST(GET):
http://narodmon.ru/api/nameSensor?id=1&name=NewName&uuid=UUID&api_key=API_KEY
Пример запроса JSON(POST):
{"cmd":"nameSensor","id":1,"name":"NewName","uuid":"UUID","api_key":"API_KEY"}
Ответ сервера:
{"result":"OK"}
pubSensor - запрос публикации приватного датчика
Параметры запроса:
- id целочисленный код датчика в проекте.
ОТВЕТ сервера:
- id целочисленный код датчика в проекте;
- code код датчика для добавления в Избранное.
Пример запроса REST(GET):
http://narodmon.ru/api/pubSensor?id=123456&uuid=UUID&api_key=API_KEY
Пример запроса JSON(POST):
{"cmd":"pubSensor","id":123456,"uuid":"UUID","api_key":"API_KEY"}
Ответ сервера:
{"id":123456,"code":123456}
webcamsNearby - запрос списка ближайших к пользователю веб-камер + свои + избранные
Параметры запроса:
- lat, lon опционально широта и долгота местонахождения пользователя в десятичном виде;
- radius опционально максимальное удаление от пользователя до веб-камеры в км, максимум ~111км (1°);
- my опционально, если = 1, то вывод только своих вебкамер (требуется авторизация);
- width опционально ширина экрана клиентского устройства в пикселях для оптимизации размера загружаемых снимков.
ОТВЕТ сервера:
- webcams массив с перечнем веб-камер;
- webcams[id] целочисленный код веб-камеры в проекте;
- webcams[name] название веб-камеры (как назвал владелец);
- webcams[my] = 1, если веб-камера авторизованного пользователя, иначе = 0;
- webcams[owner] имя владельца веб-камеры в проекте;
- webcams[fav] = 1, если веб-камера в Избранном у пользователя и = 0, если нет или не авторизован;
- webcams[distance] расстояние в км от текущего местонахождения пользователя;
- webcams[location] населенный пункт местонахождения веб-камеры;
- webcams[time] время последней загрузки снапшота на сервер в UnixTime;
- webcams[lat], webcams[lon] широта и долгота расположения веб-камеры в градусах в десятичном виде;
- webcams[image] URL последнего снимка с веб-камеры;
Пример запроса REST(GET):
http://narodmon.ru/api/webcamsNearby?radius=10&lat=55.747899&lon=37.6171&uuid=UUID&api_key=API_KEY&lang=ru
Пример запроса JSON(POST):
{"cmd":"webcamsNearby","radius":10,"lat":55.747899,"lon":37.6171,"uuid":"UUID","api_key":"API_KEY","lang":"ru"}
Ответ сервера:
{"webcams":[{"id":1,"name":"..","my":0,"owner":"1","fav":0,"distance":0.0,"lat":55.747899,"lon":37.6171,"location":"..","time":1711086535,"image":"http://.."},{..}]}
webcamImages - запрос списка снимков с веб-камеры по ее ID
Параметры запроса:
- id ID веб-камеры из ссылки вида http://narodmon.ru/-ID в балуне на карте;
- limit опционально кол-во снимков в ответе сервера, по умолчанию 20, максимум 50;
- since опционально время первого снимка в выборке в UnixTime, по умолчанию равно 0;
- latest опционально время последнего снимка в выборке в UnixTime, по умолчанию равно текущему;
- width опционально ширина экрана клиентского устройства в пикселях для оптимизации размера загружаемых снимков.
ОТВЕТ сервера:
- id целочисленный код веб-камеры в проекте;
- name название веб-камеры (как назвал владелец);
- location населенный пункт местонахождения веб-камеры;
- distance расстояние в км от текущего местонахождения пользователя;
- images массив снимков с веб-камеры находящихся на сервере;
- images[time] время актуальности снимка в UnixTime;
- images[image] URL для скачивания снимка.
Пример запроса REST(GET):
http://narodmon.ru/api/webcamImages?id=1&limit=10&uuid=UUID&api_key=API_KEY
Пример запроса JSON(POST):
{"cmd":"webcamImages","id":1,"limit":10,"uuid":"UUID","api_key":"API_KEY"}
Ответ сервера:
{"id":1,"name":"..","location":"..","distance":0.0,"images":[{"time":1711086535,"image":"http://.."},{..}]}
userLogon - авторизация пользователя в проекте или его регистрация
Параметры запроса:
- login логин пользователя для авторизации, если он не указан, то возвращается текущий логин для указанного uuid;
- hash хэш для авторизации, вычисляется по формуле с объединением строк MD5(uuid + MD5(введенный пароль)), если хэш не указан, то считается запросом на регистрацию в проекте по email/sms.
ОТВЕТ сервера:
- tz часовой пояс пользователя в проекте в UTC;
- vip = 1 признак партнера, донатора, разработчика, администрации, для остальных = 0;
- login имя авторизованного пользователя для текущего uuid или пустая строка;
- uid = ID участника проекта.
Пример запроса REST(GET):
http://narodmon.ru/api/userLogon?login=MyName&hash=MD5HASH&uuid=UUID&api_key=API_KEY&lang=ru
Пример запроса JSON(POST):
{"cmd":"userLogon","login":"MyName","hash":"MD5HASH","uuid":"UUID","api_key":"API_KEY","lang":"ru"}
Ответ сервера:
{"uid":1,"tz":3,"login":"MyName","vip":0}
userLocation - запрос текущего и установка нового местонахождение пользователя (точки отсчета)
Параметры запроса:
- lat, lon опционально широта и долгота местонахождения пользователя;
- addr опционально ближайший адрес к местонахождению пользователя;
- wifi опциональный массив точек доступа WiFi поблизости;
- wifi[bssid] MAC адрес точки доступа;
- wifi[rssi] уровень сигнала точки доступа в dBm ( <0);
- cells опциональный массив сотовых станций поблизости;
- cells[bssid] = MCC[3]:MNC[3]:LAC[4]:CID[7] в hex виде;
- cells[rssi] уровень сигнала сотовой станции в dBm ( <0);
- gui флаг указывающий на необходимость получения полного адреса.
ОТВЕТ сервера:
- lat, lon широта и долгота нового местонахождения пользователя в десятичном виде;
- addr ближайший адрес к найденным координатам (при gui = 1).
Пример запроса по координатам REST(GET):
http://narodmon.ru/api/userLocation?lat=55.747899&lon=37.6171&uuid=UUID&api_key=API_KEY&lang=ru
Пример запроса по адресу REST(GET): http://narodmon.ru/api/userLocation?addr=..&uuid=UUID&api_key=API_KEY&lang=ru
Пример запроса по координатам JSON(POST):
{"cmd":"userLocation","lat":55.747899,"lon":37.6171,"uuid":"UUID","api_key":"API_KEY","lang":"ru"}
Пример запроса по адресу JSON(POST):
{"cmd":"userLocation","addr":"..","uuid":"UUID","api_key":"API_KEY","lang":"ru"}
Пример запроса по WiFi сетям JSON(POST):
{"cmd":"userLocation","wifi":[{"bssid":"00:00:00:00:00:00","rssi":-0},{..}],"uuid":"UUID","api_key":"API_KEY","lang":"ru"}
Пример запроса по сотовым сетям JSON(POST):
{"cmd":"userLocation","cells":[{"bssid":"000:000:0000:0000000","rssi":-0},{..}],"uuid":"UUID","api_key":"API_KEY","lang":"ru"}
Ответ сервера:
{"lat":55.747899,"lon":37.6171,"addr":".."}
userFavorites - управление списком избранных датчиков и веб-камер
Параметры запроса:
- sensors опционально новый массив id избранных датчиков (список будет заменен, для его очистки передать "sensors":[0]);
- webcams опционально новый массив id избранных веб-камер (список будет заменен, для его очистки передать "webcams":[0]).
ОТВЕТ сервера:
- sensors массив избранных датчиков авторизованного пользователя;
- sensors[id] целочисленный код датчика в проекте;
- sensors[did] целочисленный код прибора в проекте;
- sensors[type] код типа датчика (см. appInit);
- sensors[name] название датчика или его ID (если нет названия);
- sensors[value] последнее показание датчика;
- sensors[unit] единица измерения;
- sensors[time] время последнего показания датчика в UnixTime;
- webcams массив избранных веб-камер авторизованного пользователя;
- webcams[id] целочисленный код веб-камеры в проекте, если 0 то удалить из списка;
- webcams[name] название веб-камеры или http-ссылка (как назвал владелец);
- webcams[time] время последней загрузки снапшота на сервер в UnixTime;
- webcams[image] URL последнего снимка с веб-камеры.
Пример запроса REST(GET):
http://narodmon.ru/api/userFavorites?sensors=1,2&webcams=1,2&uuid=UUID&api_key=API_KEY&lang=ru
Пример запроса JSON(POST):
{"cmd":"userFavorites","uuid":"UUID","api_key":"API_KEY","sensors":[1,2],"webcams":[1,2],"lang":"ru"}
Ответ сервера:
{"sensors":[{"id":1,"did":1,"type":1,"name":"..","value":0.0,"time":1711086535},{..}],
"webcams":[{"id":1,"name":"..","time":1711086535,"image":"http://.."},{..}]}
userLogout - завершение сеанса текущего пользователя
Параметры запроса:
* нет параметров *
ОТВЕТ сервера:
- login имя авторизованного пользователя для текущего uuid;
- uid ID участника проекта.
Пример запроса REST(GET):
http://narodmon.ru/api/userLogout?uuid=UUID&api_key=API_KEY
Пример запроса JSON(POST):
{"cmd":"userLogout","uuid":"UUID","api_key":"API_KEY"}
Ответ сервера:
{"login":"","uid":0}
addLike - отметка "Мне нравится" на снимках с веб-камер и приборах.
Параметры запроса:
- id веб-камеры(<0) или прибора(>0). ОТВЕТ сервера: - id веб-камеры(<0) или прибора(>0); - time время отметки в UnixTime; - liked общее число отметок "Нравится" на объекте после выполнения.
Пример запроса REST(GET):
http://narodmon.ru/api/addLike?id=1&uuid=UUID&api_key=API_KEY
Пример запроса JSON(POST):
{"cmd":"addLike","id":1,"uuid":"UUID","api_key":"API_KEY"}
Ответ сервера:
{"id":1,"time":1711086535,"liked":1}
disLike - снятие отметки "Мне нравится" на снимках с веб-камер и приборах
Параметры запроса:
- id веб-камеры(<0) или прибора(>0). ОТВЕТ сервера: - id веб-камеры(<0) или прибора(>0); - time время снятия отметки в UnixTime; - liked общее число отметок "Нравится" на объекте после выполнения.
Пример запроса REST(GET):
http://narodmon.ru/api/disLike?id=1&uuid=UUID&api_key=API_KEY
Пример запроса JSON(POST):
{"cmd":"disLike","id":1,"uuid":"UUID","api_key":"API_KEY"}
Ответ сервера:
{"id":1,"time":1711086535,"liked":0}
setPushToken, setPushURI - установка параметров отправки PUSH уведомлений. Используется FireBase (Android, iOS) и WNS (Windows)
Параметры запроса:
- token токен для Android и iOS;
- uri URL для Windows Mobile и Windows Phone.
Пример запроса REST(GET):
FireBase: http://narodmon.ru/api/setPushToken?token=..&uuid=UUID&api_key=API_KEY
WNS: http://narodmon.ru/api/setPushURI?uri=..&uuid=UUID&api_key=API_KEY
Пример запроса JSON(POST):
FireBase: {"cmd":"setPushToken","token":"..","uuid":"UUID","api_key":"API_KEY"}
WNS: {"cmd":"setPushURI","uri":"https://..","uuid":"UUID","api_key":"API_KEY"}
Ответ сервера:
{"result":"OK"}
PUSH сообщения от FireBase приходят в коллекции java.util.Map с полями:
- id идентификатор сообщения (int unsigned);
- uid идентификатор пользователя (int signed);
- time время отправки сообщения UnixTime (int unsigned);
- subj заголовок сообщения;
- body полный текст сообщения.
PUSH сообщения от WNS приходят в виде структуры JSON:
{"id":ID,"uid":UserID,"time":1711086535,"subj":"..","body":".."}
setPushStatus - отправка отчета о доставке/прочтении PUSH-уведомления
Параметры запроса:
- states массив со статусами полученных сообщений:
- states[id] идентификатор полученного сообщения (int unsigned);
- states[time] время отправки сообщения в UnixTime;
- states[status] код текущего статуса сообщения (201 - получено, 202 - прочтено).
Пример запроса REST(GET):
http://narodmon.ru/api/setPushStatus?id=1&time=1711086535&status=201&uuid=UUID&api_key=API_KEY
Пример запроса JSON(POST):
{"cmd":"setPushStatus","states":[{"id":1,"time":1711086535,"status":201},{..}],"uuid":"UUID","api_key":"API_KEY"}
Ответ сервера:
{"result":"OK"}
PUSH сообщения от FireBase приходят в коллекции java.util.Map с полями:
- id идентификатор сообщения (int unsigned);
- uid идентификатор пользователя (int signed);
- time время отправки сообщения UnixTime (int unsigned);
- subj заголовок сообщения;
- body полный текст сообщения.
PUSH сообщения от WNS приходят в виде структуры JSON:
{"id":ID,"uid":UserID,"time":1711086535,"subj":"..","body":".."}
Во избежание ошибки 429 (слишком частые запросы), настоятельно рекомендуется аккумулировать статусы доставки PUSH-сообщений и отправлять их пакетами не чаще 1 раза в минуту!
sendCommand - отправка команды управления на прибор
Параметры запроса:
- id ID приборов в проекте (integer unsigned);
- command строка команды, шаблон PCRE [a-z0-9_\-\+\=\;\/\.]+
Пример запроса REST(GET):
http://narodmon.ru/api/sendCommand?id=1&command=reboot&uuid=UUID&api_key=API_KEY
Пример запроса JSON(POST):
{"cmd":"sendCommand","id":1,"command":"gpio12=1","uuid":"UUID","api_key":"API_KEY"}
Ответ сервера:
{"result":"OK"}
sendComplaint - отправка жалобы на ошибочное показание датчика или снимка с веб-камеры
Параметры запроса:
- id код датчика (id>0) или веб-камеры (id <0);
- time UnixTime времени возникновения проблемы;
- name имя заявителя для обратной связи;
- email почта заявителя для обратной связи;
- problem краткое описание сути проблемы;
- value каким должно быть показание датчика (для id>0).
Пример запроса REST(GET):
http://narodmon.ru/api/sendComplaint?id=1&time=1711086535&value=0&name=..&email=..&problem=..&uuid=UUID&api_key=API_KEY
Пример запроса JSON(POST):
{"cmd":"sendComplaint","id":1,"time":1711086535,"value":0,"name":"..","email":"..","problem":"..","uuid":"UUID","api_key":"API_KEY"}
Ответ сервера:
{"result":"OK"}
sendMessage - отправка сообщения в беседу или вопроса к Администрации
Параметры запроса:
- uid опционально ID получателя, по умолчанию Администрация;
- name опционально имя заявителя для обращения;
- email опционально почта заявителя для дублирования;
- chat опционально ID беседы из getDialog;
- subj обязательно тема обращения;
- mess обязательно текст сообщения;
- images[..] опционально массив вложенных изображений (до 1МБ) в виде base64 строк.
Пример запроса REST(GET):
http://narodmon.ru/api/sendMessage?uid=1&name=..&email=..&subj=..&mess=..&uuid=UUID&api_key=API_KEY
Пример запроса JSON(POST):
{"cmd":"sendMessage","uid":1,"name":"..","email":"..","subj":"..","mess":"..","uuid":"UUID","api_key":"API_KEY"}
Ответ сервера:
{"result":"OK"}
weatherReport - отправка метеоданных пользователем с автономных метеоприборов
Параметры запроса:
- lat, lon широта и долгота прибора на момент отправки (предварительно обновить геолокацию!);
- temp показания уличного термометра (если он есть) °C;
- humid показания уличного гигрометра (если он есть) %;
- pss показания бытового барометра (если он есть) мм рт.ст.;
- wind азимут направления ветра (если есть анемометр) 0-360°.
Пример запроса REST(GET):
http://narodmon.ru/api/weatherReport?lat=55.747899&lon=37.6171&temp=00&humid=00&pss=000&wind=000&lang=ru&uuid=UUID&api_key=API_KEY
Пример запроса JSON(POST):
{"cmd":"weatherReport","lat":55.747899,"lon":37.6171,"temp":00,"humid":00,"pss":000,"wind":000,"lang":"ru","uuid":"UUID","api_key":"API_KEY"}
Ответ сервера:
{"result":"Вы сообщили следующие данные:..."}
Если отчет о погоде будет отправлен менее чем через час после предыдущего, то он посчитается исправлением и заменит его.
bugReport - отправка отзыва на приложение и багрепортов с техданными для отладки
Параметры запроса:
- time опционально UnixTime момента возникновения сбоя;
- name опционально имя заявителя для обращения;
- email опционально почта заявителя для дублирования;
- mess опционально текст сообщения пользователя;
- logs опционально технические данные для отладки;
- images[..] опционально массив вложенных изображений (до 1МБ) в виде base64 строк.
Пример запроса REST(GET):
http://narodmon.ru/api/bugReport?time=1711086535&name=..&email=..&mess=..&logs=..&uuid=UUID&api_key=API_KEY
Пример запроса JSON(POST):
{"cmd":"bugReport","time":1711086535,"name":"..","email":"..","mess":"..","logs":"..","uuid":"UUID","api_key":"API_KEY"}
Ответ сервера:
{"result":"OK"}
Уведомление о багрепорте в краткой форме будет отправлено автору приложения используя PUSH, а на e-mail автора будет отправлена полная версия вместе с техданными для отладки.
getHelp - запрос справочной информации о проекте
Параметры запроса:
- topic опционально идентификатор статьи, если он не указан, то возвращается оглавление.
ОТВЕТ сервера:
- topics массив со список статей;
- topics[topic] идентификатор статьи;
- topics[group] название раздела Справки;
- topics[title] название статьи из Справки;
- topics[body] html-текст статьи (если был указан topic) или хеш статьи в оглавлении.
Пример запроса в оглавлении REST(GET):
http://narodmon.ru/api/getHelp?lang=ru&uuid=UUID&api_key=API_KEY
Пример запроса оглавления JSON(POST):
{"cmd":"getHelp","lang":"ru","uuid":"UUID","api_key":"API_KEY"}
Ответ сервера с оглавлением:
{"topics":[{"topic":"topic1","group":"Раздел1","title":"Заголовок1","body":"c8542aec71a1a1e371f39553ae3b7ec7"},{..}]}
Пример запроса текста статьи REST(GET):
http://narodmon.ru/api/getHelp?topic=topic1&lang=ru&uuid=UUID&api_key=API_KEY
Пример запроса текста статьи JSON(POST):
{"cmd":"getHelp","topic":"topic1","lang":"ru","uuid":"UUID","api_key":"API_KEY"}
Ответ сервера с текстом статьи:
{"topics":[{"topic":"topic1","group":"Раздел1","title":"Заголовок1","body":"html-текст"}]}
Настоятельно рекомендуется кешировать тексты уже скачанных ранее статей в виду их существенного объёма, но при этом периодически обновлять оглавление и в случае изменения хеша статьи её следует перезакачать с сервера указав её topic и обновить title и body в локальном кеше приложения.
Пример на PHP + cURL для вывода показаний на свой сайт
// кодировка ответа сервера
header('Content-Type: text/html; charset=utf-8');
// подготовка параметров запроса
$request = array('cmd'=>'sensorsNearby', 'lat'=>55.75, 'lon'=>37.62, 'radius'=>11, 'uuid'=>md5('mysite.ru'),
'api_key'=>'MY_API_KEY', 'lang'=>'ru');
// исполнение запроса
$ch = curl_init('http://narodmon.ru/api');
if(!$ch) exit('Ошибка инициализации cURL');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 2);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_USERAGENT, 'mysite.ru');
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($request));
$reply = curl_exec($ch);
curl_close($ch);
if(empty($reply)) exit('Ошибка сети');
// декодирование ответа из JSON в массив
$data = json_decode($reply, true);
if(empty($data) or !is_array($data)) {
exit('Ошибочные данные'); }
// если была ошибка API
if(isset($data['error'])) exit($data['error']);
// выводим в цикле показания датчиков
foreach($data['devices'] as $D) {
echo "\n".$D['name'].":\n";
foreach($D['sensors'] as $S) {
echo date('H:i', $S['time']).' '.$S['name'];
echo ' = '.rounОтвет сервера:d($S['value']).$S['unit']."\n"; }}
Пример на PHP без cURL для вывода показаний на свой сайт
// кодировка ответа сервера
header('Content-Type: text/html; charset=utf-8');
// подготовка параметров запроса
$request = array('cmd'=>'sensorsNearby', 'lat'=>55.75, 'lon'=>37.62, 'radius'=>11, 'uuid'=>md5('mysite.ru'),
'api_key'=>'MY_API_KEY', 'lang'=>'ru')
// исполнение запроса
$header = "User-Agent: mysite.ru\r\nContent-Type: application/x-www-form-urlencoded\n";
$context = array('http' => array('method'=>'POST', 'header'=>$header, 'content'=>json_encode($request)));
$reply = file_get_contents('http://narodmon.ru/api', false, stream_context_create($context));
if(empty($reply)) exit('Ошибка сети');
// декодирование ответа из JSON в массив
$data = json_decode($reply, true);
if(empty($data) or !is_array($data)) {
exit('Ошибочные данные'); }
// если была ошибка API
if(isset($data['error'])) exit($data['error']);
// выводим в цикле показания датчиков
foreach($data['devices'] as $D) {
echo "\n".$D['name'].":\n";
foreach($D['sensors'] as $S) {
echo date('H:i', $S['time']).' '.$S['name'];
echo ' = '.round($S['value']).$S['unit']."\n"; }}
Пример на Python2 для вывода показаний на свой сайт
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
# by Roman Vishnevsky aka.x0x01 @ gmail.com
import urllib2
import json
import hashlib
import uuid
# ключ API для разработчика, получаемый в Мои данные \ Мои приложения после регистрации в проекте.
# заменить на свой!
api_key = 'abcdefABCDEF'
# генерация уникального ID приложения
app_id = str(uuid.getnode())
md5_app_id = hashlib.md5(app_id).hexdigest()
# формирование тела JSON
data = {
'cmd': 'sensorsNearby',
'uuid': md5_app_id,
'api_key': api_key,
'radius': 11,
'lat': 55.75,
'lon': 37.62,
'lang': 'ru'
}
# обработчик исключений
try:
# запрос
request = urllib2.Request('http://narodmon.ru/api', json.dumps(data))
response = urllib2.urlopen(request)
# работа с JSON
result = json.loads(response.read())
# вывод всего массива
print json.dumps(result, indent=4, sort_keys=True)
# или по ключу
# print result['devices']
# или по ключу в цикле
# for dev in result['devices']:
# print dev['name'], dev['distance']
except urllib2.URLError, e:
print 'HTTP error:', e
except (ValueError, TypeError), e:
print 'JSON error:', e
Пример на Python3 для вывода показаний на свой сайт
# Гладышев Дмитрий aka nightflash
import requests
import hmac, hashlib
import json
import uuid
# ключ API для разработчика, получаемый в Мои данные \ Мои приложения после регистрации в проекте.
# заменить на свой!
api_key = 'abcdef123456'
# генерация уникального ID приложения
app_id = str(uuid.getnode())
md5_app_id = hashlib.md5(app_id.encode()).hexdigest()
# формирование тела JSON
data = {
'cmd': 'sensorsNearby',
'uuid': md5_app_id,
'api_key': api_key,
'radius': 11,
'lat': 55.75,
'lon': 37.62,
'lang': 'ru'
}
# обработчик исключений
try:
# запрос
request = requests.post('http://narodmon.ru/api', data=json.dumps(data))
# работа с JSON
result = json.loads(request.text)
# вывод всего массива
print(json.dumps(result, indent=4, sort_keys=True))
# или по ключу
# print(result['devices'])
# или по ключу в цикле
# for dev in result['devices']:
# print(dev['name'], dev['distance'])
except Exception as err:
print(f"Unexpected {err=}, {type(err)=}")