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)=}")