|
4 weeks ago | |
---|---|---|
.. | ||
README.md | 4 weeks ago | |
assignment.md | 4 weeks ago |
README.md
Геозоны
Скетчноут от Nitya Narasimhan. Нажмите на изображение, чтобы увидеть его в большем размере.
Это видео дает обзор геозон и их использования в Azure Maps, темы, которые будут рассмотрены в этом уроке:
🎥 Нажмите на изображение выше, чтобы посмотреть видео
Викторина перед лекцией
Введение
В последних трех уроках вы использовали IoT для отслеживания грузовиков, перевозящих вашу продукцию с фермы на перерабатывающий центр. Вы собирали данные GPS, отправляли их в облако для хранения и визуализировали их на карте. Следующий шаг в повышении эффективности вашей цепочки поставок — это получение уведомления, когда грузовик приближается к перерабатывающему центру, чтобы команда, необходимая для разгрузки, могла быть готова с погрузчиками и другим оборудованием сразу по прибытии транспортного средства. Это позволит быстро разгрузить грузовик, и вы не будете платить за простой грузовика и водителя.
В этом уроке вы узнаете о геозонах — определенных геопространственных областях, таких как зона в радиусе 2 км от перерабатывающего центра, и о том, как проверять, находятся ли GPS-координаты внутри или вне геозоны, чтобы определить, прибыл ли ваш GPS-датчик в зону или покинул ее.
В этом уроке мы рассмотрим:
- Что такое геозоны
- Определение геозоны
- Проверка точек относительно геозоны
- Использование геозон в серверлес-коде
🗑 Это последний урок в этом проекте, поэтому после завершения урока и задания не забудьте очистить свои облачные сервисы. Вам понадобятся эти сервисы для выполнения задания, поэтому сначала убедитесь, что вы его завершили.
При необходимости обратитесь к руководству по очистке проекта для получения инструкций.
Что такое геозоны
Геозона — это виртуальный периметр для реальной географической области. Геозоны могут быть кругами, определяемыми точкой и радиусом (например, круг радиусом 100 м вокруг здания), или многоугольниками, охватывающими такие области, как школьные зоны, границы города или кампусы университетов или офисов.
💁 Возможно, вы уже использовали геозоны, даже не зная об этом. Если вы устанавливали напоминание в приложении iOS Reminders или Google Keep на основе местоположения, вы использовали геозону. Эти приложения создают геозону на основе указанного местоположения и уведомляют вас, когда ваш телефон входит в эту зону.
Есть множество причин, по которым важно знать, находится ли транспортное средство внутри или вне геозоны:
- Подготовка к разгрузке — уведомление о прибытии транспортного средства на объект позволяет команде подготовиться к разгрузке, сокращая время ожидания. Это может позволить водителю выполнять больше доставок за день с меньшим временем простоя.
- Налоговое соответствие — в некоторых странах, таких как Новая Зеландия, дорожные налоги для дизельных транспортных средств рассчитываются на основе веса транспортного средства при движении только по общественным дорогам. Использование геозон позволяет отслеживать пробег на общественных дорогах в отличие от частных дорог, например, на фермах или в лесозаготовительных районах.
- Мониторинг краж — если транспортное средство должно оставаться в определенной зоне, например, на ферме, и покидает геозону, это может означать, что его украли.
- Соблюдение правил местоположения — некоторые части рабочего объекта, фермы или завода могут быть недоступны для определенных транспортных средств, например, для тех, которые перевозят искусственные удобрения и пестициды, чтобы избежать их попадания на поля с органической продукцией. Если транспортное средство входит в такую геозону, это нарушение, и водителя можно уведомить.
✅ Можете ли вы придумать другие способы использования геозон?
Azure Maps, сервис, который вы использовали в прошлом уроке для визуализации GPS-данных, позволяет определять геозоны и проверять, находится ли точка внутри или вне геозоны.
Определение геозоны
Геозоны определяются с использованием GeoJSON, так же как и точки, добавленные на карту в предыдущем уроке. В данном случае вместо FeatureCollection
с Point
значениями используется FeatureCollection
, содержащий Polygon
.
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-122.13393688201903,
47.63829579223815
],
[
-122.13389128446579,
47.63782047131512
],
[
-122.13240802288054,
47.63783312249837
],
[
-122.13238388299942,
47.63829037035086
],
[
-122.13393688201903,
47.63829579223815
]
]
]
},
"properties": {
"geometryId": "1"
}
}
]
}
Каждая точка многоугольника определяется как пара долгота, широта в массиве, и эти точки находятся в массиве, который задается как coordinates
. В Point
из прошлого урока coordinates
был массивом из двух значений: широты и долготы. Для Polygon
это массив массивов, содержащих два значения: долгота, широта.
💁 Помните, GeoJSON использует
долгота, широта
для точек, а неширота, долгота
.
Массив координат многоугольника всегда имеет на одну запись больше, чем количество точек многоугольника, так как последняя запись совпадает с первой, замыкая многоугольник. Например, для прямоугольника будет 5 точек.
На изображении выше показан прямоугольник. Координаты многоугольника начинаются в верхнем левом углу на 47,-122, затем перемещаются вправо к 47,-121, затем вниз к 46,-121, затем влево к 46,-122, а затем возвращаются к начальной точке на 47,-122. Это дает многоугольнику 5 точек: верхний левый угол, верхний правый угол, нижний правый угол, нижний левый угол и снова верхний левый угол для замыкания.
✅ Попробуйте создать GeoJSON многоугольник вокруг вашего дома или школы. Используйте инструмент, например, GeoJSON.io.
Задание — определение геозоны
Чтобы использовать геозону в Azure Maps, сначала ее нужно загрузить в ваш аккаунт Azure Maps. После загрузки вы получите уникальный идентификатор, который можно использовать для проверки точки относительно геозоны. Для загрузки геозон в Azure Maps необходимо использовать веб-API карт. Вы можете вызывать веб-API Azure Maps с помощью инструмента curl.
🎓 Curl — это инструмент командной строки для выполнения запросов к веб-эндпоинтам.
-
Если вы используете Linux, macOS или последнюю версию Windows 10, curl, скорее всего, уже установлен. Выполните следующую команду в терминале или командной строке, чтобы проверить:
curl --version
Если вы не видите информацию о версии curl, вам нужно установить его с страницы загрузки curl.
💁 Если вы опытный пользователь Postman, вы можете использовать его вместо curl, если предпочитаете.
-
Создайте GeoJSON файл, содержащий многоугольник. Вы будете тестировать его с помощью вашего GPS-датчика, поэтому создайте многоугольник вокруг вашего текущего местоположения. Вы можете создать его вручную, отредактировав приведенный выше пример GeoJSON, или использовать инструмент, например, GeoJSON.io.
GeoJSON должен содержать
FeatureCollection
, включающийFeature
сgeometry
типаPolygon
.Вы ОБЯЗАНЫ также добавить элемент
properties
на том же уровне, что и элементgeometry
, и он должен содержатьgeometryId
:"properties": { "geometryId": "1" }
Если вы используете GeoJSON.io, вам нужно будет вручную добавить этот элемент в пустой
properties
, либо после загрузки JSON-файла, либо в редакторе JSON в приложении.Этот
geometryId
должен быть уникальным в этом файле. Вы можете загружать несколько геозон как несколькоFeatures
вFeatureCollection
в одном GeoJSON-файле, если у каждой из них разныйgeometryId
. Многоугольники могут иметь одинаковыйgeometryId
, если они загружаются из разных файлов в разное время. -
Сохраните этот файл как
geofence.json
и перейдите в папку, где он сохранен, в вашем терминале или консоли. -
Выполните следующую команду curl, чтобы создать геозону:
curl --request POST 'https://atlas.microsoft.com/mapData/upload?api-version=1.0&dataFormat=geojson&subscription-key=<subscription_key>' \ --header 'Content-Type: application/json' \ --include \ --data @geofence.json
Замените
<subscription_key>
в URL на API-ключ вашего аккаунта Azure Maps.URL используется для загрузки данных карты через API
https://atlas.microsoft.com/mapData/upload
. Вызов включает параметрapi-version
, чтобы указать, какую версию API Azure Maps использовать. Это позволяет API изменяться со временем, сохраняя обратную совместимость. Формат загружаемых данных установлен какgeojson
.Эта команда выполнит POST-запрос к API загрузки и вернет список заголовков ответа, включая заголовок
location
.content-type: application/json location: https://us.atlas.microsoft.com/mapData/operations/1560ced6-3a80-46f2-84b2-5b1531820eab?api-version=1.0 x-ms-azuremaps-region: West US 2 x-content-type-options: nosniff strict-transport-security: max-age=31536000; includeSubDomains x-cache: CONFIG_NOCACHE date: Sat, 22 May 2021 21:34:57 GMT content-length: 0
🎓 При вызове веб-эндпоинта вы можете передавать параметры вызова, добавляя
?
, за которым следуют пары ключ-значение в форматеkey=value
, разделенные символом&
. -
Azure Maps не обрабатывает запрос мгновенно, поэтому вам нужно будет проверить, завершился ли процесс загрузки, используя URL, указанный в заголовке
location
. Выполните GET-запрос к этому URL, чтобы узнать статус. Вам нужно будет добавить ваш ключ подписки в конец URLlocation
, добавив&subscription-key=<subscription_key>
, заменив<subscription_key>
на API-ключ вашего аккаунта Azure Maps. Выполните следующую команду:curl --request GET '<location>&subscription-key=<subscription_key>'
Замените
<location>
на значение заголовкаlocation
, а<subscription_key>
на API-ключ вашего аккаунта Azure Maps. -
Проверьте значение
status
в ответе. Если оно неSucceeded
, подождите минуту и попробуйте снова. -
Как только статус станет
Succeeded
, посмотрите наresourceLocation
в ответе. Этот параметр содержит детали уникального идентификатора (UDID) для объекта GeoJSON. UDID — это значение послеmetadata/
, не включаяapi-version
. Например, еслиresourceLocation
был:{ "resourceLocation": "https://us.atlas.microsoft.com/mapData/metadata/7c3776eb-da87-4c52-ae83-caadf980323a?api-version=1.0" }
Тогда UDID будет
7c3776eb-da87-4c52-ae83-caadf980323a
.Сохраните этот UDID, так как он понадобится вам для проверки геозоны.
Проверка точек относительно геозоны
После загрузки многоугольника в Azure Maps вы можете проверить, находится ли точка внутри или вне геозоны. Для этого выполните запрос к веб-API, передав UDID геозоны, а также широту и долготу проверяемой точки.
При выполнении этого запроса вы также можете передать значение, называемое searchBuffer
. Оно указывает API карт, насколько точно возвращать результаты. Это важно, так как GPS не является абсолютно точным, и иногда местоположение может быть смещено на несколько метров или больше. По умолчанию searchBuffer
равен 50 м, но вы можете установить значения от 0 м до 500 м.
Когда результаты возвращаются из API, одна из частей результата — это distance
, измеряемое до ближайшей точки на краю геозоны. Значение будет положительным, если точка находится вне геозоны, и отрицательным, если она внутри. Если это расстояние меньше searchBuffer
, возвращается фактическое расстояние в метрах, иначе значение будет 999 или -999. 999 означает, что точка находится вне геозоны на расстоянии, превышающем searchBuffer
, -999 означает, что точка находится внутри геозоны на расстоянии, превышающем searchBuffer
.
На изображении выше геозона имеет буфер поиска 50 м.
- Точка в центре геозоны, далеко внутри буфера поиска, имеет расстояние -999.
- Точка далеко за пределами буфера поиска имеет расстояние 999.
- Точка внутри геозоны и внутри буфера поиска, на расстоянии 6 м от геозоны, имеет расстояние 6 м.
- Точка вне геозоны и внутри буфера поиска, на расстоянии 39 м от геозоны, имеет расстояние 39 м.
Важно знать расстояние до края геозоны и комбинировать эту информацию с другими данными, такими как другие GPS-замеры, скорость и данные о дорогах, при принятии решений на основе местоположения транспортного средства.
Например, представьте, что GPS-замеры показывают, что транспортное средство движется по дороге, которая проходит рядом с геозоной. Если одно значение GPS окажется неточным и покажет, что транспортное средство находится внутри геозоны, хотя доступ для транспортных средств отсутствует, это значение можно проигнорировать.
На изображении показана геозона, охватывающая часть кампуса Microsoft. Красная линия обозначает движение грузовика по трассе 520, а круги показывают GPS-замеры. Большинство из них точны и находятся вдоль трассы 520, но один из замеров оказался внутри геозоны. Этот замер не может быть правильным — на территории кампуса нет дорог, по которым грузовик мог бы внезапно свернуть с трассы 520, а затем вернуться обратно. Код, проверяющий эту геозону, должен учитывать предыдущие замеры перед тем, как действовать на основе результатов теста геозоны.
✅ Какие дополнительные данные вам понадобятся, чтобы проверить, можно ли считать GPS-замер корректным?
Задача — тестирование точек относительно геозоны
-
Начните с создания URL для запроса к веб-API. Формат:
https://atlas.microsoft.com/spatial/geofence/json?api-version=1.0&deviceId=gps-sensor&subscription-key=<subscription-key>&udid=<UDID>&lat=<lat>&lon=<lon>
Замените
<subscription_key>
на ключ API для вашей учетной записи Azure Maps.Замените
<UDID>
на UDID геозоны из предыдущего задания.Замените
<lat>
и<lon>
на широту и долготу, которые вы хотите протестировать.Этот URL использует API
https://atlas.microsoft.com/spatial/geofence/json
для запроса геозоны, определенной с помощью GeoJSON. Он нацелен на версию API1.0
. ПараметрdeviceId
обязателен и должен быть именем устройства, от которого поступают широта и долгота.По умолчанию радиус поиска составляет 50 м, и вы можете изменить его, добавив дополнительный параметр
searchBuffer=<distance>
, где<distance>
— радиус поиска в метрах, от 0 до 500. -
Используйте curl для выполнения GET-запроса к этому URL:
curl --request GET '<URL>'
💁 Если вы получите код ответа
BadRequest
с ошибкой:Invalid GeoJSON: All feature properties should contain a geometryId, which is used for identifying the geofence.
это означает, что в вашем GeoJSON отсутствует раздел
properties
сgeometryId
. Вам нужно исправить GeoJSON, затем повторить шаги выше, чтобы повторно загрузить файл и получить новый UDID. -
Ответ будет содержать список
geometries
, по одному для каждого полигона, определенного в GeoJSON, использованном для создания геозоны. Каждый полигон имеет 3 интересующих поля:distance
,nearestLat
иnearestLon
.{ "geometries": [ { "deviceId": "gps-sensor", "udId": "7c3776eb-da87-4c52-ae83-caadf980323a", "geometryId": "1", "distance": 999.0, "nearestLat": 47.645875, "nearestLon": -122.142713 } ], "expiredGeofenceGeometryId": [], "invalidPeriodGeofenceGeometryId": [] }
-
nearestLat
иnearestLon
— это широта и долгота точки на границе геозоны, ближайшей к тестируемому местоположению. -
distance
— расстояние от тестируемого местоположения до ближайшей точки на границе геозоны. Отрицательные числа означают, что точка находится внутри геозоны, положительные — снаружи. Это значение будет меньше 50 (по умолчанию радиус поиска) или равно 999.
-
-
Повторите это несколько раз с местоположениями внутри и вне геозоны.
Использование геозон в серверless-коде
Теперь вы можете добавить новый триггер в ваше приложение Functions для проверки данных GPS событий IoT Hub относительно геозоны.
Группы потребителей
Как вы помните из предыдущих уроков, IoT Hub позволяет воспроизводить события, которые были получены хабом, но не обработаны. Но что произойдет, если подключится несколько триггеров? Как хаб узнает, какой из них обработал какие события?
Ответ: никак! Вместо этого вы можете определить несколько отдельных подключений для чтения событий, и каждое из них может управлять воспроизведением непрочитанных сообщений. Эти подключения называются группами потребителей. При подключении к конечной точке вы можете указать, к какой группе потребителей вы хотите подключиться. Каждый компонент вашего приложения будет подключаться к отдельной группе потребителей.
Теоретически до 5 приложений могут подключаться к каждой группе потребителей, и все они будут получать сообщения по мере их поступления. Наилучшей практикой является подключение только одного приложения к каждой группе потребителей, чтобы избежать дублирования обработки сообщений и обеспечить правильную обработку всех очередных сообщений при перезапуске. Например, если вы запустите ваше приложение Functions локально, а также в облаке, оба будут обрабатывать сообщения, что приведет к дублированию blob-объектов, сохраненных в учетной записи хранилища.
Если вы откроете файл function.json
для триггера IoT Hub, созданного в предыдущем уроке, вы увидите группу потребителей в разделе привязки триггера Event Hub:
"consumerGroup": "$Default"
При создании IoT Hub по умолчанию создается группа потребителей $Default
. Если вы хотите добавить дополнительный триггер, вы можете сделать это, используя новую группу потребителей.
💁 В этом уроке вы будете использовать другую функцию для проверки геозоны, отличную от той, которая используется для хранения данных GPS. Это сделано для демонстрации использования групп потребителей и разделения кода, чтобы сделать его более читаемым и понятным. В производственном приложении существует множество способов архитектурного решения — объединение обеих функций в одну, использование триггера на учетной записи хранилища для запуска функции проверки геозоны или использование нескольких функций. Нет "правильного" способа, все зависит от остальной части вашего приложения и ваших потребностей.
Задача — создание новой группы потребителей
-
Выполните следующую команду для создания новой группы потребителей с именем
geofence
для вашего IoT Hub:az iot hub consumer-group create --name geofence \ --hub-name <hub_name>
Замените
<hub_name>
на имя, которое вы использовали для вашего IoT Hub. -
Если вы хотите увидеть все группы потребителей для IoT Hub, выполните следующую команду:
az iot hub consumer-group list --output table \ --hub-name <hub_name>
Замените
<hub_name>
на имя, которое вы использовали для вашего IoT Hub. Это отобразит список всех групп потребителей.Name ResourceGroup -------- --------------- $Default gps-sensor geofence gps-sensor
💁 Когда вы запускали монитор событий IoT Hub в предыдущем уроке, он подключался к группе потребителей
$Default
. Именно поэтому вы не можете одновременно запускать монитор событий и триггер событий. Если вы хотите запустить оба, вы можете использовать другие группы потребителей для всех ваших приложений Functions, а$Default
оставить для монитора событий.
Задача — создание нового триггера IoT Hub
-
Добавьте новый триггер событий IoT Hub в ваше приложение
gps-trigger
, созданное в предыдущем уроке. Назовите эту функциюgeofence-trigger
.⚠️ Вы можете обратиться к инструкциям по созданию триггера событий IoT Hub из проекта 2, урока 5, если это необходимо.
-
Настройте строку подключения IoT Hub в файле
function.json
. Файлlocal.settings.json
используется всеми триггерами в приложении Functions. -
Обновите значение
consumerGroup
в файлеfunction.json
, чтобы оно ссылалось на новую группу потребителейgeofence
:"consumerGroup": "geofence"
-
Вам понадобится ключ подписки для вашей учетной записи Azure Maps в этом триггере, поэтому добавьте новую запись в файл
local.settings.json
с именемMAPS_KEY
. -
Запустите приложение Functions, чтобы убедиться, что оно подключается и обрабатывает сообщения. Триггер
iot-hub-trigger
из предыдущего урока также будет работать и загружать blob-объекты в хранилище.Чтобы избежать дублирования GPS-замеров в blob-хранилище, вы можете остановить приложение Functions, которое у вас работает в облаке. Для этого используйте следующую команду:
az functionapp stop --resource-group gps-sensor \ --name <functions_app_name>
Замените
<functions_app_name>
на имя, которое вы использовали для вашего приложения Functions.Вы можете перезапустить его позже с помощью следующей команды:
az functionapp start --resource-group gps-sensor \ --name <functions_app_name>
Замените
<functions_app_name>
на имя, которое вы использовали для вашего приложения Functions.
Задача — тестирование геозоны из триггера
Ранее в этом уроке вы использовали curl для запроса геозоны, чтобы определить, находится ли точка внутри или снаружи. Вы можете выполнить аналогичный веб-запрос из вашего триггера.
-
Чтобы запросить геозону, вам нужен ее UDID. Добавьте новую запись в файл
local.settings.json
с именемGEOFENCE_UDID
и этим значением. -
Откройте файл
__init__.py
из нового триггераgeofence-trigger
. -
Добавьте следующий импорт в начало файла:
import json import os import requests
Пакет
requests
позволяет выполнять вызовы веб-API. У Azure Maps нет Python SDK, поэтому для использования его из Python-кода необходимо выполнять вызовы веб-API. -
Добавьте следующие 2 строки в начало метода
main
, чтобы получить ключ подписки Maps:maps_key = os.environ['MAPS_KEY'] geofence_udid = os.environ['GEOFENCE_UDID']
-
Внутри цикла
for event in events
добавьте следующий код для получения широты и долготы из каждого события:event_body = json.loads(event.get_body().decode('utf-8')) lat = event_body['gps']['lat'] lon = event_body['gps']['lon']
Этот код преобразует JSON из тела события в словарь, затем извлекает
lat
иlon
из поляgps
. -
При использовании
requests
, вместо создания длинного URL, как вы делали с curl, вы можете использовать только часть URL и передать параметры в виде словаря. Добавьте следующий код для определения URL и настройки параметров:url = 'https://atlas.microsoft.com/spatial/geofence/json' params = { 'api-version': 1.0, 'deviceId': 'gps-sensor', 'subscription-key': maps_key, 'udid' : geofence_udid, 'lat' : lat, 'lon' : lon }
Элементы в словаре
params
будут соответствовать ключевым значениям, которые вы использовали при вызове веб-API через curl. -
Добавьте следующие строки кода для вызова веб-API:
response = requests.get(url, params=params) response_body = json.loads(response.text)
Это вызывает URL с параметрами и возвращает объект ответа.
-
Добавьте следующий код ниже этого:
distance = response_body['geometries'][0]['distance'] if distance == 999: logging.info('Point is outside geofence') elif distance > 0: logging.info(f'Point is just outside geofence by a distance of {distance}m') elif distance == -999: logging.info(f'Point is inside geofence') else: logging.info(f'Point is just inside geofence by a distance of {distance}m')
Этот код предполагает наличие одного полигона и извлекает расстояние от этого единственного полигона. Затем он записывает разные сообщения в журнал в зависимости от расстояния.
-
Запустите этот код. Вы увидите в выводе журнала, находятся ли GPS-координаты внутри или вне геозоны, с указанием расстояния, если точка находится в пределах 50 м. Попробуйте этот код с различными геозонами, основываясь на местоположении вашего GPS-датчика, попробуйте переместить датчик (например, подключив его к Wi-Fi через мобильный телефон или с другими координатами на виртуальном IoT-устройстве), чтобы увидеть изменения.
-
Когда будете готовы, разверните этот код в вашем приложении Functions в облаке. Не забудьте развернуть новые настройки приложения.
⚠️ Вы можете обратиться к инструкциям по загрузке настроек приложения из проекта 2, урока 5, если это необходимо.
⚠️ Вы можете обратиться к инструкциям по развертыванию вашего приложения Functions из проекта 2, урока 5, если это необходимо.
💁 Вы можете найти этот код в папке code/functions.
🚀 Челлендж
В этом уроке вы добавили одну геозону, используя GeoJSON-файл с одним полигоном. Вы можете загрузить несколько полигонов одновременно, если они имеют разные значения geometryId
в разделе properties
.
Попробуйте загрузить GeoJSON-файл с несколькими полигонами и измените ваш код, чтобы определить, к какому полигону GPS-координаты ближе или в каком они находятся.
Пост-лекционный тест
Обзор и самостоятельное изучение
- Прочитайте больше о геозонах и их применении на странице о геозонах в Википедии.
- Прочитайте больше о API геозон Azure Maps в документации Microsoft Azure Maps Spatial - Get Geofence.
- Прочитайте больше о группах потребителей в документации Microsoft о функциях и терминологии Azure Event Hubs - Event consumers.
Задание
Отправка уведомлений с помощью Twilio
Отказ от ответственности:
Этот документ был переведен с помощью сервиса автоматического перевода Co-op Translator. Хотя мы стремимся к точности, пожалуйста, учитывайте, что автоматические переводы могут содержать ошибки или неточности. Оригинальный документ на его исходном языке следует считать авторитетным источником. Для получения критически важной информации рекомендуется профессиональный перевод человеком. Мы не несем ответственности за любые недоразумения или неправильные интерпретации, возникшие в результате использования данного перевода.