You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
IoT-For-Beginners/translations/bg/3-transport/lessons/4-geofences
co-op-translator[bot] 67710c800c
🌐 Update translations via Co-op Translator (#554)
4 weeks ago
..
README.md 🌐 Update translations via Co-op Translator (#554) 4 weeks ago
assignment.md 🌐 Update translations via Co-op Translator (#554) 4 weeks ago

README.md

Геозони

Скица на урока

Скица от Nitya Narasimhan. Кликнете върху изображението за по-голяма версия.

Това видео предоставя общ преглед на геозоните и как да ги използвате в Azure Maps, теми, които ще бъдат разгледани в този урок:

Геозони с Azure Maps от Microsoft Developer IoT шоу

🎥 Кликнете върху изображението по-горе, за да гледате видеото

Тест преди урока

Тест преди урока

Въведение

В последните три урока използвахте IoT, за да локализирате камионите, които транспортират продукцията ви от фермата до центъра за обработка. Заснехте GPS данни, изпратихте ги в облака за съхранение и ги визуализирахте на карта. Следващата стъпка за повишаване на ефективността на вашата верига за доставки е да получите известие, когато камионът е на път да пристигне в центъра за обработка, за да може екипът, който трябва да разтовари, да бъде готов с мотокари и друго оборудване веднага щом превозното средство пристигне. По този начин разтоварването може да стане бързо и няма да плащате за камион и шофьор, които чакат.

В този урок ще научите за геозоните - определени геопространствени региони, като например зона в рамките на 2 км от центъра за обработка, и как да тествате дали GPS координатите са вътре или извън геозоната, за да видите дали вашият GPS сензор е пристигнал или напуснал дадена зона.

В този урок ще разгледаме:

🗑 Това е последният урок в този проект, така че след като завършите урока и задачата, не забравяйте да почистите облачните си услуги. Ще ви трябват услугите, за да завършите задачата, така че се уверете, че първо сте я завършили.

Вижте ръководството за почистване на проекта, ако е необходимо, за инструкции как да направите това.

Какво са геозони

Геозоната е виртуален периметър за реален географски регион. Геозоните могат да бъдат кръгове, дефинирани като точка и радиус (например кръг с ширина 100 м около сграда), или полигони, обхващащи зона като училищна зона, градски граници или университетски или офис кампус.

Примери за геозони, показващи кръгова геозона около магазина на Microsoft и полигонална геозона около западния кампус на Microsoft

💁 Може би вече сте използвали геозони, без да знаете. Ако сте задали напомняне с приложението за напомняния на iOS или 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 беше масив, съдържащ 2 стойности, ширина и дължина, за Polygon това е масив от масиви, съдържащи 2 стойности, дължина и ширина.

💁 Запомнете, GeoJSON използва дължина, ширина за точки, а не ширина, дължина

Масивът с координати на полигона винаги има 1 запис повече от броя на точките на полигона, като последният запис е същият като първия, затваряйки полигона. Например, за правоъгълник ще има 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 е инструмент за команден ред за извършване на заявки към уеб крайни точки

  1. Ако използвате Linux, macOS или последна версия на Windows 10, вероятно вече имате инсталиран curl. Изпълнете следното от вашия терминал или команден ред, за да проверите:

    curl --version
    

    Ако не виждате информация за версията на curl, ще трябва да го инсталирате от страницата за изтегляне на curl.

    💁 Ако сте опитни с Postman, можете да го използвате вместо това, ако предпочитате.

  2. Създайте 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, ако са качени от различен файл в различно време.

  3. Запазете този файл като geofence.json и навигирайте до мястото, където е запазен, във вашия терминал или конзола.

  4. Изпълнете следната команда curl, за да създадете GeoFence:

    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, за да се посочи коя Azure Maps API да се използва, за да се позволи 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, разделяйки двойките ключ-стойност с &.

  5. Azure Maps не обработва това незабавно, така че ще трябва да проверите дали заявката за качване е завършена, като използвате URL, даден в заглавката location. Направете GET заявка към този URL, за да видите статуса. Ще трябва да добавите вашия абонаментен ключ към края на URL location, като добавите &subscription-key=<subscription_key> към края, заменяйки <subscription_key> с API ключа за вашия Azure Maps акаунт. Изпълнете следната команда:

    curl --request GET '<location>&subscription-key=<subscription_key>'
    

    Заменете <location> със стойността на заглавката location и <subscription_key> с API ключа за вашия Azure Maps акаунт.

  6. Проверете стойността на status в отговора. Ако не е Succeeded, изчакайте минута и опитайте отново.

  7. След като статусът се върне като 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. Това казва на Maps API колко точно да бъде при връщане на резултати. Причината за това е, че GPS не е напълно точен и понякога местоположенията могат да бъдат изместени с метри или повече. По подразбиране searchBuffer е 50 м, но можете да зададете стойности от 0 м до 500 м.

Когато резултатите се върнат от API заявката, една от частите на резултата е distance, измерена до най-близката точка на ръба на геозоната, с положителна стойност, ако точката е извън геозоната, и отрицателна, ако е вътре в геозоната. Ако това разстояние е по-малко от searchBuffer, действителното разстояние се връща в метри, в противен случай стойността е 999 или -999. 999 означава, че точката е извън геозоната с повече от searchBuffer, -999 означава, че е вътре в геозоната с повече от searchBuffer.

Геозона с 50 м буфер за търсене около нея

На изображението по-горе геозоната има 50 м буфер за търсене.

  • Точка в центъра на геозоната, далеч вътре в буфера за търсене, има разстояние -999
  • Точка далеч извън буфера за търсене има разстояние 999
  • Точка вътре в геозоната и вътре в буфера за търсене, на 6 м от геозоната, има разстояние 6 м
  • Точка извън геозоната и вътре в буфера за търсене, на 39 м от геозоната, има разстояние 39 м

Важно е да знаете разстоянието до ръба на геозоната и да го комбинирате с друга информация, като други GPS показания, скорост и данни за пътя, когато вземате решения въз основа на местоположението на превозното средство.

Например, представете си GPS показания, показващи, че превозното средство се движи по път, който в крайна сметка минава до геозона. Ако една GPS стойност е неточна и поставя превозното средство вътре в геозоната, въпреки че няма достъп за превозни средства, тогава тя може да бъде игнорирана.

GPS следа, показваща превозно средство, преминаващо покрай кампуса на Microsoft на 520, с GPS показания по пътя, освен едно на кампуса, вътре в геозона На изображението по-горе е показан геозон, обхващащ част от кампуса на Microsoft. Червената линия показва камион, който се движи по магистрала 520, като кръговете обозначават GPS отчитанията. Повечето от тях са точни и се намират по магистралата, но едно отчитане е неточно и попада в геозона. Няма как това отчитане да е вярно няма пътища, по които камионът внезапно да се отклони от магистралата към кампуса и след това да се върне обратно на магистралата. Кодът, който проверява този геозон, ще трябва да вземе предвид предишните отчитания, преди да действа въз основа на резултатите от теста на геозона.

Какви допълнителни данни бихте проверили, за да определите дали едно GPS отчитане може да се счита за вярно?

Задача - тестване на точки спрямо геозон

  1. Започнете със създаването на 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. Той използва версия на API 1.0. Параметърът deviceId е задължителен и трябва да бъде името на устройството, от което идват географската ширина и дължина.

    По подразбиране буферът за търсене е 50 м, но можете да го промените, като добавите допълнителен параметър searchBuffer=<distance>, където <distance> е разстоянието на буфера за търсене в метри, от 0 до 500.

  2. Използвайте 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.

  3. Отговорът ще съдържа списък с 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.

  4. Повторете това няколко пъти с местоположения вътре и извън геозоната.

Използване на геозони от безсървърен код

Сега можете да добавите нов тригер към вашето Functions приложение, за да тествате GPS данните от IoT Hub спрямо геозоната.

Групи на потребители

Както си спомняте от предишни уроци, IoT Hub ви позволява да възпроизвеждате събития, които са получени от хъба, но не са обработени. Но какво ще се случи, ако се свържат няколко тригера? Как ще знае кой е обработил кои събития?

Отговорът е, че не може! Вместо това можете да дефинирате няколко отделни връзки за четене на събития, като всяка от тях управлява възпроизвеждането на непрочетените съобщения. Те се наричат групи на потребители. Когато се свържете към крайна точка, можете да посочите към коя група на потребители искате да се свържете. Всеки компонент на вашето приложение ще се свърже към различна група на потребители.

Един IoT Hub с 3 групи на потребители, разпределящи едни и същи съобщения към 3 различни функции

Теоретично до 5 приложения могат да се свържат към всяка група на потребители и всички те ще получават съобщения, когато пристигнат. Най-добрата практика е само едно приложение да има достъп до всяка група на потребители, за да се избегне дублиране на обработката на съобщения и да се гарантира, че при рестартиране всички съобщения в опашката ще бъдат обработени правилно. Например, ако стартирате вашето Functions приложение локално, както и в облака, и двете ще обработват съобщения, което ще доведе до дублиране на данни в хранилището.

Ако прегледате файла function.json за тригера на IoT Hub, който създадохте в по-ранен урок, ще видите групата на потребители в секцията за свързване на тригера на Event Hub:

"consumerGroup": "$Default"

Когато създадете IoT Hub, по подразбиране се създава групата на потребители $Default. Ако искате да добавите допълнителен тригер, можете да го направите, като използвате нова група на потребители.

💁 В този урок ще използвате различна функция за тестване на геозоната от тази, която се използва за съхраняване на GPS данни. Това е, за да се покаже как да се използват групи на потребители и да се раздели кодът, за да бъде по-лесен за четене и разбиране. В производствено приложение има много начини, по които можете да структурирате това като поставите и двете в една функция, като използвате тригер върху хранилището, за да стартирате функция за проверка на геозоната, или като използвате множество функции. Няма "правилен начин" това зависи от останалата част от вашето приложение и вашите нужди.

Задача - създаване на нова група на потребители

  1. Изпълнете следната команда, за да създадете нова група на потребители, наречена geofence, за вашия IoT Hub:

    az iot hub consumer-group create --name geofence \
                                     --hub-name <hub_name>
    

    Заменете <hub_name> с името, което сте използвали за вашия IoT Hub.

  2. Ако искате да видите всички групи на потребители за 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. Това беше причината, поради която не можете да стартирате монитора на събития и тригера на събития едновременно. Ако искате да стартирате и двете, тогава можете да използвате други групи на потребители за всички ваши функции, като запазите $Default за монитора на събития.

Задача - създаване на нов тригер за IoT Hub

  1. Добавете нов тригер за събития на IoT Hub към вашето приложение gps-trigger, което създадохте в по-ранен урок. Наречете тази функция geofence-trigger.

    ⚠️ Можете да се обърнете към инструкциите за създаване на тригер за събития на IoT Hub от проект 2, урок 5, ако е необходимо.

  2. Конфигурирайте низ за връзка към IoT Hub във файла function.json. Файлът local.settings.json се споделя между всички тригери в приложението.

  3. Актуализирайте стойността на consumerGroup във файла function.json, за да се отнася към новата група на потребители geofence:

    "consumerGroup": "geofence"
    
  4. Ще трябва да използвате ключа за абонамент за вашия Azure Maps акаунт в този тригер, така че добавете нов запис към файла local.settings.json, наречен MAPS_KEY.

  5. Стартирайте приложението, за да се уверите, че се свързва и обработва съобщения. Тригерът iot-hub-trigger от по-ранния урок също ще се стартира и ще качва данни в хранилището.

    За да избегнете дублиране на GPS отчитания в хранилището, можете да спрете приложението, което работи в облака. За да направите това, използвайте следната команда:

    az functionapp stop --resource-group gps-sensor \
                        --name <functions_app_name>
    

    Заменете <functions_app_name> с името, което сте използвали за вашето приложение.

    Можете да го рестартирате по-късно със следната команда:

    az functionapp start --resource-group gps-sensor \
                        --name <functions_app_name>
    

    Заменете <functions_app_name> с името, което сте използвали за вашето приложение.

Задача - тестване на геозоната от тригера

По-рано в този урок използвахте curl, за да направите заявка към геозона и да проверите дали дадена точка се намира вътре или извън нея. Можете да направите подобна уеб заявка от вашия тригер.

  1. За да направите заявка към геозоната, ви е необходим неговият UDID. Добавете нов запис към файла local.settings.json, наречен GEOFENCE_UDID, с тази стойност.

  2. Отворете файла __init__.py от новия тригер geofence-trigger.

  3. Добавете следния импорт в началото на файла:

    import json
    import os
    import requests
    

    Пакетът requests ви позволява да правите уеб API заявки. Azure Maps няма Python SDK, така че трябва да правите уеб API заявки, за да го използвате от Python код.

  4. Добавете следните два реда в началото на метода main, за да получите ключа за абонамент за Maps:

    maps_key = os.environ['MAPS_KEY']
    geofence_udid = os.environ['GEOFENCE_UDID']    
    
  5. Вътре в цикъла 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.

  6. Когато използвате 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.

  7. Добавете следните редове код, за да направите заявка към уеб API:

    response = requests.get(url, params=params)
    response_body = json.loads(response.text)
    

    Това извиква URL с параметрите и връща обект с отговор.

  8. Добавете следния код под този:

    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')
    

    Този код предполага един полигон и извлича разстоянието от този единствен полигон. След това записва различни съобщения въз основа на разстоянието.

  9. Стартирайте този код. В изхода на логовете ще видите дали GPS координатите са вътре или извън геозоната, с разстояние, ако точката е в рамките на 50 м. Тествайте този код с различни геозони въз основа на местоположението на вашия GPS сензор, опитайте да преместите сензора (например свързан към WiFi от мобилен телефон или с различни координати на виртуалното IoT устройство), за да видите промяната.

  10. Когато сте готови, разположете този код във вашето Functions приложение в облака. Не забравяйте да качите новите настройки на приложението.

    ⚠️ Можете да се обърнете към инструкциите за качване на настройки на приложението от проект 2, урок 5, ако е необходимо.

    ⚠️ Можете да се обърнете към инструкциите за разполагане на вашето Functions приложение от проект 2, урок 5, ако е необходимо.

💁 Можете да намерите този код в папката code/functions.


🚀 Предизвикателство

В този урок добавихте един геозон, използвайки GeoJSON файл с един полигон. Можете да качите множество полигони едновременно, стига да имат различни стойности за geometryId в секцията properties.

Опитайте да качите GeoJSON файл с множество полигони и коригирайте кода си, за да намерите кой полигон е най-близо до GPS координатите или в кой полигон се намират.

Тест след урока

Тест след урока

Преглед и самостоятелно обучение

Задание

Изпращане на известия с Twilio


Отказ от отговорност:
Този документ е преведен с помощта на AI услуга за превод Co-op Translator. Въпреки че се стремим към точност, моля, имайте предвид, че автоматичните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия изходен език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален превод от човек. Не носим отговорност за каквито и да е недоразумения или погрешни интерпретации, произтичащи от използването на този превод.