ActivityPub Viewer

A small tool to view real-world ActivityPub objects as JSON! Enter a URL or username from Mastodon or a similar service below, and we'll send a request with the right Accept header to the server to view the underlying object.

Open in browser →
{ "@context": [ "https://www.w3.org/ns/activitystreams", { "ostatus": "http://ostatus.org#", "atomUri": "ostatus:atomUri", "inReplyToAtomUri": "ostatus:inReplyToAtomUri", "conversation": "ostatus:conversation", "sensitive": "as:sensitive", "toot": "http://joinmastodon.org/ns#", "votersCount": "toot:votersCount", "litepub": "http://litepub.social/ns#", "directMessage": "litepub:directMessage", "blurhash": "toot:blurhash", "focalPoint": { "@container": "@list", "@id": "toot:focalPoint" }, "Hashtag": "as:Hashtag" } ], "id": "https://infosec.exchange/users/GuillaumeRossolini/statuses/113148736893536072/replies", "type": "Collection", "first": { "id": "https://infosec.exchange/users/GuillaumeRossolini/statuses/113148736893536072/replies?page=true", "type": "CollectionPage", "next": "https://infosec.exchange/users/GuillaumeRossolini/statuses/113148736893536072/replies?only_other_accounts=true&page=true", "partOf": "https://infosec.exchange/users/GuillaumeRossolini/statuses/113148736893536072/replies", "items": [ { "id": "https://infosec.exchange/users/GuillaumeRossolini/statuses/113154895996286210", "type": "Note", "summary": null, "inReplyTo": "https://infosec.exchange/users/GuillaumeRossolini/statuses/113148736893536072", "published": "2024-09-17T20:58:09Z", "url": "https://infosec.exchange/@GuillaumeRossolini/113154895996286210", "attributedTo": "https://infosec.exchange/users/GuillaumeRossolini", "to": [ "https://www.w3.org/ns/activitystreams#Public" ], "cc": [ "https://infosec.exchange/users/GuillaumeRossolini/followers" ], "sensitive": false, "atomUri": "https://infosec.exchange/users/GuillaumeRossolini/statuses/113154895996286210", "inReplyToAtomUri": "https://infosec.exchange/users/GuillaumeRossolini/statuses/113148736893536072", "conversation": "tag:infosec.exchange,2024-09-06:objectId=191694493:objectType=Conversation", "content": "<p>Latest news is that I got my brain into embedded thinking mode</p><p>I changed the way I determine if a sensor reading is worthy of archiving</p><p>The way I set up my probes, each <a href=\"https://infosec.exchange/tags/ESP8266\" class=\"mention hashtag\" rel=\"tag\">#<span>ESP8266</span></a> send its readings as fast as it can (that’s every 3s) to the entire mesh and the root node, the <a href=\"https://infosec.exchange/tags/ESP32\" class=\"mention hashtag\" rel=\"tag\">#<span>ESP32</span></a>, forwards them across WiFi networks over HTTP to my <a href=\"https://infosec.exchange/tags/RaspberryPi\" class=\"mention hashtag\" rel=\"tag\">#<span>RaspberryPi</span></a> Zero W</p><p>The rpi0 then decides what readings to keep and what to toss</p><h1>The naïve strat</h1><p>The way I was deciding what to toss was, until yesterday, an SQL query doing a GROUP BY on the node sending the readings and checking the MAX date for its readings</p><p>The database file is already several dozen MB in size and growing by almost that much daily (I’m stress testing my system), </p><p>Even with a proper SQL index, the SDCard has to read a lot of information on every incoming sensor reading (SQLite is a file based system, there is nothing in RAM), just to decide what to keep and what to toss. That translates into lots of unnecessary i/o of all kinds, faster SDCard wear, and general latency unpleasantness </p><p>The rpi0 CPU was 40% to 90% all the time, according to htop</p><p>I’m way too used to PostgreSQL…</p><h1>The embedded-friendly strat</h1><p>My new strat is simply creating a file on disk for each sensor, changing its modified timestamp and using that to determine when its readings were archived last</p><p>That’s just a handful of empty files on disk and I’m only changing their metadata, not their content. They’re using next to nothing in terms of space. Checking their metadata is also really fast, and possibly cached by the OS and/or my web server.</p><p>Now every HTTP request fits within 4ms if the previous reading for the same sensor was recent, or at most 80ms when the database gets a write </p><p>The rpi0 CPU is now back to low levels, between 7% and 12% most of the time</p><p><a href=\"https://infosec.exchange/tags/electronics\" class=\"mention hashtag\" rel=\"tag\">#<span>electronics</span></a> <a href=\"https://infosec.exchange/tags/diy\" class=\"mention hashtag\" rel=\"tag\">#<span>diy</span></a></p>", "contentMap": { "en": "<p>Latest news is that I got my brain into embedded thinking mode</p><p>I changed the way I determine if a sensor reading is worthy of archiving</p><p>The way I set up my probes, each <a href=\"https://infosec.exchange/tags/ESP8266\" class=\"mention hashtag\" rel=\"tag\">#<span>ESP8266</span></a> send its readings as fast as it can (that’s every 3s) to the entire mesh and the root node, the <a href=\"https://infosec.exchange/tags/ESP32\" class=\"mention hashtag\" rel=\"tag\">#<span>ESP32</span></a>, forwards them across WiFi networks over HTTP to my <a href=\"https://infosec.exchange/tags/RaspberryPi\" class=\"mention hashtag\" rel=\"tag\">#<span>RaspberryPi</span></a> Zero W</p><p>The rpi0 then decides what readings to keep and what to toss</p><h1>The naïve strat</h1><p>The way I was deciding what to toss was, until yesterday, an SQL query doing a GROUP BY on the node sending the readings and checking the MAX date for its readings</p><p>The database file is already several dozen MB in size and growing by almost that much daily (I’m stress testing my system), </p><p>Even with a proper SQL index, the SDCard has to read a lot of information on every incoming sensor reading (SQLite is a file based system, there is nothing in RAM), just to decide what to keep and what to toss. That translates into lots of unnecessary i/o of all kinds, faster SDCard wear, and general latency unpleasantness </p><p>The rpi0 CPU was 40% to 90% all the time, according to htop</p><p>I’m way too used to PostgreSQL…</p><h1>The embedded-friendly strat</h1><p>My new strat is simply creating a file on disk for each sensor, changing its modified timestamp and using that to determine when its readings were archived last</p><p>That’s just a handful of empty files on disk and I’m only changing their metadata, not their content. They’re using next to nothing in terms of space. Checking their metadata is also really fast, and possibly cached by the OS and/or my web server.</p><p>Now every HTTP request fits within 4ms if the previous reading for the same sensor was recent, or at most 80ms when the database gets a write </p><p>The rpi0 CPU is now back to low levels, between 7% and 12% most of the time</p><p><a href=\"https://infosec.exchange/tags/electronics\" class=\"mention hashtag\" rel=\"tag\">#<span>electronics</span></a> <a href=\"https://infosec.exchange/tags/diy\" class=\"mention hashtag\" rel=\"tag\">#<span>diy</span></a></p>" }, "attachment": [ { "type": "Document", "mediaType": "image/jpeg", "url": "https://media.infosec.exchange/infosec.exchange/media_attachments/files/113/154/889/946/242/629/original/60296d064f08fe42.jpeg", "name": "Screenshot of my web server logs showing the time each request took", "blurhash": "U99%#H~p%3sqw[ayWBayxuWBWEflt6ayWBfQ", "focalPoint": [ 0, 0 ], "width": 1398, "height": 1483 } ], "tag": [ { "type": "Hashtag", "href": "https://infosec.exchange/tags/esp8266", "name": "#esp8266" }, { "type": "Hashtag", "href": "https://infosec.exchange/tags/esp32", "name": "#esp32" }, { "type": "Hashtag", "href": "https://infosec.exchange/tags/raspberrypi", "name": "#raspberrypi" }, { "type": "Hashtag", "href": "https://infosec.exchange/tags/electronics", "name": "#electronics" }, { "type": "Hashtag", "href": "https://infosec.exchange/tags/diy", "name": "#diy" } ], "replies": { "id": "https://infosec.exchange/users/GuillaumeRossolini/statuses/113154895996286210/replies", "type": "Collection", "first": { "type": "CollectionPage", "next": "https://infosec.exchange/users/GuillaumeRossolini/statuses/113154895996286210/replies?min_id=113165647871802580&page=true", "partOf": "https://infosec.exchange/users/GuillaumeRossolini/statuses/113154895996286210/replies", "items": [ "https://infosec.exchange/users/GuillaumeRossolini/statuses/113165647871802580" ] } }, "likes": { "id": "https://infosec.exchange/users/GuillaumeRossolini/statuses/113154895996286210/likes", "type": "Collection", "totalItems": 3 }, "shares": { "id": "https://infosec.exchange/users/GuillaumeRossolini/statuses/113154895996286210/shares", "type": "Collection", "totalItems": 0 } } ] } }