{"id":746,"date":"2018-12-04T10:38:14","date_gmt":"2018-12-04T09:38:14","guid":{"rendered":"http:\/\/www.embedded-communication.com\/?p=746"},"modified":"2019-10-01T14:23:09","modified_gmt":"2019-10-01T12:23:09","slug":"using-emtas-canopen-stack-with-python","status":"publish","type":"post","link":"http:\/\/www.embedded-communication.com\/en\/misc\/using-emtas-canopen-stack-with-python\/","title":{"rendered":"Using emotas CANopen stack with Python"},"content":{"rendered":"<p>Implementation of CANopen devices with commercial CANopen Stacks, like the <a href=\"https:\/\/www.emotas.de\/en\/produkte\/canopen-slave-stack\">emotas CANopen Stack<\/a>, is easy in fast. At least in C and C++. But when it comes to other languages some kind of wrappers are needed, because most of the stacks come the programing language ANSI C. This short article is supposed to show a easy way how to get a ANSI C CANopen Stack into the Python environment.<\/p>\n<h2>Creating the C Library<\/h2>\n<p>The first thing we need is a C Library of the Stack, so on Windows one would create a .dll, in Linux a .so, and on Mac a .dylib. Especially under Windows you have to be careful which export version of our public API you are using. There are two way, using <em><strong>__stdcall<\/strong><\/em> or <em><strong>__declspec(dllexport)<\/strong><\/em>. Depending on that you have to choose the right way of creating callbacks for the stack. We will see an example later. In this article we are using a Windows dll, and we used <em><strong>__stdcall<\/strong><\/em> for the export of the API.<\/p>\n<h2>Using Python ctypes to call C functions<\/h2>\n<p>Since version 2.5 of Python there is a standard library included in Python, which enables us to use C functions in Python.<\/p>\n<p>First we have to import the package with:<\/p>\n<pre class=\"brush: python; title: ; notranslate\" title=\"\">\r\nfrom ctypes import *\r\n<\/pre>\n<p>After we imported the library we can now load the dll\/so\/dylib with:<\/p>\n<pre class=\"brush: python; title: ; notranslate\" title=\"\">\r\ncanopen = ctypes.WinDLL(&quot;canopen.dll&quot;)\r\n<\/pre>\n<p>or<\/p>\n<pre class=\"brush: python; title: ; notranslate\" title=\"\">\r\ncanopen = ctypes.CDLL(&quot;canopen.so&quot;)\r\n<\/pre>\n<p>The result of this call is that we created an object canon which has every public function of the dll as a member method. So now you can call functions of the stack like this:<\/p>\n<pre class=\"brush: python; title: ; notranslate\" title=\"\">\r\ncanopen.coLibdrvHardwareInit()\r\n<\/pre>\n<p>or<\/p>\n<pre class=\"brush: python; title: ; notranslate\" title=\"\">\r\ncanopen.coLibdrvCanInit(250)\r\n<\/pre>\n<p>So for normal C functions it is pretty straight forward with using the ctyes library of python.<\/p>\n<h2>Using Python ctyes for C callback functions<\/h2>\n<p>The emtas CANopen stack comes with the opportunity to register C callback function in form of function pointer for several events. In case one of these events occurs the corresponding application callback function is called. Since we are now in the Python environment we have to enable the C library to call Python functions. But there is a pretty easy and straight-forward solution in ctypes, too.<\/p>\n<p>As an example how to use callbacks lets assume the following: The CANopen Stack uses for the implementation of a CANopen LED a with the following C layout:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\ntypedef void (* CO_EVENT_LED_T)(BOOL_T);\r\n<\/pre>\n<p>So a function which takes one parameter of type BOOL, and it returns void. So in Python first we create a corresponding function type.<\/p>\n<pre class=\"brush: python; title: ; notranslate\" title=\"\">\r\nCO_EVENT_LED_T = WINFUNCTYPE(None, c_bool)\r\n<\/pre>\n<p>We use WINFUNCTYPE instead of CFUNCTYPE because of the type of export we choose for the C-DLL.<\/p>\n<p>No we can create a callback-object with a real Python function:<\/p>\n<pre class=\"brush: python; title: ; notranslate\" title=\"\">\r\nledCallback = CO_EVENT_LED_T(ledGreenInd)\r\n<\/pre>\n<p>Where ledGreenInd is the name of the real Python function.<\/p>\n<p>After we created the callback, we can actually pass it to the metas CANopen Stack with calling the Register function of the stack.<\/p>\n<pre class=\"brush: python; title: ; notranslate\" title=\"\">\r\ncanopen.coLibEventRegister_LED_GREEN(ledCallback)\r\n<\/pre>\n<p>From this point on, every time the stack wants to turn the CANopen LED on or off, it will call the Python Application function ledGreenInd with a bool parameter.<\/p>\n<h3>Important notice<\/h3>\n<p>Make sure that your C library is compiled in the same format (32\/64 bit) as your Python interpreter.<\/p>\n<h2>More complex example<\/h2>\n<p>In the following there is a more complex example of a slave example with the emtas CANopen stack in Python:<\/p>\n<pre class=\"brush: python; title: ; notranslate\" title=\"\">\r\nfrom ctypes import *\r\nimport ctypes\r\n\r\ncanopen = ctypes.WinDLL('canopen.dll')\r\n\r\n###########################\r\n### this is the main function\r\n###########################\r\ndef main():\r\n\r\n\tcanopen.coLibdrvHardwareInit()\r\n\r\n\tif canopen.coLibdrvCanInit(250) != 0:\r\n\t\texit(1)\r\n\r\n\tif canopen.coLibdrvTimerSetup(1000) != 0:\r\n\t\texit(2)\r\n\r\n\tCO_EVENT_STORE_T = WINFUNCTYPE(c_int, c_ubyte)\r\n\tcallback1 = CO_EVENT_STORE_T(loadInd)\r\n\tretVal = canopen.coLibCanOpenStackInit(callback1)\r\n\tif retVal != 0:\r\n\t\texit(3)\r\n\r\n\tCO_EVENT_NMT_T = WINFUNCTYPE(c_int, c_bool, c_int)\r\n\tcallback2 = CO_EVENT_NMT_T(nmtInd)\r\n\tif canopen.coLibEventRegister_NMT(callback2) != 0:\r\n\t\texit(3)\r\n\r\n\tCO_EVENT_ERRCTRL_T = WINFUNCTYPE(None, c_ubyte, c_int, c_int)\r\n\tcallback3 = CO_EVENT_ERRCTRL_T(hbState)\r\n\tif canopen.coLibEventRegister_ERRCTRL(callback3) != 0:\r\n\t\texit(4)\r\n\r\n\tCO_EVENT_SDO_SERVER_T = WINFUNCTYPE(c_int, c_bool, c_ubyte, c_ushort, c_ubyte)\r\n\tcallback4 = CO_EVENT_SDO_SERVER_T(sdoServerReadInd)\r\n\tif canopen.coLibEventRegister_SDO_SERVER_READ(callback4) != 0:\r\n\t\texit(5)\r\n\r\n\r\n\tCO_EVENT_SDO_SERVER_T = WINFUNCTYPE(c_int, c_bool, c_ubyte, c_ushort, c_ubyte)\r\n\tcallback6 = CO_EVENT_SDO_SERVER_T(sdoServerWriteInd)\r\n\tif canopen.coLibEventRegister_SDO_SERVER_WRITE(callback6) != 0:\r\n\t\texit(7)\r\n\r\n\tCO_EVENT_PDO_T = WINFUNCTYPE(None, c_ushort)\r\n\tcallback7 = CO_EVENT_PDO_T(pdoInd)\r\n\tif canopen.coLibEventRegister_PDO(callback7) != 0:\r\n\t\texit(8)\r\n\r\n\tCO_EVENT_PDO_T = WINFUNCTYPE(None, c_ushort)\r\n\tcallback8 = CO_EVENT_PDO_T(pdoRecEvent)\r\n\tif canopen.coLibEventRegister_PDO_REC_EVENT(callback8) != 0:\r\n\t\texit(9)\r\n\r\n\tCO_EVENT_CAN_STATE_T = WINFUNCTYPE(None, c_int)\r\n\tcallback11 = CO_EVENT_CAN_STATE_T(canInd)\r\n\tif canopen.coLibEventRegister_CAN_STATE(callback11) != 0:\r\n\t\texit(12)\r\n\r\n\tCO_EVENT_COMM_T = WINFUNCTYPE(None, c_int)\r\n\tcallback12 = CO_EVENT_COMM_T(commInd)\r\n\tif canopen.coLibEventRegister_COMM_EVENT(callback12) != 0:\r\n\t\texit(13)\r\n\r\n\tif canopen.coLibdrvCanEnable() != 0:\r\n\t\texit(14)\r\n\r\n\twhile True:\r\n\t\tcanopen.coLibCommTask()\r\n\r\n\treturn\r\n\r\n\r\ndef loadInd(sub_index):\r\n\tprint &quot;loadInd:&quot;, sub_index\r\n\treturn 0\r\n\r\n\r\ndef nmtInd(execute, newState):\r\n\tprint &quot;nmtInd: New Nmt state&quot;, newState,&quot;- execute&quot;, execute\r\n\treturn 0\r\n\r\n\r\ndef pdoInd(pdoNr):\r\n\tprint &quot;pdoInd: pdo&quot;, pdoNr, &quot;received&quot;\r\n\r\n\r\ndef pdoRecEvent(pdoNr):\r\n\tprint &quot;pdoRecEvent: pdo&quot;, pdoNr, &quot;time out&quot;\r\n\r\n\r\ndef hbState(nodeId,state,nmtState):\r\n\tprint &quot;hbInd: HB Event&quot;, state, &quot;node&quot;, nodeId, &quot;nmtState:&quot;, nmtState\r\n\r\n\r\ndef sdoServerReadInd(execute,sdoNr,index,subIndex):\r\n\tprint &quot;sdo server read ind: exec:&quot;, execute, &quot;sdoNr&quot;,  sdoNr, &quot;index&quot;, index,&quot;:&quot;, subIndex\r\n\t#return 10\r\n\treturn 0\r\n\r\n\r\n\r\n\t\r\ndef sdoServerWriteInd(execute,sdoNr,index,subIndex):\r\n\tprint &quot;sdo server write ind: exec:&quot;, execute, &quot;sdoNr&quot;,  sdoNr, &quot;index&quot;, index,&quot;:&quot;, subIndex\r\n\t#return 10\r\n\treturn 0\r\n\r\n\r\ndef canInd(canState):\r\n\tprint &quot;CAN STATE:&quot;, canState\r\n\treturn\r\n\r\n\r\ndef commInd(commEvent):\r\n\tprint &quot;COMM STATE:&quot;, commEvent\r\n\treturn\r\n\r\n\r\ndef ledGreenInd(on):\r\n\tprint &quot;GREEN:&quot;, on\r\n\r\n\r\ndef ledRedInd(on):\r\n\tprint &quot;RED:&quot;, on\r\n\r\n\r\nif __name__ == '__main__':\r\n\tmain()\r\n\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>","protected":false},"excerpt":{"rendered":"<p>Implementation of CANopen devices with commercial CANopen Stacks, like the emotas CANopen Stack, is easy in fast. At least in C and C++. But when it comes to other languages some kind of wrappers are needed, because most of the stacks come the programing language ANSI C. This short article is supposed to show a &hellip; <a href=\"http:\/\/www.embedded-communication.com\/en\/misc\/using-emtas-canopen-stack-with-python\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Using emotas CANopen stack with Python&#8221;<\/span><\/a><\/p>\n","protected":false},"author":4,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[36],"tags":[18,44],"class_list":["post-746","post","type-post","status-publish","format-standard","hentry","category-misc","tag-canopen","tag-python"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v24.0 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Using emotas CANopen stack with Python - embedded communication<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"http:\/\/www.embedded-communication.com\/en\/misc\/using-emtas-canopen-stack-with-python\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Using emotas CANopen stack with Python - embedded communication\" \/>\n<meta property=\"og:description\" content=\"Implementation of CANopen devices with commercial CANopen Stacks, like the emotas CANopen Stack, is easy in fast. At least in C and C++. But when it comes to other languages some kind of wrappers are needed, because most of the stacks come the programing language ANSI C. This short article is supposed to show a &hellip; Continue reading &quot;Using emotas CANopen stack with Python&quot;\" \/>\n<meta property=\"og:url\" content=\"http:\/\/www.embedded-communication.com\/en\/misc\/using-emtas-canopen-stack-with-python\/\" \/>\n<meta property=\"og:site_name\" content=\"embedded communication\" \/>\n<meta property=\"article:published_time\" content=\"2018-12-04T09:38:14+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2019-10-01T12:23:09+00:00\" \/>\n<meta name=\"author\" content=\"Alexander Philipp\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@EmbeddedComm\" \/>\n<meta name=\"twitter:site\" content=\"@EmbeddedComm\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Alexander Philipp\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"5 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"http:\/\/www.embedded-communication.com\/en\/misc\/using-emtas-canopen-stack-with-python\/#article\",\"isPartOf\":{\"@id\":\"http:\/\/www.embedded-communication.com\/en\/misc\/using-emtas-canopen-stack-with-python\/\"},\"author\":{\"name\":\"Alexander Philipp\",\"@id\":\"http:\/\/www.embedded-communication.com\/#\/schema\/person\/8df820296d4e943c0370b066161607ef\"},\"headline\":\"Using emotas CANopen stack with Python\",\"datePublished\":\"2018-12-04T09:38:14+00:00\",\"dateModified\":\"2019-10-01T12:23:09+00:00\",\"mainEntityOfPage\":{\"@id\":\"http:\/\/www.embedded-communication.com\/en\/misc\/using-emtas-canopen-stack-with-python\/\"},\"wordCount\":1052,\"publisher\":{\"@id\":\"http:\/\/www.embedded-communication.com\/#organization\"},\"keywords\":[\"CANopen\",\"Python\"],\"articleSection\":[\"Misc\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"http:\/\/www.embedded-communication.com\/en\/misc\/using-emtas-canopen-stack-with-python\/\",\"url\":\"http:\/\/www.embedded-communication.com\/en\/misc\/using-emtas-canopen-stack-with-python\/\",\"name\":\"Using emotas CANopen stack with Python - embedded communication\",\"isPartOf\":{\"@id\":\"http:\/\/www.embedded-communication.com\/#website\"},\"datePublished\":\"2018-12-04T09:38:14+00:00\",\"dateModified\":\"2019-10-01T12:23:09+00:00\",\"breadcrumb\":{\"@id\":\"http:\/\/www.embedded-communication.com\/en\/misc\/using-emtas-canopen-stack-with-python\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"http:\/\/www.embedded-communication.com\/en\/misc\/using-emtas-canopen-stack-with-python\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"http:\/\/www.embedded-communication.com\/en\/misc\/using-emtas-canopen-stack-with-python\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Startseite\",\"item\":\"http:\/\/www.embedded-communication.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Using emotas CANopen stack with Python\"}]},{\"@type\":\"WebSite\",\"@id\":\"http:\/\/www.embedded-communication.com\/#website\",\"url\":\"http:\/\/www.embedded-communication.com\/\",\"name\":\"embedded communication\",\"description\":\"A blog about embedded communcation protocols.\",\"publisher\":{\"@id\":\"http:\/\/www.embedded-communication.com\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"http:\/\/www.embedded-communication.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"http:\/\/www.embedded-communication.com\/#organization\",\"name\":\"embedded communication\",\"url\":\"http:\/\/www.embedded-communication.com\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"http:\/\/www.embedded-communication.com\/#\/schema\/logo\/image\/\",\"url\":\"http:\/\/www.embedded-communication.com\/wp-content\/uploads\/2016\/08\/embedded-communication.png\",\"contentUrl\":\"http:\/\/www.embedded-communication.com\/wp-content\/uploads\/2016\/08\/embedded-communication.png\",\"width\":240,\"height\":240,\"caption\":\"embedded communication\"},\"image\":{\"@id\":\"http:\/\/www.embedded-communication.com\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/x.com\/EmbeddedComm\"]},{\"@type\":\"Person\",\"@id\":\"http:\/\/www.embedded-communication.com\/#\/schema\/person\/8df820296d4e943c0370b066161607ef\",\"name\":\"Alexander Philipp\",\"sameAs\":[\"http:\/\/www.emtas.de\/team\/4136\"],\"url\":\"http:\/\/www.embedded-communication.com\/en\/author\/phi\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Using emotas CANopen stack with Python - embedded communication","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"http:\/\/www.embedded-communication.com\/en\/misc\/using-emtas-canopen-stack-with-python\/","og_locale":"en_US","og_type":"article","og_title":"Using emotas CANopen stack with Python - embedded communication","og_description":"Implementation of CANopen devices with commercial CANopen Stacks, like the emotas CANopen Stack, is easy in fast. At least in C and C++. But when it comes to other languages some kind of wrappers are needed, because most of the stacks come the programing language ANSI C. This short article is supposed to show a &hellip; Continue reading \"Using emotas CANopen stack with Python\"","og_url":"http:\/\/www.embedded-communication.com\/en\/misc\/using-emtas-canopen-stack-with-python\/","og_site_name":"embedded communication","article_published_time":"2018-12-04T09:38:14+00:00","article_modified_time":"2019-10-01T12:23:09+00:00","author":"Alexander Philipp","twitter_card":"summary_large_image","twitter_creator":"@EmbeddedComm","twitter_site":"@EmbeddedComm","twitter_misc":{"Written by":"Alexander Philipp","Est. reading time":"5 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"http:\/\/www.embedded-communication.com\/en\/misc\/using-emtas-canopen-stack-with-python\/#article","isPartOf":{"@id":"http:\/\/www.embedded-communication.com\/en\/misc\/using-emtas-canopen-stack-with-python\/"},"author":{"name":"Alexander Philipp","@id":"http:\/\/www.embedded-communication.com\/#\/schema\/person\/8df820296d4e943c0370b066161607ef"},"headline":"Using emotas CANopen stack with Python","datePublished":"2018-12-04T09:38:14+00:00","dateModified":"2019-10-01T12:23:09+00:00","mainEntityOfPage":{"@id":"http:\/\/www.embedded-communication.com\/en\/misc\/using-emtas-canopen-stack-with-python\/"},"wordCount":1052,"publisher":{"@id":"http:\/\/www.embedded-communication.com\/#organization"},"keywords":["CANopen","Python"],"articleSection":["Misc"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"http:\/\/www.embedded-communication.com\/en\/misc\/using-emtas-canopen-stack-with-python\/","url":"http:\/\/www.embedded-communication.com\/en\/misc\/using-emtas-canopen-stack-with-python\/","name":"Using emotas CANopen stack with Python - embedded communication","isPartOf":{"@id":"http:\/\/www.embedded-communication.com\/#website"},"datePublished":"2018-12-04T09:38:14+00:00","dateModified":"2019-10-01T12:23:09+00:00","breadcrumb":{"@id":"http:\/\/www.embedded-communication.com\/en\/misc\/using-emtas-canopen-stack-with-python\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["http:\/\/www.embedded-communication.com\/en\/misc\/using-emtas-canopen-stack-with-python\/"]}]},{"@type":"BreadcrumbList","@id":"http:\/\/www.embedded-communication.com\/en\/misc\/using-emtas-canopen-stack-with-python\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Startseite","item":"http:\/\/www.embedded-communication.com\/"},{"@type":"ListItem","position":2,"name":"Using emotas CANopen stack with Python"}]},{"@type":"WebSite","@id":"http:\/\/www.embedded-communication.com\/#website","url":"http:\/\/www.embedded-communication.com\/","name":"embedded communication","description":"A blog about embedded communcation protocols.","publisher":{"@id":"http:\/\/www.embedded-communication.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"http:\/\/www.embedded-communication.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"http:\/\/www.embedded-communication.com\/#organization","name":"embedded communication","url":"http:\/\/www.embedded-communication.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"http:\/\/www.embedded-communication.com\/#\/schema\/logo\/image\/","url":"http:\/\/www.embedded-communication.com\/wp-content\/uploads\/2016\/08\/embedded-communication.png","contentUrl":"http:\/\/www.embedded-communication.com\/wp-content\/uploads\/2016\/08\/embedded-communication.png","width":240,"height":240,"caption":"embedded communication"},"image":{"@id":"http:\/\/www.embedded-communication.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/x.com\/EmbeddedComm"]},{"@type":"Person","@id":"http:\/\/www.embedded-communication.com\/#\/schema\/person\/8df820296d4e943c0370b066161607ef","name":"Alexander Philipp","sameAs":["http:\/\/www.emtas.de\/team\/4136"],"url":"http:\/\/www.embedded-communication.com\/en\/author\/phi\/"}]}},"_links":{"self":[{"href":"http:\/\/www.embedded-communication.com\/en\/wp-json\/wp\/v2\/posts\/746","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.embedded-communication.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.embedded-communication.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.embedded-communication.com\/en\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"http:\/\/www.embedded-communication.com\/en\/wp-json\/wp\/v2\/comments?post=746"}],"version-history":[{"count":22,"href":"http:\/\/www.embedded-communication.com\/en\/wp-json\/wp\/v2\/posts\/746\/revisions"}],"predecessor-version":[{"id":833,"href":"http:\/\/www.embedded-communication.com\/en\/wp-json\/wp\/v2\/posts\/746\/revisions\/833"}],"wp:attachment":[{"href":"http:\/\/www.embedded-communication.com\/en\/wp-json\/wp\/v2\/media?parent=746"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.embedded-communication.com\/en\/wp-json\/wp\/v2\/categories?post=746"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.embedded-communication.com\/en\/wp-json\/wp\/v2\/tags?post=746"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}