{"id":1718,"date":"2016-12-07T16:52:30","date_gmt":"2016-12-08T00:52:30","guid":{"rendered":"http:\/\/internetofhomethings.com\/homethings\/?p=1718"},"modified":"2016-12-07T16:52:30","modified_gmt":"2016-12-08T00:52:30","slug":"esp8266-as-a-coap-client","status":"publish","type":"post","link":"https:\/\/internetofhomethings.com\/homethings\/?p=1718","title":{"rendered":"ESP8266 as a CoAP Client"},"content":{"rendered":"<p><a href=\"http:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2016\/11\/coap1.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-1720\" src=\"http:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2016\/11\/coap1.jpg\" alt=\"coap1\" width=\"450\" height=\"450\" srcset=\"https:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2016\/11\/coap1.jpg 225w, https:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2016\/11\/coap1-150x150.jpg 150w\" sizes=\"auto, (max-width: 450px) 100vw, 450px\" \/><\/a><\/p>\n<p>Several examples can be found to configure the ESP8266 as a CoAP server. Last year I too had developed one.\u00a0<a href=\"http:\/\/wp.me\/p5NRQ8-jS\" target=\"_blank\">Here <\/a>is my working example.<\/p>\n<p>But what about using the device as a CoAP client? Using the ESP8266 to send requests to a CoAP server? With a two-ESP8266 module setup, this would provide the capability to set up a CoAP client\/server\u00a0architecture.<\/p>\n<p>While I was unable to find a working example, much to my surprise, it was not that difficult to develop a client from my working server. Here is how it was done&#8230;<\/p>\n<h2 style=\"text-align: center;\"><strong>Turning the tables<\/strong><\/h2>\n<p>After reviewing my ESP8266 CoAP server code, the seeds for a client were obvious. The server listens for CoAP request, acts on it, and sends a reply. To make a client, all that is necessary is to reverse the order.<\/p>\n<p>First, use the server&#8217;s reply code to send a request to a server. Then simply listen for a reply from the CoAP server using the &#8220;listen&#8221; code.<\/p>\n<h2 style=\"text-align: center;\"><strong>Communication Structure\u00a0<\/strong><\/h2>\n<p>This project uses\u00a0a standard http server to initiate requests to a CoAP server. With this structure, a standard web browser can be used to test the CoAP client functionality.<\/p>\n<p><a href=\"http:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2016\/11\/coap_client.jpg\"><br \/>\n<\/a><a href=\"http:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2016\/12\/coap_client.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-1748 size-full\" src=\"http:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2016\/12\/coap_client.jpg\" alt=\"coap_client\" width=\"843\" height=\"649\" srcset=\"https:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2016\/12\/coap_client.jpg 843w, https:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2016\/12\/coap_client-300x231.jpg 300w, https:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2016\/12\/coap_client-768x591.jpg 768w\" sizes=\"auto, (max-width: 843px) 100vw, 843px\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<h2 style=\"text-align: center;\"><strong>Separate\u00a0Requests and\u00a0Replies\u00a0<\/strong><\/h2>\n<p>Using http request to initiate a CoAP client request presents a slight complication. That is, I found that checking for a CoAP reply (UDP) from a request while the http (TCP) connection was open caused the ESP8266 to crash. The problem was that the TCP connection callback\u00a0function blocks the CoAP UDP reply packet. It was stuck waiting until the ESP8266 watchdog timed out, and then&#8230; Crash!<\/p>\n<p>One\u00a0solution is to use\u00a0an Asynchronous TCP library such as the one found <a href=\"https:\/\/github.com\/me-no-dev\/ESPAsyncTCP\" target=\"_blank\">here<\/a>. But that is beyond the scope of this simple ESP8266 CoAP client project. However, I do intend to explore that option in a future post on this subject.<\/p>\n<p>But for now, it was easier to resolve this problem by breaking down an http GET initiated CoAP communication \u00a0exchange into two parts. The first http GET sends a CoAP request to the target CoAP server. After the TCP connection is closed. the CoAP UDP reply is received and stored. A second http GET is then needed to retrieve the CoAP reply.<\/p>\n<h2 style=\"text-align: center;\">\u00a0<strong>Sending a CoAP Request\u00a0<\/strong><\/h2>\n<p>A CoAP request is comprised of a UDP packet per<a href=\"https:\/\/tools.ietf.org\/html\/rfc7252\" target=\"_blank\"> RFC7252<\/a>. This\u00a0example uses a <a href=\"http:\/\/wp.me\/p5NRQ8-jS\" target=\"_blank\">simple CoAP server<\/a> installed on a second ESP8266\u00a0that supports just 3 actions.<\/p>\n<ol>\n<li>Turn Led On\/Off<\/li>\n<li>Blink Led<\/li>\n<li>Get Sensor Values<\/li>\n<\/ol>\n<p>The CoAP UDP request packets are pre-defined in unique byte arrays:<\/p>\n<pre class=\"easycode; title:;lang:;\">uint8_t\u00a0packetbuf_LED_ON[]\u00a0\u00a0\u00a0\u00a0\u00a0=\u00a0{0x40,\u00a00x03,\u00a00x00,\u00a00x00,\u00a00xB5,\u00a00x6C,\u00a00x69,\u00a00x67,\u00a00x68,\u00a00x74,\u00a00xFF,\u00a00x31};\r\nuint8_t\u00a0packetbuf_LED_OFF[]\u00a0\u00a0\u00a0\u00a0=\u00a0{0x40,\u00a00x03,\u00a00x00,\u00a00x00,\u00a00xB5,\u00a00x6C,\u00a00x69,\u00a00x67,\u00a00x68,\u00a00x74,\u00a00xFF,\u00a00x30};\r\nuint8_t\u00a0packetbuf_LED_BLINK[]\u00a0\u00a0=\u00a0{0x40,\u00a00x03,\u00a00x00,\u00a00x00,\u00a00xBB,\u00a00x6C,\u00a00x69,\u00a00x67,\u00a00x68,\u00a00x74,\u00a00x5F,\u00a00x62,\u00a0\r\n                                  0x6C,\u00a00x69,\u00a00x6E,\u00a00x6B,\u00a00xFF,\u00a00x35};\r\nuint8_t\u00a0packetbuf_GETSENSORS[]\u00a0=\u00a0{0x40,\u00a00x03,\u00a00x00,\u00a00x00,\u00a00xB7,\u00a00x72,\u00a00x65,\u00a00x71,\u00a00x75,\u00a00x65,\u00a00x73,\u00a00x74,\u00a0\r\n                                  0xFF,\u00a00x2F,\u00a00x3F,\u00a00x72,\u00a00x65,\u00a00x71,\u00a00x75,\u00a00x65,\u00a00x73,\u00a00x74,\u00a00x3D,\u00a00x47,\u00a0\r\n                                  0x65,\u00a00x74,\u00a00x53,\u00a00x65,\u00a00x6E,\u00a00x73,\u00a00x6F,\u00a00x72,\u00a00x73};<\/pre>\n<p style=\"text-align: left;\">The first byte (0x40) identifies the CoAP version as 1.0. The &#8216;0&#8217; in the lower 4 bits indicate no tokens will follow the message header. The second byte (0x03) identifies the CoAP code as 0.03, indicating the PUT method used in the UDP request packet. Bytes 3 and 4 contain the messageID. This value starts at 0 upon ESP8266 startup and is incremented every time a message is sent.<\/p>\n<p style=\"text-align: left;\">The lower 4 bits identify the packet option length and is followed by the option value. Then, the byte following the option is the payload deliminator, and is set to oxFF.<\/p>\n<p style=\"text-align: center;\">[wptg_comparison_table id=&#8221;18&#8243;]<\/p>\n<p style=\"text-align: left;\">The packet payload, which follows the 0xFF deliminator, contains the request message. As shown in the table above, the parameter is set to 1 to turn the\u00a0CoAP server ESP8266 circuit LED on and 0 to turn the LED off.<\/p>\n<p style=\"text-align: left;\">And just as with other web server request, the CoAP requests are sent (udp_send) after an http GET is received.<\/p>\n<pre class=\"easycode; title:;lang:;\"> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/\u00a0Send\u00a0CoAP\u00a0Request\u00a0to\u00a0ESP8266\u00a0(192.168.0.141)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0else\u00a0if(os_strcmp(pURL_Param-&gt;pParVal[0],\u00a0\"CoAPLedOn\")==0)\u00a0{\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0coaplen\u00a0=\u00a0sizeof(packetbuf_LED_ON);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0incrMessageID(packetbuf_LED_ON);\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/Increment\u00a0Mesaage\u00a0ID\u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0udp_send(packetbuf_LED_ON,\u00a0coaplen);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0payld\u00a0=\u00a0\"http\u00a0GET\u00a0'CoAPGetReply'\u00a0required\u00a0to\u00a0get\u00a0CoAP\u00a0reply\";\u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/\u00a0Send\u00a0CoAP\u00a0Request\u00a0to\u00a0ESP8266\u00a0(192.168.0.141)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0else\u00a0if(os_strcmp(pURL_Param-&gt;pParVal[0],\u00a0\"CoAPLedOff\")==0)\u00a0{\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0coaplen\u00a0=\u00a0sizeof(packetbuf_LED_OFF);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0incrMessageID(packetbuf_LED_OFF);\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/Increment\u00a0Mesaage\u00a0ID\u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0udp_send(packetbuf_LED_OFF,\u00a0coaplen);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0payld\u00a0=\u00a0\"http\u00a0GET\u00a0'CoAPGetReply'\u00a0required\u00a0to\u00a0get\u00a0CoAP\u00a0reply\";\u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/\u00a0Send\u00a0CoAP\u00a0Request\u00a0to\u00a0ESP8266\u00a0(192.168.0.141)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0else\u00a0if(\u00a0(os_strcmp(pURL_Param-&gt;pParVal[0],\u00a0\"CoAPLedBlink\")==0)&amp;&amp;(os_strcmp(pURL_Param-&gt;pParam[1],\u00a0\"cnt\")==0)\u00a0)\u00a0{\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0coaplen\u00a0=\u00a0sizeof(packetbuf_LED_BLINK);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/Insert\u00a0Blink\u00a0Count\u00a0(1-9)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0*pURL_Param-&gt;pParVal[1]\u00a0=\u00a0(*pURL_Param-&gt;pParVal[1]\u00a0&lt;\u00a00x31)\u00a0?\u00a00x31\u00a0:\u00a0*pURL_Param-&gt;pParVal[1];\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0*pURL_Param-&gt;pParVal[1]\u00a0=\u00a0(*pURL_Param-&gt;pParVal[1]\u00a0&gt;\u00a00x39)\u00a0?\u00a00x39\u00a0:\u00a0*pURL_Param-&gt;pParVal[1];\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0packetbuf_LED_BLINK[coaplen-1]\u00a0=\u00a0*pURL_Param-&gt;pParVal[1];\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0incrMessageID(packetbuf_LED_BLINK);\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/Increment\u00a0Mesaage\u00a0ID\u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0udp_send(packetbuf_LED_BLINK,\u00a0coaplen);\u00a0\u00a0\u00a0\/\/Send\u00a0Packet\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0payld\u00a0=\u00a0\"http\u00a0GET\u00a0'CoAPGetReply'\u00a0required\u00a0to\u00a0get\u00a0CoAP\u00a0reply\";\u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/\u00a0Send\u00a0CoAP\u00a0Request\u00a0to\u00a0ESP8266\u00a0(192.168.0.141)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0else\u00a0if(os_strcmp(pURL_Param-&gt;pParVal[0],\u00a0\"CoAPGetSensors\")==0)\u00a0{\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0coaplen\u00a0=\u00a0sizeof(packetbuf_GETSENSORS);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0incrMessageID(packetbuf_GETSENSORS);\u00a0\u00a0\u00a0\u00a0\u00a0\/\/Increment\u00a0Mesaage\u00a0ID\u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0udp_send(packetbuf_GETSENSORS,\u00a0coaplen);\r\n                    payld = \"http GET 'CoAPGetReply' required to get CoAP reply\";\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/\u00a0Send\u00a0CoAP\u00a0Request\u00a0to\u00a0ESP8266\u00a0(192.168.0.141)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0else\u00a0if(os_strcmp(pURL_Param-&gt;pParVal[0],\u00a0\"CoAPGetReply\")==0)\u00a0{\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0payld\u00a0=\u00a0String(coap_reply_c);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}<\/pre>\n<h2 style=\"text-align: center;\"><\/h2>\n<h2 style=\"text-align: center;\"><strong>Receiving the CoAP Reply\u00a0<\/strong><\/h2>\n<p>Note in the above code that the CoAP reply is set (payld) after the UDP packet it sent to the CoAP server. But the reply simply states that you must send a &#8216;CoAPGetReply&#8217; request in order to get the CoAP reply. As noted previously, that is due to the blocking nature of the TCP callback.<\/p>\n<p>The actual reply is stored in the global character string &#8216;coap_reply_c&#8217;.To get the reply, simply send the second GET request:<\/p>\n<p>&lt;ESP_IP&gt;:&lt;ESP_PORT&gt;\/?request=CoAPGetReply<\/p>\n<h2 style=\"text-align: center;\"><strong>Example Transactions<\/strong><\/h2>\n<p>So here is the browser based requests you can use the test this CoAP server. This example assumes the ESP IP is 192.168.0.141 and the TCP port is set to 9706.<\/p>\n<p style=\"text-align: center;\">[wptg_comparison_table id=&#8221;19&#8243;]<\/p>\n<h2 style=\"text-align: center;\"><a href=\"https:\/\/github.com\/internetofhomethings\/ESP8266-CoAP-Client\" target=\"_blank\"><strong>This project&#8217;s\u00a0GitHub Repository\u00a0<\/strong><\/a><\/h2>\n<h2 style=\"text-align: center;\"><strong>In Closing\u00a0<\/strong><\/h2>\n<p>There you have it. A simple ESP8266 CoAP client structure to use in your custom application. But this is just a starting framework. There are obvious enhancements that can be made to this working example. Here are some of the things I would do next&#8230;<\/p>\n<ol>\n<li>Add web configurable options &#8211; <a href=\"http:\/\/wp.me\/p5NRQ8-ku\" target=\"_blank\">Example<\/a><\/li>\n<li>Revise to support\u00a0Async TCP<\/li>\n<li>Implementation of additional<a href=\"https:\/\/tools.ietf.org\/html\/rfc7252#section-10.1.2\" target=\"_blank\"> RFC7252<\/a> options<\/li>\n<\/ol>\n<p>Hope you find this information useful&#8230;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Several examples can be found to configure the ESP8266 as a CoAP server. Last year I too had developed one.\u00a0Here is my working example. But what about using the device &hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1,19,132],"tags":[147,146,149,148,12],"class_list":["post-1718","post","type-post","status-publish","format-standard","hentry","category-alltheposts","category-internet-of-things","category-web-server","tag-clientserver","tag-coap","tag-coap-client","tag-esp8266-coap-client","tag-iot"],"_links":{"self":[{"href":"https:\/\/internetofhomethings.com\/homethings\/index.php?rest_route=\/wp\/v2\/posts\/1718","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/internetofhomethings.com\/homethings\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/internetofhomethings.com\/homethings\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/internetofhomethings.com\/homethings\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/internetofhomethings.com\/homethings\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1718"}],"version-history":[{"count":26,"href":"https:\/\/internetofhomethings.com\/homethings\/index.php?rest_route=\/wp\/v2\/posts\/1718\/revisions"}],"predecessor-version":[{"id":1750,"href":"https:\/\/internetofhomethings.com\/homethings\/index.php?rest_route=\/wp\/v2\/posts\/1718\/revisions\/1750"}],"wp:attachment":[{"href":"https:\/\/internetofhomethings.com\/homethings\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1718"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/internetofhomethings.com\/homethings\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1718"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/internetofhomethings.com\/homethings\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1718"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}