{"id":1401,"date":"2016-07-26T14:46:45","date_gmt":"2016-07-26T21:46:45","guid":{"rendered":"http:\/\/internetofhomethings.com\/homethings\/?p=1401"},"modified":"2016-07-26T14:46:45","modified_gmt":"2016-07-26T21:46:45","slug":"mqtt-for-app-inventor-more-configurable-settings","status":"publish","type":"post","link":"https:\/\/internetofhomethings.com\/homethings\/?p=1401","title":{"rendered":"MQTT for App Inventor &#8211; More Configurable Settings"},"content":{"rendered":"<h2 style=\"text-align: center;\"><a href=\"http:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2016\/07\/configs.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1682\" src=\"http:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2016\/07\/configs.jpg\" alt=\"configs\" width=\"358\" height=\"124\" srcset=\"https:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2016\/07\/configs.jpg 358w, https:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2016\/07\/configs-300x104.jpg 300w\" sizes=\"auto, (max-width: 358px) 100vw, 358px\" \/><\/a><\/h2>\n<h2 style=\"text-align: center;\"><strong>More\u00a0MQTT Configurable Parameters via\u00a0<\/strong><strong>App Inventor <\/strong><\/h2>\n<p>My\u00a0<a href=\"http:\/\/wp.me\/p5NRQ8-lf\" target=\"_blank\">last post<\/a>\u00a0on this subject introduced a few configurable setting to an\u00a0MQTT App Inventor project. It was a no frills, bare bones version. But a few essential parameters were \u00a0left out. This article fills in the some of the gaps, including connection authentication, websocket port assignment, timeout, last will and testimonial, and the clientID. With this update, the following MQTT settings become\u00a0configurable:<\/p>\n<ul>\n<li>MQTT Broker domain name<\/li>\n<li>Request Topic<\/li>\n<li>Reply Topic<\/li>\n<li>User Name (Leave Blank if not used)<\/li>\n<li>Password (Leave Blank if not used)<\/li>\n<li>MQTT Websocket Port<\/li>\n<li>Client ID<\/li>\n<li>Keep Alive Timeout (seconds)<\/li>\n<li>Last Will Topic<\/li>\n<li>Last Will Message<\/li>\n<li>Last Will QoS<\/li>\n<\/ul>\n<p><strong>NOTE:<\/strong> If you want to skip the implementation details presented below and simply\u00a0use this project now, it is available on <a href=\"https:\/\/github.com\/internetofhomethings\/Configurable-Web-Server\/tree\/master\/AppInventor_CfgMQTT_rev1\" target=\"_blank\">GitHub here<\/a>.<\/p>\n<h2 style=\"text-align: center;\"><strong>A New Client Library<\/strong><\/h2>\n<p>My initial App Inventor MQTT project used the Mosquitto client library. While that was great for developing the &#8220;proof-of-concept&#8221;, demonstrating that you could indeed link\u00a0an App Inventor project to an MQTT broker, some serious shortcomings soon became\u00a0evident.<\/p>\n<p>When attempting to refine the project to support broker connections with authentication, I discovered that the Mosquitto library did not support this basic feature. So a new library was needed. Fortunately, an existing open-source client library is available with full support for password-enabled logins.<\/p>\n<p>The library is called <a href=\"https:\/\/projects.eclipse.org\/projects\/technology.paho\" target=\"_blank\">Eclipse Paho<\/a>. And just as with\u00a0my initial application, the API provides a JavaScript interface. This interface supports all the features identified above, configurable through App Inventor.<\/p>\n<h2 style=\"text-align: center;\"><strong>Expanding The Configurable Parameters<\/strong><\/h2>\n<p>Here is how the expanded App Inventor configuration screen looks. When user name\/password credentials are not used, the fields should remain blank. Just as before, the configuration settings are stored in an Android device file. Upon start-up, the system initializes with the values stored in that file (cfg.txt).<\/p>\n<p><a href=\"http:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2016\/07\/mqtt_cfg-1.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1679\" src=\"http:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2016\/07\/mqtt_cfg-1.jpg\" alt=\"mqtt_cfg\" width=\"923\" height=\"598\" srcset=\"https:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2016\/07\/mqtt_cfg-1.jpg 923w, https:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2016\/07\/mqtt_cfg-1-300x194.jpg 300w, https:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2016\/07\/mqtt_cfg-1-768x498.jpg 768w\" sizes=\"auto, (max-width: 923px) 100vw, 923px\" \/><\/a><\/p>\n<p>A last will message has been added to the set of App Inventor configurable parameters. As per the MQTT specification, the last will message is sent when the MQTT\u00a0connection is closing.<\/p>\n<h2 style=\"text-align: center;\"><strong>Test Case<\/strong><\/h2>\n<p>The HiveMQ broker\u00a0&#8220;broker.mqttdashboard.com&#8221; was\u00a0used to demonstrate the capabilities of this project. And the on-line client used is available at:\u00a0http:\/\/www.hivemq.com\/demos\/websocket-client\/<\/p>\n<p>A simple test: Open a browser to the MQTT client:\u00a0http:\/\/www.hivemq.com\/demos\/websocket-client\/<\/p>\n<p>Enter the Host broker as shown below and click &#8220;Connect&#8221;.<\/p>\n<p><a href=\"http:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2016\/07\/hiveMQ.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1683\" src=\"http:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2016\/07\/hiveMQ.jpg\" alt=\"hiveMQ\" width=\"979\" height=\"564\" srcset=\"https:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2016\/07\/hiveMQ.jpg 979w, https:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2016\/07\/hiveMQ-300x173.jpg 300w, https:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2016\/07\/hiveMQ-768x442.jpg 768w\" sizes=\"auto, (max-width: 979px) 100vw, 979px\" \/><\/a><\/p>\n<p>Subscribe to the App Inventor MQTT Request and Last Will topics:<\/p>\n<p>Request Topic: mqtt_request<\/p>\n<p>Last Will Topic: lwt<\/p>\n<p><a href=\"http:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2016\/07\/subscribe.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1684\" src=\"http:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2016\/07\/subscribe.jpg\" alt=\"subscribe\" width=\"323\" height=\"235\" srcset=\"https:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2016\/07\/subscribe.jpg 323w, https:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2016\/07\/subscribe-300x218.jpg 300w\" sizes=\"auto, (max-width: 323px) 100vw, 323px\" \/><\/a><\/p>\n<p>Open the updated MQTT App on your Android device. Click on the &#8220;Configure MQTT&#8221; icon.<\/p>\n<p><a href=\"http:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2016\/07\/new_cfg.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1686\" src=\"http:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2016\/07\/new_cfg.jpg\" alt=\"new_cfg\" width=\"480\" height=\"853\" srcset=\"https:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2016\/07\/new_cfg.jpg 480w, https:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2016\/07\/new_cfg-169x300.jpg 169w\" sizes=\"auto, (max-width: 480px) 100vw, 480px\" \/><\/a><\/p>\n<p>Edit or take\u00a0note of the last will topic and message. Close the App Inventor app and verify the HiveMQ client displays the last will message.<\/p>\n<p>Note: Use a broker that supports username\/password logins to verify that new configurable parameter pair. Refer to <a href=\"http:\/\/wp.me\/p5NRQ8-my\" target=\"_blank\">this post<\/a> if you would like to setup your own MQTT broker with login authentication enabled.<\/p>\n<h2 style=\"text-align: center;\"><strong>JavaScript\u00a0Updates<\/strong><\/h2>\n<p>The App Inventor WebViewString is used to communicate between the application and the Paho MQTT JavaScript library. Here are the highlights of the revised JavaScript interface.<\/p>\n<p><strong>Paho MQTT API\u00a0Fork<\/strong><\/p>\n<p>I started this project update\u00a0with paho-javascript version 1.0.2. After debugging the changes\u00a0using a web browser, the code was moved to the target Android device. Unfortunately, after much troubleshooting, an unsupported AppInventor &#8220;WebViewer&#8221; component feature was identified. \u00a0The \u00a0required feature for the Paho library is called &#8220;localStorage&#8221;.<\/p>\n<p>Fortunately, there is an alternative to localStorage. I have modified the Paho library to use Cookies instead of localStorage. With this change, the Paho library\/App Inventor communication has been verified to function properly.<\/p>\n<p>Three\u00a0sections of the library had to be modified:<\/p>\n<ol>\n<li>Verify localStorage is supported (Comment out this check)<\/li>\n<\/ol>\n<pre class=\"easycode; title:;lang:;\">\/\/\u00a0Check\u00a0dependencies\u00a0are\u00a0satisfied\u00a0in\u00a0this\u00a0browser.\r\nif\u00a0(!(\"WebSocket\"\u00a0in\u00a0global\u00a0&amp;&amp;\u00a0global[\"WebSocket\"]\u00a0!==\u00a0null))\u00a0{\r\n    throw\u00a0new\u00a0Error(format(ERROR.UNSUPPORTED,\u00a0[\"WebSocket\"]));\r\n}\r\n\/\/cookies\u00a0used\u00a0since\u00a0localstorage\u00a0not\u00a0supported\u00a0with\u00a0appinventor\r\n\/*\r\nif\u00a0(!(\"localStorage\"\u00a0in\u00a0global\u00a0&amp;&amp;\u00a0global[\"localStorage\"]\u00a0!==\u00a0null))\u00a0{\r\n    throw\u00a0new\u00a0Error(format(ERROR.UNSUPPORTED,\u00a0[\"localStorage\"]));\r\n}\r\n*\/<\/pre>\n<p>2. Replace localStorage with cookies<\/p>\n<pre class=\"easycode; title:;lang:;\">    \/\/localStorage.setItem(prefix+this._localKey+wireMessage.messageIdentifier,\u00a0JSON.stringify(storedMessage));\r\n    setCookie(prefix+this._localKey+wireMessage.messageIdentifier,\u00a0JSON.stringify(storedMessage),\u00a01);\r\n};\r\n\r\nClientImpl.prototype.restore\u00a0=\u00a0function(key)\u00a0{\r\n\/\/var\u00a0value\u00a0=\u00a0localStorage.getItem(key);\r\nvar\u00a0value\u00a0=\u00a0getCookie(key);<\/pre>\n<p>3. Add Get\/Set cookies functions<\/p>\n<pre class=\"easycode; title:;lang:;\"> function\u00a0setCookie(cname,\u00a0cvalue,\u00a0exdays)\u00a0{\r\n\u00a0\u00a0\u00a0\u00a0var\u00a0d\u00a0=\u00a0new\u00a0Date();\r\n\u00a0\u00a0\u00a0\u00a0d.setTime(d.getTime()\u00a0+\u00a0(exdays*24*60*60*1000));\r\n\u00a0\u00a0\u00a0\u00a0var\u00a0expires\u00a0=\u00a0\"expires=\"+d.toUTCString();\r\n\u00a0\u00a0\u00a0\u00a0document.cookie\u00a0=\u00a0cname\u00a0+\u00a0\"=\"\u00a0+\u00a0cvalue\u00a0+\u00a0\";\u00a0\"\u00a0+\u00a0expires;\r\n}\r\n\r\nfunction\u00a0getCookie(cname)\u00a0{\r\n\u00a0\u00a0\u00a0\u00a0var\u00a0name\u00a0=\u00a0cname\u00a0+\u00a0\"=\";\r\n\u00a0\u00a0\u00a0\u00a0var\u00a0ca\u00a0=\u00a0document.cookie.split(';');\r\n\u00a0\u00a0\u00a0\u00a0for(var\u00a0i\u00a0=\u00a00;\u00a0i\u00a0&lt;\u00a0ca.length;\u00a0i++)\u00a0{\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0var\u00a0c\u00a0=\u00a0ca[i];\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0while\u00a0(c.charAt(0)\u00a0==\u00a0'\u00a0')\u00a0{\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0c\u00a0=\u00a0c.substring(1);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if\u00a0(c.indexOf(name)\u00a0==\u00a00)\u00a0{\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return\u00a0c.substring(name.length,\u00a0c.length);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\r\n\u00a0\u00a0\u00a0\u00a0}\r\n\u00a0\u00a0\u00a0\u00a0return\u00a0\"\";\r\n}<\/pre>\n<p><strong>The AppInventor to PAHO MQTT API JavaScript<\/strong><\/p>\n<p>The MQTT broker is no longer automatically loaded after the webview page is loaded by the App Inventor application:<\/p>\n<pre class=\"easycode; title:;lang:;\">\/\/executes\u00a0once\u00a0after\u00a0window\u00a0is\u00a0loaded\u00a0---------------------------------------------&gt;\r\nfunction\u00a0windowloaded()\u00a0{\r\n    \/\/client.connect(connectOptions);\u00a0\u00a0\u00a0\u00a0\u00a0\/\/\u00a0Connect\u00a0to\u00a0MQTT\u00a0broker\r\n\u00a0\u00a0\u00a0\u00a0AppInventorServer();\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/\u00a0Start\u00a0polling\u00a0WebViewString\r\n}\r\nwindow.onload\u00a0=\u00a0windowloaded;\u00a0\u00a0\/\/\u00a0Launch\u00a0windowloaded()<\/pre>\n<p>The JavaScript must now receive a command to connect to the configured MQTT broker. The command received is called CFG, which loads the current connection settings stored in a file on the android device. The ensures the most current\u00a0configuration is used for the connection.<\/p>\n<p>There are 4 commands the JavaScript recognizes from the App Inventor App via the WebViewString.<\/p>\n<ol>\n<li>GET: Used to send an MQTT request message from the AppInventor App<\/li>\n<li>CFG: Update configurable parameters, disconnect and reconnect to MQTT broker<\/li>\n<li>CNX: Connect to MQTT broker<\/li>\n<li>KILLCNX: Disconnect from MQTT broker<\/li>\n<\/ol>\n<pre class=\"easycode; title:;lang:;\">\/\/GET:\u00a0Send\u00a0MQTT\u00a0message\u00a0-------------------------------------------------------------\r\n\/\/------------------------------------------------------------------------------------\r\nif(request.substring(0,\u00a04)==\"GET:\")\u00a0{\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/\u00a0Validate\u00a0request\r\n    window.AppInventor.setWebViewString(\"\");\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/\u00a0Reset\u00a0String\u00a0(process\u00a0once)\r\n    $(\"#request\").val(request.substring(4,\u00a0request.length));\u00a0\/\/set\u00a0request\u00a0html\u00a0textbox\r\n    SendMqttRequest();\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/\u00a0Send\u00a0Mqtt\u00a0Request\r\n}\r\n\/\/CFG: Update configurable files in Android Device File ------------------------------\r\n\/\/------------------------------------------------------------------------------------\r\nif(request.substring(0, 4) == \"CFG:\") { \/\/ Validate request\r\n    window.AppInventor.setWebViewString(\"\"); \/\/ Reset String (process once)\r\n\r\n    if(typeof(client) !== 'undefined') { \/\/ Disconnect if connected\r\n        client.disconnect();\r\n    }\r\n\r\n    var cfgpar = JSON.parse(request.substring(4, request.length));\r\n    txtopic = cfgpar.mqtt_txtopic;\r\n    rxtopic = cfgpar.mqtt_rxtopic;\r\n    mqtt_url = cfgpar.mqtt_broker;\r\n    mqtt_port = Number(cfgpar.mqtt_port);\r\n    mqtt_clientId = cfgpar.mqtt_clientId;\r\n    mqtt_keepalive = cfgpar.mqtt_keepalive;\r\n    mqtt_lastwilltopic = cfgpar.mqtt_lastWillTopic;\r\n    mqtt_lastwillmessage = cfgpar.mqtt_lastWillMessage;\r\n    mqtt_lastwillqos = cfgpar.mqtt_lastWillQoS;\r\n\r\n    connectOptions.userName = cfgpar.mqtt_un;\r\n    connectOptions.password = cfgpar.mqtt_pw;\r\n    connectOptions.keepAliveInterval= Number(mqtt_keepalive);\r\n\r\n    \/\/ Create a Last-Will-and-Testament\r\n    var lwt = new Paho.MQTT.Message(mqtt_lastwillmessage);\r\n    lwt.destinationName = mqtt_lastwilltopic;\r\n    lwt.qos = Number(mqtt_lastwillqos);\r\n    lwt.retained = false;\r\n    connectOptions.willMessage = lwt;\r\n\r\n    client = new Paho.MQTT.Client(mqtt_url, mqtt_port, mqtt_clientId);\r\n    client.onConnectionLost = onConnectionLost;\r\n    client.onMessageArrived = onMessageArrived;\r\n    client.connect(connectOptions); \/\/ Connect to MQTT broker\r\n}\r\n\r\n\/\/CNX: Connect to MQTT broker --------------------------------------------------------\r\n\/\/------------------------------------------------------------------------------------\r\nif(request.substring(0, 4)==\"CNX:\") {        \/\/ Validate request\r\n    window.AppInventor.setWebViewString(\"\"); \/\/ Reset String (process once)\r\n    if(typeof(client) == 'undefined') {\r\n        \/\/ Create MQTT client instance --------------------------------------------------&gt;\r\n        client = new Paho.MQTT.Client(mqtt_url, mqtt_port, mqtt_clientId);\r\n        \/\/ set callback handlers\r\n        client.onConnectionLost = onConnectionLost;\r\n        client.onMessageArrived = onMessageArrived;\r\n    }\r\n    client.connect(connectOptions); \/\/ Connect to MQTT broker\r\n}\r\n\r\n\/\/KILLCNX: Diconnect from MQTT broker ------------------------------------------------\r\n\/\/------------------------------------------------------------------------------------\r\nif(request.substring(0, 7)==\"KILLCNX\") {         \/\/ Validate request\r\n    window.AppInventor.setWebViewString(\"\");     \/\/ Reset String (process once)\r\n    conn_kill = \"Y\";\r\n    client.disconnect();\r\n}\r\nhAppInvSvr = setTimeout(AppInventorServer, 100); \/\/ run AppInventorServer() in 100 ms<\/pre>\n<p>The callbacks executed upon MQTT broker connection, disconnection, and receipt of subscribed message can easily be understood through a review of the JavaScript file (mqtt_appinventor_paho.html).<\/p>\n<h2 style=\"text-align: center;\"><strong>App Inventor Updates<\/strong><\/h2>\n<p>Changes to the App Inventor code simply expand the scope of the configurable parameters. Again, a review of the code should make these changes self-evident.<\/p>\n<p><a href=\"http:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2016\/07\/appinventor_update.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1692\" src=\"http:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2016\/07\/appinventor_update.jpg\" alt=\"appinventor_update\" width=\"698\" height=\"441\" srcset=\"https:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2016\/07\/appinventor_update.jpg 698w, https:\/\/internetofhomethings.com\/homethings\/wp-content\/uploads\/2016\/07\/appinventor_update-300x190.jpg 300w\" sizes=\"auto, (max-width: 698px) 100vw, 698px\" \/><\/a><\/p>\n<h2 style=\"text-align: center;\"><strong>Here is the code<\/strong><\/h2>\n<p>The AppInventor and JavaScript code is available on <a href=\"https:\/\/github.com\/internetofhomethings\/Configurable-Web-Server\/tree\/master\/AppInventor_CfgMQTT_rev1\" target=\"_blank\">GitHub here<\/a>. Installation instructions are included in the readme.md file.<\/p>\n<h2 style=\"text-align: center;\"><strong>In Conclusion<\/strong><\/h2>\n<p>There you have it. It is with great pleasure to present this update which supports username\/password MQTT connections using the AppInventor. I hope you find this information useful.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>More\u00a0MQTT Configurable Parameters via\u00a0App Inventor My\u00a0last post\u00a0on this subject introduced a few configurable setting to an\u00a0MQTT App Inventor project. It was a no frills, bare bones version. But a few &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,10,19,111],"tags":[109,106,140,141],"class_list":["post-1401","post","type-post","status-publish","format-standard","hentry","category-alltheposts","category-esp8266","category-internet-of-things","category-mqtt","tag-app-inventor-configurable-mqtt","tag-app-inventor-mqtt","tag-mqtt-with-authentication","tag-mqtt-with-last-will-message"],"_links":{"self":[{"href":"https:\/\/internetofhomethings.com\/homethings\/index.php?rest_route=\/wp\/v2\/posts\/1401","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=1401"}],"version-history":[{"count":20,"href":"https:\/\/internetofhomethings.com\/homethings\/index.php?rest_route=\/wp\/v2\/posts\/1401\/revisions"}],"predecessor-version":[{"id":1696,"href":"https:\/\/internetofhomethings.com\/homethings\/index.php?rest_route=\/wp\/v2\/posts\/1401\/revisions\/1696"}],"wp:attachment":[{"href":"https:\/\/internetofhomethings.com\/homethings\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1401"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/internetofhomethings.com\/homethings\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1401"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/internetofhomethings.com\/homethings\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1401"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}