{"id":5038,"date":"2019-09-15T19:09:11","date_gmt":"2019-09-15T18:09:11","guid":{"rendered":"https:\/\/www.purplemeanie.co.uk\/?p=5038"},"modified":"2025-01-31T13:08:37","modified_gmt":"2025-01-31T13:08:37","slug":"ecu-diagnostics-part-10-decoding-ec2-files","status":"publish","type":"post","link":"https:\/\/purplemeanie.co.uk\/index.php\/2019\/09\/15\/ecu-diagnostics-part-10-decoding-ec2-files\/","title":{"rendered":"ECU Diagnostics &#8211; part 10 : Decoding EC2 Files"},"content":{"rendered":"\n<p>Now we need to start proving some of our theories about how Easimap is actually talking to the ECU. And it seemed to me that if I was going to prove anything then I&#8217;d need to pass a lot of data through any theory I came up with, and that meant writing a program &#8211; since bit bashing (doing the decoding by hand) hundreds of packets of CAN bus data was probably going to take as long to decode by hand as it would to write a program to do it. Having a program would also mean I could push lots of examples through my code to check out my theories, but also tweak my theories and quickly run my code again to check them.<\/p>\n\n\n\n<p>And if I was going to write a program then it was going to need to translate the binary data on the CAN bus into something human readable. Of course that&#8217;s what Easimap uses the EC2 files for and I wanted to use that same information in any programs I wrote.<\/p>\n\n\n\n<p>The EC2 files are plain text files using a similar, but not quite the same, layout as legacy Windows ini files. There a lots of programs that now use this file format and it seems MBE\/SBD have come up with their own variation &#8211; at least I&#8217;ve not seen anything quite like it before.<\/p>\n\n\n\n<p>It uses the regular square brackets &#8220;[ ]&#8221; to create sections in the file, but it then nests these sections to create hierarchies. And it means that standard libraries to read in an EC2 file won&#8217;t work. Time to write some code then&#8230;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">EC2 File Sections<\/h3>\n\n\n\n<p>The 9A4 EC2 file has the following hierarchical, top-level sections, each contained in the EC2 file and having square brackets around them:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>HISTORY<\/li><li>PROPERTIES<\/li><li>PARAMETER PROTOTYPES<\/li><li>NUMERIC SCALES<\/li><li>STRING SCALES<\/li><li>PARAMETER DEFINITIONS<\/li><li>COLLECTIONS<\/li><li>ALARMS<\/li><li>SPECIAL FUNCTIONS<\/li><li>MAPPING VECTORS<\/li><li>MAPPING CONTROLS<\/li><li>SETUP PROTOTYPES<\/li><li>SETUP DEFINITIONS<\/li><li>MAP PROGRAMS<\/li><li>VARIANTS<\/li><li>SPECIAL INTERFACE PROTOTYPES<\/li><li>MATRICES<\/li><\/ul>\n\n\n\n<p>So, in the EC2 file the History section has a line with [ HISTORY ] in it.<\/p>\n\n\n\n<p>There&#8217;s clearly a lot of those sections that will be interesting to look into at some point. But I had a very focused desire to get the raw sensor diagnostic data out of the car and that meant I only needed to look at three sections for the moment.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Parameter Definitions<\/h3>\n\n\n\n<p>After a bunch of trial and error it seemed I needed to use the Parameter Definitions to get a list of all the data variables that the car could divulge.<\/p>\n\n\n\n<p>So for Engine RPM the corresponding Parameter Definition is:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">[RT_ENGINESPEED]\nNumber of Dimensions = 0\nPage = F8\nAddress = 237C\nBytes per Cell = 2\n0 = SCALE_ENGINESPEED<\/pre>\n\n\n\n<p>That allowed me to figure out what the request was that I needed to make to the ECU in order for the ECU to respond with Enging RPM. See the <a href=\"https:\/\/www.purplemeanie.co.uk\/index.php\/2019\/09\/15\/ecu-diagnostics-part-9-the-easimap-protocol-theory\/\">previous post<\/a> for a breakdown of that.<\/p>\n\n\n\n<p>It also told me that I was going to get two bytes of data back from the ECU (Bytes per Cell = 2).<\/p>\n\n\n\n<p>But 2 bytes of data can range from 0 to 65535 (assuming its a positive integer). And I wasn&#8217;t sure how to interpret the 2 bytes. Other data variables, like battery voltage, were going to be floating point numbers and while Engine RPM could be a 2 byte integer with no scaling or offset, that wasn&#8217;t going to be the case for most of the other data coming from the car.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Numeric Scales<\/h3>\n\n\n\n<p>That&#8217;s where the Numeric Scales top level section comes in&#8230;<\/p>\n\n\n\n<p>It turns out that the line:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">0 = SCALE_ENGINESPEED<\/pre>\n\n\n\n<p>refers to a SCALE_ENGINSPEED section in the Numeric Scales section of the EC2 file. The &#8220;0 = &#8221; bit refers to the fact that this is the zeroth dimension for the variable, something that becomes important for 1D, 2D and 3D maps where there are more scales defined for each of the axies on the map. The definition of SCALE_ENGINESPEED&nbsp;looks like this:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">[SCALE_ENGINESPEED]\nUnits = RPM\nScale Minimum = 0.000000\nScale Maximum = 65535.000000\nDisplay Minimum = 0.000000\nDisplay Maximum = 12000.000000\nDisplay Interval = 1000.000000<\/pre>\n\n\n\n<p>I suspect that&#8217;s fairly obvious what&#8217;s going on here, but the idea is that these Numeric Scales set the limits for the data coming back from the car, along with any scale factor that needs to be applied and any offset.<\/p>\n\n\n\n<p>For instance, the temperate variables have a scale (allowing them to be floating point numbers when the result is divided by the scale) and offsets (meaning that the data coming from the car needs to be offset by a particular value, allowing the number to also be negative &#8211; as might happen with air temperature on a cold day).<\/p>\n\n\n\n<p>You can also see that the Numeric Scale also sets the characters we can use for the Units, RPM in this case.<\/p>\n\n\n\n<p>Finally, I wanted to be able to see the data coming from the car in a human readable form. And while RT_ENGINESPEED is reasonably simple to understand, there are other variables that are much more obtuse, like RT_TPSFUEL+TRIMBANK1.&nbsp;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Parameter Prototypes<\/h3>\n\n\n\n<p>That&#8217;s where the Parameter Prototype section comes in with English definitions of what each variable is. For instance, RT_ENGINESPEED has this parameter prototype:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">RT_ENGINESPEED, \n  Engine Speed, \n  EngSpeed, \n  Engine Speed in rpm as measured by the crankshaft sensor. This is the primary input for the fuel and ignition maps<\/pre>\n\n\n\n<p>I spread that definition across a few lines, it&#8217;s on a single line in the EC2 file.<\/p>\n\n\n\n<p>One thing to note about these Parameter Prototypes is that at the end of the line in the EC2 file, you can get the word &#8220;DISABLED&#8221;. I ignored this at first but soon came to realise that it really did mean &#8220;disabled&#8221;. If I didn&#8217;t take account of it in the code I wrote, then I found there were variables defined more than once. Only one of the definitions was not disabled, so by ignoring the disabled ones I was able to get a clean list of valid variables.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">ec2parse.py<\/h3>\n\n\n\n<p>Now I knew the layout of the EC2 file, I could write some code. My weapon of choice here is Python. I&#8217;m reasonably new to Python but there&#8217;s a huge library base now behind Python and I can code with it on Linux, Mac and PC reasonably easily.&nbsp;<\/p>\n\n\n\n<p>The code for ec2parse.py can be found <a href=\"https:\/\/github.com\/Purplemeanie\/Caterham-OBD\/blob\/master\/tools\/ec2parse.py\">here<\/a>. The code is far from pretty&#8230; but it does a job. I may go and tidy it up when I get a chance (but I think everyone says that and I always advocate writing neat code in the first place so you don&#8217;t have to go back to it later &#8211; do as I say, not a I do!).<\/p>\n\n\n\n<p>This Python code will take an EC2 file and create an output file that can be used later, i.e. in the mbepcap2txt.py example below. For the moment I&#8217;ve been using the JSON output that I created which creates a formatted file that another Python file can read (use) instead of it having to decode the EC2 file every time.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">mbepcap2txt.py<\/h3>\n\n\n\n<p>Once I&#8217;d written this parsing code for the EC2 files I also the wrote a test app to take a CAN bus Wireshark capture file (.pcap or .pcapng) and turn it into something human readable &#8211; remember this is an onion with protocol layers&#8230; CAN bus being turned into a SocketCAN format, decoded as CAN then as ISOTP &#8211; phew!.<\/p>\n\n\n\n<p>This allowed me to take many hundreds of messages sent between Easimap and the ECU and verify that I had all my theories validated before I actually used any of this software I&#8217;d written to send any messages to the car&#8230;. I didn&#8217;t want to have to fork out for a new ECU, or even worse a new engine because I&#8217;d sent some random message to the ECU.<\/p>\n\n\n\n<p>And it all worked&#8230; here&#8217;s some output in something more human readable that the CAN bus messages:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">REQUEST: 0100000000f83031363744454c4d4e4f50515a5b5c5d646a6b7c7d9e9fa0a1d8d9dadb\nRESPONSE: 814e39094a9c52b886e8844e39a80d70a000b04f00005695800900800080\nRT_THROTTLEANGLE1(RAW)=1.1192 V ( Throttle Angle 1 (Raw) )\nRT_AIRTEMP1(LIM)=16.273 ( Air Temp )\nRT_COOLANTTEMP1(LIM)=21.632 ( Coolant Temp )\nRT_COOLANTFUELFACTOR=110.5 ( Coolant Fuel Factor )\nRT_AIRTEMPFUELFACTOR=3.8346 ( Air Temp Fuel Factor )\nRT_THROTTLEANGLEINCREASING=1.1192 V ( Throttle Angle Increasing )\nRT_TPSFUEL+TRIMBANK1=5.6013 ms ( TPS Fuel + Trim )\nRT_TPSVSSPEEDIGN+TRIM1=4.7938 ( TPS vs Speed Ign + Trim )\nRT_THROTTLESITE1=0.0 Site ( Throttle Site 1 )\nRT_BAROSCALEDLIM=1.04 Bar ( Baro Pressure ) \nRT_ENGINESPEED=0.0 RPM ( Engine Speed ) \nRT_BATTERYVOLTAGE(LIM)=11.667 V ( Battery Voltage )\nRT_BATTERYVOLTAGECOMP=0.48725 ms ( Battery Voltage Comp )\nRT_MAPPINGPOT1LIM=0.0015259 ( Mapping Pot 1 )\nRT_MAPPINGPOT2LIM=0.0015259 ( Mapping Pot 2 )\n#[28]# ISOTP REQUEST :0100000000f9babbbcbd\n#[29]# ISOTP RESPONSE :81781edc1e\nRT_SOFTCUTTIME=7800.0 RPM ( Soft Cut )\nRT_HARDCUTTIME=7900.0 RPM ( Hard Cut )<\/pre>\n\n\n\n<p>Remember this is all test data that I\u2019ve \u201ccaptured\u201d or \u201csniffed\u201d when Easimap was communicating with the cars ECU. To this point none of my code is sending anything to the car. So, before I could do some real damage to the car and send my own data to the ECU, there was one more test I wanted to do to make sure everything was going to be as safe as I could make it. I wanted to connect up a Logic Analyser to the CAN bus so I could make sure the communications were working as expected&#8230;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Now we need to start proving some of our theories about how Easimap is actually talking to the ECU. And it seemed to me that if I was going to prove anything then I&#8217;d need to pass a lot of data through any theory I came up with, and that meant writing a program &#8211; [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"advanced_seo_description":"","jetpack_seo_html_title":"","jetpack_seo_noindex":false,"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","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[51,20],"tags":[34],"class_list":["post-5038","post","type-post","status-publish","format-standard","hentry","category-caterham-blog","category-ecu-diagnostics","tag-ecu-diagnostics"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p8yl38-1jg","jetpack-related-posts":[{"id":4943,"url":"https:\/\/purplemeanie.co.uk\/index.php\/2019\/09\/07\/ecu-diagnostics-part-5-the-correlator-dead-end\/","url_meta":{"origin":5038,"position":0},"title":"ECU Diagnostics &#8211; part 5 : The Correlator Dead-end","author":"John Martin","date":"September 7, 2019","format":false,"excerpt":"Hopefully this is a quick post... The story so far is that: We've got a test bench made of a Raspberry Pi, CAN bus decoder board and an OBD Y-cableThe Raspberry Pi can \"sniff\" all the packets sent between the car's ECU and something that can talk to the car,\u2026","rel":"","context":"In &quot;Caterham Blog&quot;","block_context":{"text":"Caterham Blog","link":"https:\/\/purplemeanie.co.uk\/index.php\/category\/caterham-blog\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/purplemeanie.co.uk\/wp-content\/uploads\/2019\/09\/Github-Correlator.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/purplemeanie.co.uk\/wp-content\/uploads\/2019\/09\/Github-Correlator.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/purplemeanie.co.uk\/wp-content\/uploads\/2019\/09\/Github-Correlator.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/purplemeanie.co.uk\/wp-content\/uploads\/2019\/09\/Github-Correlator.png?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/purplemeanie.co.uk\/wp-content\/uploads\/2019\/09\/Github-Correlator.png?resize=1050%2C600&ssl=1 3x, https:\/\/i0.wp.com\/purplemeanie.co.uk\/wp-content\/uploads\/2019\/09\/Github-Correlator.png?resize=1400%2C800&ssl=1 4x"},"classes":[]},{"id":5155,"url":"https:\/\/purplemeanie.co.uk\/index.php\/2019\/09\/20\/ecu-diagnostics-part-13-3-mbe-isotp\/","url_meta":{"origin":5038,"position":1},"title":"ECU Diagnostics &#8211; part 13.3 : MBE-ISOTP","author":"John Martin","date":"September 20, 2019","format":false,"excerpt":"SUMMARY We now understand the communications protocol used by Easimap (the Windows software supplied by the ECU manufacturer) and can use it to ask the ECU for whatever data the car has to offer. We can then manipulate the responses we get back from the car and format them to\u2026","rel":"","context":"In &quot;Caterham Blog&quot;","block_context":{"text":"Caterham Blog","link":"https:\/\/purplemeanie.co.uk\/index.php\/category\/caterham-blog\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":5004,"url":"https:\/\/purplemeanie.co.uk\/index.php\/2019\/09\/15\/ecu-diagnostics-part-9-the-easimap-protocol-theory\/","url_meta":{"origin":5038,"position":2},"title":"ECU Diagnostics &#8211; part 9 : The Easimap Protocol Theory","author":"John Martin","date":"September 15, 2019","format":false,"excerpt":"Ok. so we've set ourselves up to be able to look at what is going on with a Caterham diagnostics port, we've talked a bit about the theory of what we might see from the port and we've also seen that Easimap talks to the ECU using a higher level\u2026","rel":"","context":"In &quot;ECU Diagnostics&quot;","block_context":{"text":"ECU Diagnostics","link":"https:\/\/purplemeanie.co.uk\/index.php\/category\/caterham-blog\/ecu-diagnostics\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/purplemeanie.co.uk\/wp-content\/uploads\/2019\/09\/Part-9-Banner.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/purplemeanie.co.uk\/wp-content\/uploads\/2019\/09\/Part-9-Banner.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/purplemeanie.co.uk\/wp-content\/uploads\/2019\/09\/Part-9-Banner.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/purplemeanie.co.uk\/wp-content\/uploads\/2019\/09\/Part-9-Banner.png?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":5008,"url":"https:\/\/purplemeanie.co.uk\/index.php\/2019\/09\/15\/ecu-diagnostics-part-8-easimap-uses-isotp\/","url_meta":{"origin":5038,"position":3},"title":"ECU Diagnostics &#8211; part 8 : Easimap uses ISOTP (sort of)","author":"John Martin","date":"September 15, 2019","format":false,"excerpt":"Ok, that's enough of the theory about mapping. Lets get back to what Easimap is doing when it talks to the car. When we left this subject last we had got to the point where we could see what Easimap was sending and receiving on the CAN bus, but we\u2026","rel":"","context":"In &quot;Caterham Blog&quot;","block_context":{"text":"Caterham Blog","link":"https:\/\/purplemeanie.co.uk\/index.php\/category\/caterham-blog\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/purplemeanie.co.uk\/wp-content\/uploads\/2019\/09\/CANBus-Header-Diagram.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/purplemeanie.co.uk\/wp-content\/uploads\/2019\/09\/CANBus-Header-Diagram.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/purplemeanie.co.uk\/wp-content\/uploads\/2019\/09\/CANBus-Header-Diagram.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/purplemeanie.co.uk\/wp-content\/uploads\/2019\/09\/CANBus-Header-Diagram.png?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/purplemeanie.co.uk\/wp-content\/uploads\/2019\/09\/CANBus-Header-Diagram.png?resize=1050%2C600&ssl=1 3x"},"classes":[]},{"id":5192,"url":"https:\/\/purplemeanie.co.uk\/index.php\/2019\/09\/20\/ecu-diagnostics-part-14-software-framework-mbe-py\/","url_meta":{"origin":5038,"position":4},"title":"ECU Diagnostics &#8211; part 14 : Software Framework mbe.py","author":"John Martin","date":"September 20, 2019","format":false,"excerpt":"This is hopefully a reasonably short post about the software framework I've developed to help read sensor data from the MBE 9A4 ECU. The software is written in Python 3 and is available here: Caterham-OBD. However, I'm going to talk about using one file only which is mbe.py.\u00a0 The idea\u2026","rel":"","context":"In &quot;Caterham Blog&quot;","block_context":{"text":"Caterham Blog","link":"https:\/\/purplemeanie.co.uk\/index.php\/category\/caterham-blog\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":4731,"url":"https:\/\/purplemeanie.co.uk\/index.php\/2019\/09\/12\/ecu-diagnostics-part-7-ecu-maps-and-mapping\/","url_meta":{"origin":5038,"position":5},"title":"ECU Diagnostics &#8211; part 7 : ECU Maps and Mapping","author":"John Martin","date":"September 12, 2019","format":false,"excerpt":"People often talk about \"mapping\" a car. When they do that they're usually interested in one or more of three things: To increase its performance Improve its fuel economyImprove its drivability So what is mapping? In technical terms a map is a translation, or conversion, function that takes an input\u2026","rel":"","context":"In &quot;Caterham Blog&quot;","block_context":{"text":"Caterham Blog","link":"https:\/\/purplemeanie.co.uk\/index.php\/category\/caterham-blog\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/purplemeanie.co.uk\/wp-content\/uploads\/2019\/08\/matplottest2-e1567080546893.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/purplemeanie.co.uk\/wp-content\/uploads\/2019\/08\/matplottest2-e1567080546893.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/purplemeanie.co.uk\/wp-content\/uploads\/2019\/08\/matplottest2-e1567080546893.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/purplemeanie.co.uk\/wp-content\/uploads\/2019\/08\/matplottest2-e1567080546893.png?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/purplemeanie.co.uk\/wp-content\/uploads\/2019\/08\/matplottest2-e1567080546893.png?resize=1050%2C600&ssl=1 3x"},"classes":[]}],"jetpack_likes_enabled":true,"_links":{"self":[{"href":"https:\/\/purplemeanie.co.uk\/index.php\/wp-json\/wp\/v2\/posts\/5038","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/purplemeanie.co.uk\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/purplemeanie.co.uk\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/purplemeanie.co.uk\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/purplemeanie.co.uk\/index.php\/wp-json\/wp\/v2\/comments?post=5038"}],"version-history":[{"count":1,"href":"https:\/\/purplemeanie.co.uk\/index.php\/wp-json\/wp\/v2\/posts\/5038\/revisions"}],"predecessor-version":[{"id":10698,"href":"https:\/\/purplemeanie.co.uk\/index.php\/wp-json\/wp\/v2\/posts\/5038\/revisions\/10698"}],"wp:attachment":[{"href":"https:\/\/purplemeanie.co.uk\/index.php\/wp-json\/wp\/v2\/media?parent=5038"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/purplemeanie.co.uk\/index.php\/wp-json\/wp\/v2\/categories?post=5038"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/purplemeanie.co.uk\/index.php\/wp-json\/wp\/v2\/tags?post=5038"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}