Как стать автором
Обновить

Выгружаем данные из метеорологической стации Oregon Scientific WMR500

Время на прочтение4 мин
Количество просмотров3.2K
Однажды мы решили, что нам на сайте нужна своя актуальная погода за окном. А значит нужна какая-то метеорологическая станция с подключением в Интернет. Недорого. Ибо брать что-то типа Davis Vantage Pro2 Plus за овер 100 тысяч рублей, да еще и держать отдельный компьютер для подключения к ней (как это сделали в mail.ru) не хотелось как с точки зрения бюджета, так и с точки зрения сложности.



Выбор пал на недорогую, достаточно свежую метео-станцию Oregon Scientific WMR500. Обзор её я делать не буду, можете самостоятельно поискать в Интернете. Достаточно того, что она умеет измерять температуру, влажность, давление, скорость и направление ветра. В теории она умеет еще качество воздуха и уровень УФ-излучения, но мы не нашли в продаже соответствующих дополнительных датчиков. Ценой за бюджетность была схема её работы. Данные она сама отдает в облако по Wi-Fi. Доступ к данным есть в мобильном приложении, а так же с web, но несколько странный. Об этом, собственно, и пойдет речь.

Для получения доступа к web-части необходим аккаунт, который создается в мобильном приложении. Собственно и настройка станции в части того, какой Wi-Fi ей использовать для подключения происходит только в приложении при первичном подключении к временной точке доступа самой станции. Тут все делается по инструкции и ничего сложного нет. В итоге, в приложении мы получаем добавленное устройство, id которого нам понадобится далее.



Web-интерфейс находится по адресу http://web-wmr500.idtlive.com/



Зайдя в него, можно смотреть графики средней красивости по кнопке «Show», а так же экспортировать данные в формате XLS за выбранный период (кнопка «Export»). Сразу скажу, что показ влажности на график работает, а вот экспорт нет, потому что данные влажности экспортируются вместе с данными температуры. Такая вот странная ситуация. Посматривая в запросы можно увидеть, что для графиков есть некий api, отдающий данные в json, что уже хорошо. Можно грабить корованы!



Для примера «грабим» набор данных по темпрературе за сутки. Запрос пойдет на web-wmr500.idtlive.com/index/api.show/index.html, с параметрами (тут PHP массив параметров для примера):

$request = [
	'type'		=> 'temperature',
	'unit'		=> '°C',
	'id'		=> 'id-вашего-устройства',
	'channel'	=> 'номер-канала-блока-датчиков',
	'start'		=> "'2020-07-20T00:00:00Z'",
	'end'		=> "'2020-07-21T00:00:00Z'",
];

Даты обязательно в одинарных кавычках и в формате ISO 8601 без TimeZone. Номер канала (channel) – 1, 2 или 3, в зависимости от того, на каком канале подключен блок датчиков. Данные запроса по типам отличаются собственно типом запрашиваемых данных (type) и единицами измерения (unit).

Все доступные типы и единицы измерения:

temperature – °C или °F
humidity – %
rain – mm/h или inch/h
wind – m/s, knots, kph, mph
pressure – mbar,hPa,mmHg,inHg

Одно плохо, через api.show можно получить данные только указанных параметров, к примеру нельзя узнать направление ветра, или точку росы, да там много всего статистического. А хотелось бы. И тут нам поможет EXPORT.

Делаем первый запрос на адрес web-wmr500.idtlive.com/index/api.export/index.html с теми же параметрами. В ответ сервер где-то в дебрях генерирует статический XLS файл и отдает ссылку на него. Скачать его можно после этого в любой момент (я видел на сервере чужие файлы за 2018 год, папка открыта для индексирования). В файлах уже существенно больше информации, вернее она там вся доступная.



Но тут тоже есть свои плюсы и свои минусы. Плюс – вы можете получить данные за нужный период. Минус — в web-часть эти данные попадают с 15-ти минутным интервалом. Для хранения погоды у себя в БД это даже хорошо, можно загрузить сразу все данные с момента запуска станции и все такое. А вот если вы хотите чаще, или быстрее получать актуальную информацию, то придется провести более продвинутые изыскания.

Я «психанул» и решил перехватить трафик приложения, оно получает данные практически мгновенно. Вернее оно получает данные «напрямую» от станции, которая отдает последние данные, полученные от блока датчиков. А блок датчиков она опрашивает раз в 15 секунд.

Оказалось, что приложение по протоколу MQTT идет куда-то в инстанс амазона (адрес 35.161.38.128 получен путем перехвата трафика, кхе-кхе), подписывается на топик со случайным topic-id, шлет в топик станции (она сама по wi-fi и подкючена только по MQTT только туда, web-часть судя по всему тоже периодически из брокера MQTT эти же даные и получает) с её id команду типа «родная, дай-ка мне свой статус, ответь в topic-id». И если для получения данных с web-части я использовал php + curl (вы можете использовать то, что вам больше по душе), то тут нужна асинхронщина в рамках одного соединения. Быстро и «на коленке» я придумал только использовать node.js. Понадобится модуль mqtt.

В моем случае это просто консольный скрипт, который через exec я «дергаю» в php.

#!/usr/bin/node

var mqtt  = require('mqtt');
var md5   = require('md5');

String.prototype.insert = function (index, string) {
  if (index > 0)
   return this.substring(0, index) + string + this.substring(index, this.length);
  else
    return string + this;
};

var host       = 'mqtt.idtlive.com';
var your_mail  = 'your_account_mail@somehost.com'; // see in app, registered account
var clientId   = 'Android_' + your_mail;
var deviceId   = 'your-device-id'; // see in app connected device section, something like F9987D92-E180-64DE-A202-D43AAD0D5784
var channelId  = 1; // channel beetwen station & external sensors block

var timeInMs   = Date.now();
var uniqTopic  = md5(timeInMs).toUpperCase().insert(8,'-').insert(13,'-').insert(18,'-').insert(23,'-');

var client = mqtt.connect( {
  host : host,
  port : 1883,
  cliendId : clientId
});

client.on('connect', function() {
  client.subscribe('enno/out/json/'+uniqTopic,
    function(err) {
      if (!err) {
        client.publish('enno/out/json/'+deviceId, '{"command":"getChannel'+channelId+'Status","id":"'+uniqTopic+'"}');
      } else {
        console.log('connect error');
      }
    })
});

client.on('message', function(topic, message) {
  console.log(message.toString())
  client.end()
});

Как парсить данные из web-части (JSON), экспорта (Excel) или из MQTT (JSON) я рассказывать не буду, тут уж как хотите, так и обрабатывайте.

Вот собственно и все. Если кому-то вдруг поможет, то буду только рад.

P.S> Update, код скрипта причесан, добавлена генерация случайного топика MQTT, для имитации работы как из приложения, а так же выложен сюда
Теги:
Хабы:
+3
Комментарии3

Публикации

Истории

Ближайшие события

Weekend Offer в AliExpress
Дата20 – 21 апреля
Время10:00 – 20:00
Место
Онлайн
Конференция «Я.Железо»
Дата18 мая
Время14:00 – 23:59
Место
МоскваОнлайн