{"id":1777,"date":"2020-04-17T06:24:19","date_gmt":"2020-04-17T06:24:19","guid":{"rendered":"http:\/\/www.sabulo.com\/sb\/?p=1777"},"modified":"2020-04-17T09:06:51","modified_gmt":"2020-04-17T09:06:51","slug":"using-the-udp-protocol-with-an-esp32-and-android-studio-part-2","status":"publish","type":"post","link":"https:\/\/www.sabulo.com\/sb\/esp32-development-board\/using-the-udp-protocol-with-an-esp32-and-android-studio-part-2\/","title":{"rendered":"Using the UDP protocol with an ESP32 and Android Studio, Part 2"},"content":{"rendered":"\n<p>In the <a href=\"https:\/\/www.sabulo.com\/sb\/esp32-development-board\/using-the-udp-protocol-with-an-esp32-and-android-studio-part-1\/\" target=\"_blank\" rel=\"noreferrer noopener\">first episode of this three part saga<\/a>, I gave you a basic overview of the workflow when working with ESP32s and UDP datagrams. This time, I am going to walk you through the receiving end, and the best way to do that is to explain to you how the code works. The<a rel=\"noreferrer noopener\" href=\"http:\/\/www.github.com\/heikkihietala\" target=\"_blank\"> entire system will be available on my GitHub account<\/a>, and you can just download everything from there, use the app, and flash your ESP32 with the relevant code.<\/p>\n\n\n\n<p>To get started with ESP32, if you are all new to the idea, you should install the support for ESP32 in your Arduino IDE. The best place to learn how to do that is <a rel=\"noreferrer noopener\" href=\"https:\/\/randomnerdtutorials.com\/projects-esp32\/\" target=\"_blank\">RandomNerdTutorials, an excellent site <\/a>for just about anything related to ESP32 and its predecessor, ESP8266.  <\/p>\n\n\n\n<p>The code I will go through is geared towards the Heltec ESP32 with an integrated OLED display. Therefore all code that starts with Heltec can be ignored by you if you don&#8217;t have such a device, but a regular ESP32 instead. On the other hand, if you want to see feedback from your device, you should add code that uses the Serial Monitor. I will add both versions of the code to the Github repo, so that you can pick the one that suits your ESP3a version<\/p>\n\n\n\n<p>So, I&#8217;ll post parts of the code and explain each part as I go. The code is commented too, so both can be used to understand how it works. My system will eventually drive a small car, with the UDP commands setting out both speed and angle of the servo that is steering the car. If you use yours for something else, it&#8217;s easy enough to use these structures and do something different.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Includes and Variables<\/h3>\n\n\n\n<pre class=\"wp-block-preformatted\">#include \"AsyncUDP.h\"\n#include \"WiFi.h\"\n#include \"heltec.h\"\n#include \"images.h\"\nconst char* ssid = \"YOUR_SSID_HERE\";\nconst char* pass = \"YOUR_PASSWORD_HERE\";\nString udpSpeed, udpDir;\nint localPort = 1234;\nint driveSpeed, driveDir;\n\/\/ Motor A\nint motor1Pin1 = 27;\nint motor1Pin2 = 26;\nint enable1Pin = 14;\n\/\/ Setting PWM properties\nconst int freq = 30000;\nconst int pwmChannel = 0;\nconst int resolution = 8;\nint dutyCycle = 200;\n\/\/ Servo\nconst int turnPin = 12; \/\/Steering Servo Pin\nint myTurn;\n\nAsyncUDP udp;<\/pre>\n\n\n\n<p>So, in the top we have four includes: <strong>Asynch.h<\/strong> and <strong>Wifi.h<\/strong> are vital for getting your ESP32 to connect to yourWifi and to use the UDP protocol. Heltec.h and Images.h are Heltec OLED specific files and can be omitted if you are not on Heltec.<\/p>\n\n\n\n<p>Replace the ssid and pass with your own network info. The localPort variable states which port your UDP messages should be sent to. The next things from driveSpeed to myTurn are again specific to my use of the UDP, and you probably want to replace these with what you need to do.<\/p>\n\n\n\n<p>The <strong>AsyncUDP<\/strong> creates an objcct called <strong>udp<\/strong>, which is the receptable of your messages. It will be vitally important later.<\/p>\n\n\n\n<p>My messages are strings. You can also send hexadecimal messages, if that suits you better. I suggest you go get <a href=\"https:\/\/play.google.com\/store\/apps\/details?id=com.hastarin.android.udpsender&amp;hl=fi\" target=\"_blank\" rel=\"noreferrer noopener\">the very useful application, UDPSender, from App Store<\/a>. With that installed, you can define the IP address you get from your ESP32, and the port you set up in the code, and see your messages appear on the ESP32.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">The Setup() function<\/h3>\n\n\n\n<pre class=\"wp-block-preformatted\">void setup() {\nHeltec.begin(true \/<em>DisplayEnable Enable<\/em>\/, false \/<em>LoRa Enable<\/em>\/, true \/<em>Serial Enable<\/em>\/);\nHeltec.display -&gt; clear();\nHeltec.display -&gt; drawXbm(0, 0, hhlogo_width, hhlogo_height, hhlogo_bits);\nHeltec.display -&gt; display();\ndelay(2000);\nHeltec.display -&gt; clear();\nHeltec.display -&gt; drawXbm(0, 0, robolablogo_width, robolablogo_height, robolablogo_bits);\nHeltec.display -&gt; display();\ndelay(2000);\nHeltec.display -&gt; clear();\nHeltec.display-&gt;setFont(ArialMT_Plain_10);\n\/\/ Initialize Serial Monitor\nHeltec.display-&gt;drawString(0, 0, \"Connecting to WLAN\");\nHeltec.display -&gt; display();\nSerial.begin(115200);<\/pre>\n\n\n\n<p>In this part of the Setup function, a couple of logo files are displayed, <a rel=\"noreferrer noopener\" href=\"https:\/\/www.sabulo.com\/sb\/esp32-development-board\/how-to-use-the-heltec-oled-display-on-the-esp32\/\" target=\"_blank\">as described in the blog post on Heltec<\/a>, so if you are not on Heltec, you can again ignore everything up to <strong>Serial.begin(115200)<\/strong>, which is needed to start the Serial Monitor communication.<\/p>\n\n\n\n<p>Then we go on to starting the network connection and settling in to wait for the UDP datagrams.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">WiFi.disconnect(true); \/\/this is needed to make sure net is off\nWiFi.mode(WIFI_STA); \/\/setup wifi in station mode\nWiFi.begin(ssid, pass); \/\/start connection\nwhile (WiFi.status() != WL_CONNECTED) { \/\/loop and wait until connected\ndelay(500);\nSerial.print(\".\");\n}\nHeltec.display-&gt;clear(); \/\/clear display and show data\nHeltec.display-&gt;drawString(0, 0, \"WiFi connected.\");\nHeltec.display-&gt;drawString(0, 12, \"IP address: \");\nHeltec.display-&gt;drawString(0, 24, String(WiFi.localIP().toString()));\nHeltec.display-&gt;drawString(0, 36, \"UDP Listening on: \" + String(localPort));\nHeltec.display -&gt; display(); \/\/show the info\ndelay(2000); \/\/for 2000 ms, ie. 2 seconds.<\/pre>\n\n\n\n<p>The last part of the Setup function is again specific to my adaptation of this protocol and deals with the setting up of a motor for driving the car and a servo for steering it.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">\/\/ sets the pins as outputs:\npinMode(motor1Pin1, OUTPUT);\npinMode(motor1Pin2, OUTPUT);\npinMode(enable1Pin, OUTPUT);\n\/\/ configure LED PWM functionalitites\nledcSetup(pwmChannel, freq, resolution);\n\/\/ attach the channel to the GPIO to be controlled\nledcAttachPin(enable1Pin, pwmChannel);\nledcSetup(4, 50, 16); \/\/channel, freq, resolution for servo\nledcAttachPin(turnPin, 4); \/\/ pin, channel\n}<\/pre>\n\n\n\n<p>And now we are set up, the system is listening to the UDP datagrams on Port 1234, or whatever you set up in the code. The good thing about this little display is that if you were to have multiple devices around, you could easily see what IP and what port are available on any devices. <\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1536\" height=\"864\" src=\"https:\/\/i0.wp.com\/www.sabulo.com\/sb\/wp-content\/uploads\/2020\/04\/esp03.png?fit=825%2C464&amp;ssl=1\" alt=\"\" class=\"wp-image-1819\" srcset=\"https:\/\/i0.wp.com\/www.sabulo.com\/sb\/wp-content\/uploads\/2020\/04\/esp03.png?w=1536&amp;ssl=1 1536w, https:\/\/i0.wp.com\/www.sabulo.com\/sb\/wp-content\/uploads\/2020\/04\/esp03.png?resize=300%2C169&amp;ssl=1 300w, https:\/\/i0.wp.com\/www.sabulo.com\/sb\/wp-content\/uploads\/2020\/04\/esp03.png?resize=1024%2C576&amp;ssl=1 1024w, https:\/\/i0.wp.com\/www.sabulo.com\/sb\/wp-content\/uploads\/2020\/04\/esp03.png?resize=768%2C432&amp;ssl=1 768w\" sizes=\"auto, (max-width: 825px) 100vw, 825px\" \/><figcaption>ESP32 all raring to go<\/figcaption><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">The main loop<\/h3>\n\n\n\n<p>The main loop is just a cycle with a little delay in it to allow for the messages to be dealt with. The UDP is a buffer that is filled with the message, then the buffer is converted into text, and the text parsed into values. These values in my application are passed to a function that turns the motor at the set speed and turns the servo to the desired angle. Let&#8217;s look at the loop.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">void loop()\n{\nHeltec.display-&gt;setFont(ArialMT_Plain_10); \/\/set font\nif (udp.listen(localPort)) { \/\/this is triggered by a message\ndelay(100);\nudp.onPacket([](AsyncUDPPacket packet) {\nchar buf[packet.length() + 1] = {};\nmemcpy(buf, packet.data(), packet.length());\nString s = String(buf);\nint udpSplit = s.indexOf(\",\");\nudpSpeed = s.substring(0, udpSplit);\nudpDir = s.substring(udpSplit + 1, packet.length());\n\n\/\/manage the display to show the data\nHeltec.display-&gt;clear();\nHeltec.display-&gt;drawString(0, 0, \"Incoming packet: \" + s);\nHeltec.display-&gt;setFont(ArialMT_Plain_16);\nHeltec.display-&gt;drawString(0, 15, \"Speed: \" + udpSpeed);\nHeltec.display-&gt;drawString(0, 35, \"Direction: \" + udpDir);\nHeltec.display -&gt; display();\n\n\/\/make speed and direction integers\ndriveSpeed = udpSpeed.toInt();\ndriveDir = udpDir.toInt();\nSerial.println(driveSpeed);\n\n\/\/go to function RunMotor to actually run the car\nrunMotor (driveDir, driveSpeed);\ndelay(100);\n});\n}\n}<\/pre>\n\n\n\n<p>So, the way it works is this: when the UDP object finds out that there is a message in the UDP port, the packet is read into a character buffer, called <strong>buf<\/strong>. The function <strong>memcpy<\/strong> copies the message data to the buffer. This buffer is then made into a String, called <strong>s<\/strong>. This entire packet is displayed on the top of the OLED, in its whole form, with this piece of code:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">Heltec.display-&gt;drawString(0, 0, \"Incoming packet: \" + s);<\/pre>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1040\" height=\"500\" src=\"https:\/\/i2.wp.com\/www.sabulo.com\/sb\/wp-content\/uploads\/2020\/04\/in-action.jpg?fit=825%2C396&amp;ssl=1\" alt=\"\" class=\"wp-image-1821\" srcset=\"https:\/\/i0.wp.com\/www.sabulo.com\/sb\/wp-content\/uploads\/2020\/04\/in-action.jpg?w=1040&amp;ssl=1 1040w, https:\/\/i0.wp.com\/www.sabulo.com\/sb\/wp-content\/uploads\/2020\/04\/in-action.jpg?resize=300%2C144&amp;ssl=1 300w, https:\/\/i0.wp.com\/www.sabulo.com\/sb\/wp-content\/uploads\/2020\/04\/in-action.jpg?resize=1024%2C492&amp;ssl=1 1024w, https:\/\/i0.wp.com\/www.sabulo.com\/sb\/wp-content\/uploads\/2020\/04\/in-action.jpg?resize=768%2C369&amp;ssl=1 768w\" sizes=\"auto, (max-width: 825px) 100vw, 825px\" \/><figcaption>Listening and acting on packets<\/figcaption><\/figure>\n\n\n\n<p>In my application, I send two integers for direction (values -5 to 5) and speed (values -10 to 10), values separated by a comma. If you have a different message you want to pass, you must handle the string according to your specifications, but the conversion to string structure is valid for any case.  The following bit is just a way of splitting the message into two parts.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">int udpSplit = s.indexOf(\",\"); \/\/find the index of the comma\nudpSpeed = s.substring(0, udpSplit);\/\/Speed is the first part\nudpDir = s.substring(udpSplit + 1, packet.length()); \/\/and direction is the latter part<\/pre>\n\n\n\n<p>Then there is some Heltec stuff again about displaying the UDP datagram first, and then split up into its constituent parts. This way I can monitor the incoming UDP data before I act on it. The last part merely takes the string, splits it at the comma, and then goes off to the function runMotor with the newly-minted values for speed and direction. The runMotor part isn&#8217;t probably all that interesting, but I&#8217;ll put it in here in any case.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">The runMotor and its auxiliary function<\/h3>\n\n\n\n<pre class=\"wp-block-preformatted\">void runMotor(int myDir, int mySpeed) {\nSerial.println(mySpeed);\nint finalSpeed;\nfinalSpeed = map(abs(mySpeed), 0, 10, 215, 255);\nSerial.println(finalSpeed);\nSerial.println(\"Moving Forward\");\nif (mySpeed &gt; 0) {\nSerial.println(\"Forward\");\ndigitalWrite(motor1Pin1, HIGH);\ndigitalWrite(motor1Pin2, LOW);\n} else if (mySpeed &lt; 0) {\nSerial.println(\"Back\");\ndigitalWrite(motor1Pin1, LOW);\ndigitalWrite(motor1Pin2, HIGH);\n} else {\nSerial.println(\"STOP\");\ndigitalWrite(motor1Pin1, LOW);\ndigitalWrite(motor1Pin2, LOW);\n}\nledcWrite(pwmChannel, finalSpeed);\nmyTurn = map (myDir, -10, 11, 36, 180);\nsteeringAnalogWrite(4, myTurn); \/\/ set steering\n}\n\nvoid steeringAnalogWrite(uint8_t channel, uint32_t value, uint32_t valueMax = 180) {\n\/\/ calculate duty, 8191 from 2 ^ 13 - 1\nuint32_t duty = (8191 \/ valueMax) * min(value, valueMax);\nledcWrite(channel, duty);\n}<\/pre>\n\n\n\n<p>This batch is rather self-explanatory. The runMotor takes two parameters, speed and direction. The <strong>Serial.println<\/strong> is just for monitoring what is being passed to the car &#8211; if everything works, it&#8217;s zooming around the room and you can&#8217;t read the OLED in any case. <\/p>\n\n\n\n<p>The <strong>finalSpeed <\/strong>variable is for mapping the inbound value, 10 to 10, to a scale of speed that the motor can use. The <strong>Map <\/strong>function is very handy in this and it maps the value from the parameter to a value between 210 and 255. 210 is rather slow and 255 is top speed. If the value is less than 0, then the motow is running counterclockwise and the car reverses, and id larger than 0, it moves forward.<\/p>\n\n\n\n<p>The function steering AnalogWrite is needed because the Heltec ESP32 doesn&#8217;t have a servo library that is compatible with regular ESP32s. That&#8217;s why it has to be done the hard way as shown in this function. It is irrelevant to the functioning of the car, but it took some extra pondering  to get to run.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">To sum it up<\/h3>\n\n\n\n<p>UDP can be a very good tool if you have a simple message to pass to a device, especially if you don&#8217;t have any security issues in broadcasting data with no ability to confirm delivery. The third part of this blog post set will discuss the building of an Android app.<\/p>\n<div class=\"pvc_clear\"><\/div><p id=\"pvc_stats_1777\" class=\"pvc_stats all  \" data-element-id=\"1777\" style=\"\"><i class=\"pvc-stats-icon medium\" aria-hidden=\"true\"><svg aria-hidden=\"true\" focusable=\"false\" data-prefix=\"far\" data-icon=\"chart-bar\" role=\"img\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 512 512\" class=\"svg-inline--fa fa-chart-bar fa-w-16 fa-2x\"><path fill=\"currentColor\" d=\"M396.8 352h22.4c6.4 0 12.8-6.4 12.8-12.8V108.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v230.4c0 6.4 6.4 12.8 12.8 12.8zm-192 0h22.4c6.4 0 12.8-6.4 12.8-12.8V140.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v198.4c0 6.4 6.4 12.8 12.8 12.8zm96 0h22.4c6.4 0 12.8-6.4 12.8-12.8V204.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v134.4c0 6.4 6.4 12.8 12.8 12.8zM496 400H48V80c0-8.84-7.16-16-16-16H16C7.16 64 0 71.16 0 80v336c0 17.67 14.33 32 32 32h464c8.84 0 16-7.16 16-16v-16c0-8.84-7.16-16-16-16zm-387.2-48h22.4c6.4 0 12.8-6.4 12.8-12.8v-70.4c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v70.4c0 6.4 6.4 12.8 12.8 12.8z\" class=\"\"><\/path><\/svg><\/i> <img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"16\" height=\"16\" alt=\"Loading\" src=\"https:\/\/i0.wp.com\/www.sabulo.com\/sb\/wp-content\/plugins\/page-views-count\/ajax-loader-2x.gif?resize=16%2C16&#038;ssl=1\" border=0 \/><\/p><div class=\"pvc_clear\"><\/div>","protected":false},"excerpt":{"rendered":"<p>In the first episode of this three part saga, I gave you a basic overview of the workflow when working &hellip; <a href=\"https:\/\/www.sabulo.com\/sb\/esp32-development-board\/using-the-udp-protocol-with-an-esp32-and-android-studio-part-2\/\" class=\"more-link\">More <span class=\"screen-reader-text\">Using the UDP protocol with an ESP32 and Android Studio, Part 2<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n<div class=\"pvc_clear\"><\/div>\n<p id=\"pvc_stats_1777\" class=\"pvc_stats all  \" data-element-id=\"1777\" style=\"\"><i class=\"pvc-stats-icon medium\" aria-hidden=\"true\"><svg aria-hidden=\"true\" focusable=\"false\" data-prefix=\"far\" data-icon=\"chart-bar\" role=\"img\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 512 512\" class=\"svg-inline--fa fa-chart-bar fa-w-16 fa-2x\"><path fill=\"currentColor\" d=\"M396.8 352h22.4c6.4 0 12.8-6.4 12.8-12.8V108.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v230.4c0 6.4 6.4 12.8 12.8 12.8zm-192 0h22.4c6.4 0 12.8-6.4 12.8-12.8V140.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v198.4c0 6.4 6.4 12.8 12.8 12.8zm96 0h22.4c6.4 0 12.8-6.4 12.8-12.8V204.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v134.4c0 6.4 6.4 12.8 12.8 12.8zM496 400H48V80c0-8.84-7.16-16-16-16H16C7.16 64 0 71.16 0 80v336c0 17.67 14.33 32 32 32h464c8.84 0 16-7.16 16-16v-16c0-8.84-7.16-16-16-16zm-387.2-48h22.4c6.4 0 12.8-6.4 12.8-12.8v-70.4c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v70.4c0 6.4 6.4 12.8 12.8 12.8z\" class=\"\"><\/path><\/svg><\/i> <img loading=\"lazy\" decoding=\"async\" width=\"16\" height=\"16\" alt=\"Loading\" src=\"https:\/\/www.sabulo.com\/sb\/wp-content\/plugins\/page-views-count\/ajax-loader-2x.gif\" border=0 \/><\/p>\n<div class=\"pvc_clear\"><\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false},"version":2}},"categories":[87,64,86,85],"tags":[],"class_list":["post-1777","post","type-post","status-publish","format-standard","hentry","category-android-app-development","category-esp32-development-board","category-heltec-oled","category-udp-protocol"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p6vhqE-sF","_links":{"self":[{"href":"https:\/\/www.sabulo.com\/sb\/wp-json\/wp\/v2\/posts\/1777","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.sabulo.com\/sb\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.sabulo.com\/sb\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.sabulo.com\/sb\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.sabulo.com\/sb\/wp-json\/wp\/v2\/comments?post=1777"}],"version-history":[{"count":10,"href":"https:\/\/www.sabulo.com\/sb\/wp-json\/wp\/v2\/posts\/1777\/revisions"}],"predecessor-version":[{"id":1824,"href":"https:\/\/www.sabulo.com\/sb\/wp-json\/wp\/v2\/posts\/1777\/revisions\/1824"}],"wp:attachment":[{"href":"https:\/\/www.sabulo.com\/sb\/wp-json\/wp\/v2\/media?parent=1777"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.sabulo.com\/sb\/wp-json\/wp\/v2\/categories?post=1777"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.sabulo.com\/sb\/wp-json\/wp\/v2\/tags?post=1777"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}