{"id":2302,"date":"2021-09-18T22:57:01","date_gmt":"2021-09-19T02:57:01","guid":{"rendered":"http:\/\/matthannan.net\/blog\/?p=2302"},"modified":"2021-09-18T23:47:10","modified_gmt":"2021-09-19T03:47:10","slug":"modernizing-my-temperature-and-humidity-sensor","status":"publish","type":"post","link":"https:\/\/matthannan.net\/blog\/modernizing-my-temperature-and-humidity-sensor\/","title":{"rendered":"Modernizing My Temperature and Humidity Sensor"},"content":{"rendered":"\n<p>My <a rel=\"noreferrer noopener\" href=\"https:\/\/matthannan.net\/blog\/from-the-real-world-to-the-web\/\" target=\"_blank\">basement temperature and humidity sensor<\/a> has been up and running for 2.5 years now with hardly a hiccup at all. But, it is time for an upgrade.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/i0.wp.com\/matthannan.net\/blog\/wp-content\/uploads\/2021\/09\/tnhPage2021.png?ssl=1\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"386\" data-attachment-id=\"2303\" data-permalink=\"https:\/\/matthannan.net\/blog\/modernizing-my-temperature-and-humidity-sensor\/tnhpage2021\/\" data-orig-file=\"https:\/\/i0.wp.com\/matthannan.net\/blog\/wp-content\/uploads\/2021\/09\/tnhPage2021.png?fit=1149%2C694&amp;ssl=1\" data-orig-size=\"1149,694\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"tnhPage2021\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/matthannan.net\/blog\/wp-content\/uploads\/2021\/09\/tnhPage2021.png?fit=640%2C386&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/matthannan.net\/blog\/wp-content\/uploads\/2021\/09\/tnhPage2021.png?resize=640%2C386&#038;ssl=1\" alt=\"\" class=\"wp-image-2303\" srcset=\"https:\/\/i0.wp.com\/matthannan.net\/blog\/wp-content\/uploads\/2021\/09\/tnhPage2021.png?resize=1024%2C618&amp;ssl=1 1024w, https:\/\/i0.wp.com\/matthannan.net\/blog\/wp-content\/uploads\/2021\/09\/tnhPage2021.png?resize=300%2C181&amp;ssl=1 300w, https:\/\/i0.wp.com\/matthannan.net\/blog\/wp-content\/uploads\/2021\/09\/tnhPage2021.png?resize=768%2C464&amp;ssl=1 768w, https:\/\/i0.wp.com\/matthannan.net\/blog\/wp-content\/uploads\/2021\/09\/tnhPage2021.png?w=1149&amp;ssl=1 1149w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/figure>\n\n\n\n<p>I&#8217;ve made some tweaks to the page over the years, but I &#8216;ve grown less and less happy with the matplotlib implementation. You can see on the X axes that they do not actually reflect the timestamp, but rather the record number. I&#8217;ve gone after this so many times, but no luck. Also, I&#8217;d like to be able to crunch some of those numbers.<\/p>\n\n\n\n<p>In my research of how to modernize this, I discovered <a rel=\"noreferrer noopener\" href=\"https:\/\/grafana.com\/\" target=\"_blank\">Grafana<\/a>, which reads databases and makes pretty graphs out of the data. This does not natively read <a rel=\"noreferrer noopener\" href=\"https:\/\/sqlite.org\/\" target=\"_blank\">sqlite3<\/a> databases, but <a rel=\"noreferrer noopener\" href=\"https:\/\/grafana.com\/grafana\/plugins\/frser-sqlite-datasource\/\" target=\"_blank\">it can be made to<\/a>. It isn&#8217;t easy or nice, however, due to how sqlite3 works with timestamps. Basically, it doesn&#8217;t. It deals with string-formatted timestamps, but Grafana, for all its power, can&#8217;t be arsed to figure out what I have seen in many, many json files:<br><strong>YYYY-MM-DD hh:mm:ss<\/strong><br>It relies on either straight <a rel=\"noreferrer noopener\" href=\"https:\/\/www.unixtimestamp.com\/\" target=\"_blank\">UNIX time<\/a> (I guess for speed, as only a machine can figure out what that means), or something called <a rel=\"noreferrer noopener\" href=\"http:\/\/henry.precheur.org\/python\/rfc3339\" target=\"_blank\">RF3339 format<\/a>, which looks like this:<br><strong>2008-04-02T20:00:00Z<\/strong><br>Yeah, that is an actual thing. Somehow, you can get time zones involved with that mess, too, but, seriously, this time (no pun) it is me who couldn&#8217;t be arsed to figure it out.<\/p>\n\n\n\n<p>What it boils down to is that I have 2.5 years of data trapped in a database that I will not be able to use in Grafana, unless I figure out one of a couple of not-so-easy routes forward. At first, I was thinking of migrating the data to <a rel=\"noreferrer noopener\" href=\"https:\/\/www.mysql.com\/\" target=\"_blank\">MySQL<\/a> (or <a rel=\"noreferrer noopener\" href=\"https:\/\/mariadb.org\/\" target=\"_blank\">MariaDB<\/a> for the Mods), but then I figured that if I was going to start messing with actual SQL databases on small Linux devices, I might as well look at something useful: <a rel=\"noreferrer noopener\" href=\"https:\/\/www.postgresql.org\/\" target=\"_blank\">PostgreSQL<\/a>. So, I set about installing PostgreSQL and Grafana on the target Pi, which is vintage 3B+. Grafana works, but it is not great. And, it has something of a learning curve to it. As for Postgres&#8230; Yeah, that was pretty much a non-starter. I&#8217;d still like to learn it, but not while I am working on this issue.<\/p>\n\n\n\n<p>While learning how to use Grafana, I was introduced to another database, <a rel=\"noreferrer noopener\" href=\"https:\/\/www.influxdata.com\/products\/influxdb\/\" target=\"_blank\">InfluxDB<\/a>, which has great Grafana support, and is a time series database, which means something. So, I installed InfluxDB on the Pi and set out to learn how to make this work. Turns out, it is very different from SQL databases. It uses something called Series instead of Tables. This database write section is copied directly out of my test Python script:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#InfluxDB Connection Details\ninfluxHost = 'localhost'\ninfluxPort = '8086'\ninfluxUser = 'grafana'\ninfluxPasswd = 'none_of_your_business'\ninfluxdbName = 'home'\n\ninflux_metric = &#91;{\n    'measurement': 'TemperatureSensor',\n    'time': datetime.datetime.utcnow(),\n    'fields': {\n        'temperature': temperature,\n        'humidity': humidity,\n        'location': \"basement\"\n    }\n}]\n\n#Saving data to InfluxDB\ntry:\n    db = influxdb.InfluxDBClient(influxHost, influxPort, influxUser, influxPasswd, influxdbName)\n    db.write_points(influx_metric)\nfinally:\n    db.close()<\/code><\/pre>\n\n\n\n<p>If you are familiar with writing to SQL databases in Python, this is fairly different. But, it is pretty easy to figure out, too. In fact, I ran it a couple of time (that isn&#8217;t the whole script&#8230;the sensor set up stuff is all missing) for to see what was getting in the database. And hooking it up to Grafana was totes easy.<\/p>\n\n\n\n<figure class=\"wp-block-gallery columns-1 is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex\"><ul class=\"blocks-gallery-grid\"><li class=\"blocks-gallery-item\"><figure><a href=\"https:\/\/i0.wp.com\/matthannan.net\/blog\/wp-content\/uploads\/2021\/09\/tnhPage_Grafana_InfluxDB-1.png?ssl=1\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"216\" data-attachment-id=\"2305\" data-permalink=\"https:\/\/matthannan.net\/blog\/modernizing-my-temperature-and-humidity-sensor\/tnhpage_grafana_influxdb-1\/\" data-orig-file=\"https:\/\/i0.wp.com\/matthannan.net\/blog\/wp-content\/uploads\/2021\/09\/tnhPage_Grafana_InfluxDB-1.png?fit=1911%2C645&amp;ssl=1\" data-orig-size=\"1911,645\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"tnhPage_Grafana_InfluxDB-1\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/matthannan.net\/blog\/wp-content\/uploads\/2021\/09\/tnhPage_Grafana_InfluxDB-1.png?fit=640%2C216&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/matthannan.net\/blog\/wp-content\/uploads\/2021\/09\/tnhPage_Grafana_InfluxDB-1.png?resize=640%2C216&#038;ssl=1\" alt=\"\" data-id=\"2305\" data-full-url=\"https:\/\/matthannan.net\/blog\/wp-content\/uploads\/2021\/09\/tnhPage_Grafana_InfluxDB-1.png\" data-link=\"https:\/\/matthannan.net\/blog\/?attachment_id=2305\" class=\"wp-image-2305\" srcset=\"https:\/\/i0.wp.com\/matthannan.net\/blog\/wp-content\/uploads\/2021\/09\/tnhPage_Grafana_InfluxDB-1.png?resize=1024%2C346&amp;ssl=1 1024w, https:\/\/i0.wp.com\/matthannan.net\/blog\/wp-content\/uploads\/2021\/09\/tnhPage_Grafana_InfluxDB-1.png?resize=300%2C101&amp;ssl=1 300w, https:\/\/i0.wp.com\/matthannan.net\/blog\/wp-content\/uploads\/2021\/09\/tnhPage_Grafana_InfluxDB-1.png?resize=768%2C259&amp;ssl=1 768w, https:\/\/i0.wp.com\/matthannan.net\/blog\/wp-content\/uploads\/2021\/09\/tnhPage_Grafana_InfluxDB-1.png?resize=1536%2C518&amp;ssl=1 1536w, https:\/\/i0.wp.com\/matthannan.net\/blog\/wp-content\/uploads\/2021\/09\/tnhPage_Grafana_InfluxDB-1.png?w=1911&amp;ssl=1 1911w, https:\/\/i0.wp.com\/matthannan.net\/blog\/wp-content\/uploads\/2021\/09\/tnhPage_Grafana_InfluxDB-1.png?w=1280&amp;ssl=1 1280w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/figure><\/li><\/ul><\/figure>\n\n\n\n<p>You can see that I am not at all unhappy with the layout of the older webpage. I&#8217;m not sure what is happening yet with the chart, however. There is no line connecting the points. It&#8217;ll get sorted eventually.<\/p>\n\n\n\n<p>As I was working on this, it became clear to me that running the data collection via the sensor and Python, the database server, and the Grafana server all on the lower powered Pi 3B+ was not the best way forward. Grafana can reach out to databases on remote systems, so I installed Grafana on my damn-near idle Pi 4B (4GB), sitting on the desk in my office, and pointed it at the database running on the Pi 3B+, sitting in the network rack in the basement. To my amazement, it connected with no issues.<\/p>\n\n\n\n<p>The more I played around with this, the more I started thinking about having multiple sensors around the house, all reporting in to the one Grafana dashboard. But then it occurred to me that that would be multiple database servers running and I might be able to get away with one&#8230;running on the same box as the Grafana server. I was looking at the fancy ways that InfluxDB might be able to get this accomplished, and then I remembered an often overlooked feature baked right into Raspberry Pi: <a rel=\"noreferrer noopener\" href=\"https:\/\/gpiozero.readthedocs.io\/en\/stable\/remote_gpio.html\" target=\"_blank\">Remote GPIO<\/a>.<\/p>\n\n\n\n<p>I enabled this via raspi-config on the 3B+ and installed the needed software. But before I dove in too deep, I grabbed the Pi4B (1GB) that has been sitting powered off behind me all summer. I mainly use this Pi for time-lapse photography. The last experiment I did on it was with an ultrasonic sensor, and it is still wired up to the breadboard. I really wanted to see about getting that to work from remote, but I followed the docs and made an LED blink&#8230;from across the LAN. I set such a massive cock-a-hoop that Jenny told Calin that I had obviously finally cracked.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#!\/usr\/bin\/python3\n\nfrom gpiozero import LED\nfrom gpiozero.pins.pigpio import PiGPIOFactory\nfrom time import sleep\n\n\nremote_factory = PiGPIOFactory(host='10.25.68.154')\nled = LED(\"BOARD13\", pin_factory=remote_factory)\n\nwhile True:\n    led.value = 1\n    led.on()\n    sleep(1)\n    led.off()\n    sleep(2)<\/code><\/pre>\n\n\n\n<p>Just that easy. Tomorrow, I am going to see about getting readings from the <a rel=\"noreferrer noopener\" href=\"https:\/\/www.sparkfun.com\/products\/15569\" target=\"_blank\">HC-SR04<\/a> ultrasonic sensor. I don&#8217;t think this will be too difficult. The script for getting this sensor to work locally is not much more complex than that above. My worry is that first import statement, though. We&#8217;ll see.<\/p>\n\n\n\n<p>That is where I am going to leave this for tonight. Once I get the pieces in place and working, I will then turn my attention to figuring out how to import the 2.5 years of data from the 3B+. There&#8217;s got to be a way to do this, but I simply haven&#8217;t found it yet.<\/p>\n\n\n\n<p>I&#8217;d like to thank the authors of the main tutorials I have been following:<br>* <a rel=\"noreferrer noopener\" href=\"https:\/\/simonhearne.com\/2020\/pi-influx-grafana\/\" target=\"_blank\">Simon Hearne<\/a><br>* <a rel=\"noreferrer noopener\" href=\"https:\/\/notenoughtech.com\/featured\/grafana-influxdb\/\" target=\"_blank\">Mat at notenoughtech.com<\/a>, who has obviously been down this same road many times previously<br>* And countless other bloggers and tinkerers.<\/p>\n\n\n\n<p>Thank you all.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>My basement temperature and humidity sensor has been up and running for 2.5 years now with hardly a hiccup at all. But, it is time for an upgrade. I&#8217;ve made some tweaks to the page over the years, but I &hellip; <a href=\"https:\/\/matthannan.net\/blog\/modernizing-my-temperature-and-humidity-sensor\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/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":""},"categories":[5],"tags":[94,604,602,600,418,601,98,313,326,603,417],"class_list":["post-2302","post","type-post","status-publish","format-standard","hentry","category-geek","tag-calin","tag-cock-a-hoop","tag-databases","tag-grafana","tag-humidity","tag-influxdb","tag-jenny","tag-python","tag-raspberrypi","tag-remote-gpio","tag-temperature"],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p2NxlE-B8","jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"jetpack-related-posts":[{"id":1576,"url":"https:\/\/matthannan.net\/blog\/from-the-real-world-to-the-web\/","url_meta":{"origin":2302,"position":0},"title":"From the Real World to the Web","author":"matthannan","date":"9 April 2019","format":false,"excerpt":"Part of my quest for world domination, er, getting my Raspberry Pi to tell me about things in my basement without my having to actually go down there is just about complete. I bought a temperature and humidity sensor from Adafruit and finally got around to wiring it up and\u2026","rel":"","context":"In &quot;Geek&quot;","block_context":{"text":"Geek","link":"https:\/\/matthannan.net\/blog\/category\/geek\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/matthannan.net\/blog\/wp-content\/uploads\/2019\/04\/tnhPage.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/matthannan.net\/blog\/wp-content\/uploads\/2019\/04\/tnhPage.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/matthannan.net\/blog\/wp-content\/uploads\/2019\/04\/tnhPage.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/matthannan.net\/blog\/wp-content\/uploads\/2019\/04\/tnhPage.png?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/matthannan.net\/blog\/wp-content\/uploads\/2019\/04\/tnhPage.png?resize=1050%2C600&ssl=1 3x, https:\/\/i0.wp.com\/matthannan.net\/blog\/wp-content\/uploads\/2019\/04\/tnhPage.png?resize=1400%2C800&ssl=1 4x"},"classes":[]},{"id":2464,"url":"https:\/\/matthannan.net\/blog\/what-i-did-on-my-mid-summer-vacation-day-5\/","url_meta":{"origin":2302,"position":1},"title":"What I Did on My Mid-Summer Vacation: Day 5","author":"matthannan","date":"31 August 2022","format":false,"excerpt":"Forecast for the day is a heat advisory. If we haven't already been under one, having one today was really bad news. I took advantage of not being able to work out in the yard to get caught up on the checking account and paying the couple of bills that\u2026","rel":"","context":"In &quot;Geek&quot;","block_context":{"text":"Geek","link":"https:\/\/matthannan.net\/blog\/category\/geek\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/matthannan.net\/blog\/wp-content\/uploads\/2022\/08\/mqtt-publish-subscribe-3.png?fit=1024%2C320&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/matthannan.net\/blog\/wp-content\/uploads\/2022\/08\/mqtt-publish-subscribe-3.png?fit=1024%2C320&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/matthannan.net\/blog\/wp-content\/uploads\/2022\/08\/mqtt-publish-subscribe-3.png?fit=1024%2C320&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/matthannan.net\/blog\/wp-content\/uploads\/2022\/08\/mqtt-publish-subscribe-3.png?fit=1024%2C320&ssl=1&resize=700%2C400 2x"},"classes":[]},{"id":1555,"url":"https:\/\/matthannan.net\/blog\/rsyslog-loganalyzer-follow-up\/","url_meta":{"origin":2302,"position":2},"title":"rsyslog &#038; LogAnalyzer, follow-up","author":"matthannan","date":"17 March 2019","format":false,"excerpt":"Well, it has been a solid day watching these nagging log entries scroll by over and over again. I just cleared up a cacti issue on Pi1 by determining that I was not actually using cacti for anything and removing it, along with the CRON job that was generating the\u2026","rel":"","context":"In &quot;Geek&quot;","block_context":{"text":"Geek","link":"https:\/\/matthannan.net\/blog\/category\/geek\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1435,"url":"https:\/\/matthannan.net\/blog\/making-the-computer-see\/","url_meta":{"origin":2302,"position":3},"title":"Making the computer &#8220;see&#8221;.","author":"matthannan","date":"13 August 2018","format":false,"excerpt":"I am currently down the OpenCV rabbit hole. I want to velcro a Rasp Pi to my oil tank and have it \"see\" how much oil is in there. I don't want to see a picture of the meter. That would be too easy. I want something of an alpha-numeric\u2026","rel":"","context":"In &quot;Geek&quot;","block_context":{"text":"Geek","link":"https:\/\/matthannan.net\/blog\/category\/geek\/"},"img":{"alt_text":"OpenCV","src":"https:\/\/i0.wp.com\/matthannan.net\/blog\/wp-content\/uploads\/2018\/08\/opencv-300x212.png?resize=350%2C200","width":350,"height":200},"classes":[]},{"id":1481,"url":"https:\/\/matthannan.net\/blog\/raspberry-pi-poe-hat\/","url_meta":{"origin":2302,"position":4},"title":"Raspberry Pi POE HAT","author":"matthannan","date":"12 December 2018","format":false,"excerpt":"I am gearing up to return to this OpenCV project. Changing jobs and such do make hobbies a challenge. Looking at how to power the Pi once it is installed on the oil tank is causing me some headaches. I'd love to keep this thing running on WiFi and not\u2026","rel":"","context":"In &quot;Geek&quot;","block_context":{"text":"Geek","link":"https:\/\/matthannan.net\/blog\/category\/geek\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":34,"url":"https:\/\/matthannan.net\/blog\/playing-with-temperature-and-fermentation\/","url_meta":{"origin":2302,"position":5},"title":"Playing with temperature and fermentation","author":"matthannan","date":"13 February 2010","format":false,"excerpt":"So, I've been looking at regulating the temperature of my fermentations beyond wrapping carboys in towels and placing them near radiators.Earlier this week I took my just about then two-week old porter and placed it near a radiator and saw with my own eyes what a couple of degrees can\u2026","rel":"","context":"In &quot;Beer&quot;","block_context":{"text":"Beer","link":"https:\/\/matthannan.net\/blog\/category\/beer\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"_links":{"self":[{"href":"https:\/\/matthannan.net\/blog\/wp-json\/wp\/v2\/posts\/2302","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/matthannan.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/matthannan.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/matthannan.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/matthannan.net\/blog\/wp-json\/wp\/v2\/comments?post=2302"}],"version-history":[{"count":2,"href":"https:\/\/matthannan.net\/blog\/wp-json\/wp\/v2\/posts\/2302\/revisions"}],"predecessor-version":[{"id":2307,"href":"https:\/\/matthannan.net\/blog\/wp-json\/wp\/v2\/posts\/2302\/revisions\/2307"}],"wp:attachment":[{"href":"https:\/\/matthannan.net\/blog\/wp-json\/wp\/v2\/media?parent=2302"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/matthannan.net\/blog\/wp-json\/wp\/v2\/categories?post=2302"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/matthannan.net\/blog\/wp-json\/wp\/v2\/tags?post=2302"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}