{"id":695,"date":"2026-05-19T08:22:53","date_gmt":"2026-05-19T16:22:53","guid":{"rendered":"https:\/\/salemdata.net\/johnpress\/?p=695"},"modified":"2026-05-19T08:22:53","modified_gmt":"2026-05-19T16:22:53","slug":"from-python-prototype-to-c-protocol-core-a-ble-reticulum-milestone","status":"publish","type":"post","link":"https:\/\/salemdata.net\/johnpress\/?p=695","title":{"rendered":"From Python Prototype to C++ Protocol Core: A BLE Reticulum Milestone"},"content":{"rendered":"<h3><strong>highly technical<\/strong><\/h3>\n<p><strong>The goal is simple to state and hard to implement: move the Reticulum node closer to the radio hardware, so the T-Beam is no longer merely a modem for a phone, but a Reticulum participant in its own right.<\/strong><\/p>\n<figure id=\"attachment_696\" aria-describedby=\"caption-attachment-696\" style=\"width: 112px\" class=\"wp-caption alignleft\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-696 alignleft\" src=\"https:\/\/salemdata.net\/johnpress\/wp-content\/uploads\/2026\/05\/20260518_195622_Mon.png\" alt=\"an avatar with purple bars for eyes and a square for a mouth\" width=\"112\" height=\"125\" srcset=\"https:\/\/salemdata.net\/johnpress\/wp-content\/uploads\/2026\/05\/20260518_195622_Mon.png 386w, https:\/\/salemdata.net\/johnpress\/wp-content\/uploads\/2026\/05\/20260518_195622_Mon-269x300.png 269w\" sizes=\"auto, (max-width: 112px) 100vw, 112px\" \/><figcaption id=\"caption-attachment-696\" class=\"wp-caption-text\">torlando<\/figcaption><\/figure>\n<p>GitHub user <a href=\"https:\/\/github.com\/torlando-tech\">torlando-tech<\/a> designed a Bluetooth protocol for <a href=\"https:\/\/reticulum.network\/\">Reticulum<\/a>. Bluetooth is not easy. A BLE interface has to manage discovery, connection direction, dropped connections, identity, fragmentation, reassembly, and recovery. It is not a simple ON\/OFF radio link.<\/p>\n<p>Torlando also built a Python scaffold around that protocol. My goal was to see whether the protocol behavior could be migrated into C++ so it could eventually support a Bluetooth interface for the LilyGO T-Beam SUPREME running Chad Attermann\u2019s microReticulum.<\/p>\n<p>Torlando has also built a Reticulum client application named Columba, described as:<\/p>\n<p style=\"padding-left: 160px;\">\u201ca simple messaging and voice app for the <a href=\"https:\/\/github.com\/markqvist\/Reticulum\">Reticulum<\/a> network on Android. Send <a href=\"https:\/\/github.com\/markqvist\/LXMF\">LXMF<\/a> messages and make <a href=\"https:\/\/github.com\/markqvist\/LXST\/tree\/master\/LXST\">LXST<\/a> voice calls without relying on the internet, cell towers, or any central servers.\u201d<\/p>\n<figure id=\"attachment_697\" aria-describedby=\"caption-attachment-697\" style=\"width: 113px\" class=\"wp-caption alignleft\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-697\" src=\"https:\/\/salemdata.net\/johnpress\/wp-content\/uploads\/2026\/05\/20260518_200513_Mon.png\" alt=\"skull with a tweed driving cap\" width=\"113\" height=\"123\" srcset=\"https:\/\/salemdata.net\/johnpress\/wp-content\/uploads\/2026\/05\/20260518_200513_Mon.png 380w, https:\/\/salemdata.net\/johnpress\/wp-content\/uploads\/2026\/05\/20260518_200513_Mon-277x300.png 277w\" sizes=\"auto, (max-width: 113px) 100vw, 113px\" \/><figcaption id=\"caption-attachment-697\" class=\"wp-caption-text\">Chad Attermann<\/figcaption><\/figure>\n<p>Chad Attermann\u2019s microReticulum is written in C++. I have compiled microReticulum and run it on a T-Beam. It worked well for my simple test, but the T-Beam\u2019s built-in interface is a tiny screen intended mostly for status messages. My test used predetermined messages; it did not provide a practical human interface for typing, reading, or managing conversations.<\/p>\n<p>The usual approach is to run a Reticulum client on Android, where a person can read and compose messages, while the T-Beam acts as a LoRa modem. That works, but it keeps the Reticulum node conceptually higher up the stack, on the phone side.<\/p>\n<p>What interests me is the opposite architecture: run the Reticulum instance on the T-Beam itself, and let the phone or other human-friendly device connect over Bluetooth as the user interface. In that model, the T-Beam is not merely a modem. It is the Reticulum node. The phone becomes the keyboard, screen, and operator console.<\/p>\n<p>Moving the Reticulum instance down onto the T-Beam creates a more self-contained communications device. If cellular service or the internet is unavailable, the T-Beam still has its LoRa radio, its Reticulum identity, and its mesh-network role.<\/p>\n<p>To make that architecture practical, the Bluetooth protocol cannot remain only in Python. A future T-Beam\/microReticulum implementation needs the BLE protocol and session behavior available in C++.<\/p>\n<p>So I set out to migrate the protocol-relevant parts of Torlando\u2019s BLE Reticulum work into a C++ core. The important point is not merely that C++ code was compiled. The milestone is that the BLE protocol behavior was separated from the Python\/Linux scaffolding and moved into a C++ library that Python can call for testing.<\/p>\n<p>Python still serves as the Linux test harness and adapter. The protocol\/session core is now C++. That is the bridge toward eventually using the same logic inside microReticulum on ESP32-S3 hardware.<\/p>\n<p>Mind you, this is not the type of programming I did at Oracle \u2014 far from it. In retirement I have become fascinated with smaller electronic devices, radio, and embedded systems. I used OpenAI\u2019s ChatGPT as a high-level architectural tutor and reviewer, and I used OpenAI Codex inside Visual Studio Code to inspect, modify, build, and test the code on my workstation.<\/p>\n<p>My role was part programmer, part test operator, and part project manager. I maintained the Forgejo repository, moved code between my Intel workstation and two Raspberry Pi Zero 2Ws, ran field tests, preserved logs, and forced the work through a staged validation process.<\/p>\n<p>Over a couple of days, with ChatGPT and Codex assisting, I reached a working C++ protocol\/session core based on Torlando\u2019s BLE Reticulum protocol. The major intellectual credit for the protocol belongs to Torlando. My contribution was to help distill that behavior into C++ and prove that it could still move Reticulum traffic in a live test.<\/p>\n<p>For a field test, I used two Raspberry Pi Zero 2Ws. Each ran the Reticulum BLE test harness, explicitly configured to require the C++ session backend and the C++ fragmentation backend. I then had the two devices exchange the complete text of the United States Constitution over Reticulum using BLE.<\/p>\n<p>The point of this test was not literary patriotism, although the Constitution is a convenient piece of public-domain text. The point was to force a non-trivial bilateral transfer through the BLE Reticulum stack and verify that the C++ protocol\/session core was actually being used.<\/p>\n<p>Here are the consoles for the two Pis:<\/p>\n<div class=\"reticulum-console-pair\">\n<div class=\"reticulum-console-shell\">\n<div class=\"reticulum-console-title\">jlpoole@zerodev1: \/usr\/local\/src\/ble-reticulum \u2014 Konsole<\/div>\n<p><iframe class=\"reticulum-console-frame\" src=\"https:\/\/salemdata.net\/dev\/reticulum\/logs\/20260518_1855_zerodev1_Gate2F_BilateralConstitution_90seconds_console_20260518_205120.html\"><br \/>\n<\/iframe><\/p>\n<\/div>\n<div class=\"reticulum-console-shell\">\n<div class=\"reticulum-console-title\">jlpoole@zerodev2: \/usr\/local\/src\/ble-reticulum \u2014 Konsole<\/div>\n<p><iframe class=\"reticulum-console-frame\" src=\"https:\/\/salemdata.net\/dev\/reticulum\/logs\/20260518_1855_zerodev2_Gate2F_BilateralConstitution_90seconds_console_20260518_204140.html\"><br \/>\n<\/iframe><\/p>\n<\/div>\n<\/div>\n<p>Then I generate a report:<\/p>\n<pre class=\"reticulum-report-block\">Reticulum BLE file transfer analysis\r\nGenerated: 2026-05-18 21:22:51 PDT\r\nInput files:\r\n  tmp\/run17\/20260518_1855_zerodev1_Gate2F_BilateralConstitution_90seconds.txt\r\n  tmp\/run17\/20260518_1855_zerodev2_Gate2F_BilateralConstitution_90seconds.txt\r\n\r\nLog provenance summary:\r\n  20260518_1855_zerodev1_Gate2F_BilateralConstitution_90seconds.txt receiver=zerodev1   date='Mon May 18 18:51:32 PDT 2026' provenance=script        command_lines=0 data_lines=602\r\n    invoked_script      : migration\/zerodev1_command_clump_Gate2F_BilateralConstitution_90seconds.sh\r\n    invoked_working_dir : \/usr\/local\/src\/ble-reticulum\r\n    resolved_script     : \/usr\/local\/src\/ble-reticulum\/migration\/zerodev1_command_clump_Gate2F_BilateralConstitution_90seconds.sh\r\n  20260518_1855_zerodev2_Gate2F_BilateralConstitution_90seconds.txt receiver=zerodev2   date='Mon May 18 06:51:34 PM PDT 2026' provenance=script        command_lines=0 data_lines=597\r\n    invoked_script      : migration\/zerodev2_command_clump_Gate2F_BilateralConstitution_90seconds.sh\r\n    invoked_working_dir : \/usr\/local\/src\/ble-reticulum\r\n    resolved_script     : \/usr\/local\/src\/ble-reticulum\/migration\/zerodev2_command_clump_Gate2F_BilateralConstitution_90seconds.sh\r\n\r\nCPP backend preflight summary:\r\n  20260518_1855_zerodev1_Gate2F_BilateralConstitution_90seconds.txt\r\n    BLE_RETICULUM_SESSION_BACKEND       : cpp\r\n    BLE_RETICULUM_FRAGMENTATION_BACKEND : cpp\r\n    ble_protocol_core_cpp               : \/usr\/local\/src\/ble-reticulum\/migration\/protocol_core\/ble_protocol_core_cpp.cpython-313-aarch64-linux-gnu.so\r\n    fragmentation backend               : cpp\r\n    session backend                     : cpp\r\n    CPP backend preflight               : OK\r\n    BLEInterface backend line           : cpp (fragmenter=ble_protocol_core_cpp.BLEFragmenter, reassembler=ble_protocol_core_cpp.BLEReassembler)\r\n  20260518_1855_zerodev2_Gate2F_BilateralConstitution_90seconds.txt\r\n    BLE_RETICULUM_SESSION_BACKEND       : cpp\r\n    BLE_RETICULUM_FRAGMENTATION_BACKEND : cpp\r\n    ble_protocol_core_cpp               : \/usr\/local\/src\/ble-reticulum\/migration\/protocol_core\/ble_protocol_core_cpp.cpython-313-aarch64-linux-gnu.so\r\n    fragmentation backend               : cpp\r\n    session backend                     : cpp\r\n    CPP backend preflight               : OK\r\n    BLEInterface backend line           : cpp (fragmenter=ble_protocol_core_cpp.BLEFragmenter, reassembler=ble_protocol_core_cpp.BLEReassembler)\r\n\r\nCommand provenance:\r\n--- tmp\/run17\/20260518_1855_zerodev1_Gate2F_BilateralConstitution_90seconds.txt ---\r\nInvoked from terminal capture:\r\n  cwd    : \/usr\/local\/src\/ble-reticulum\r\n  script : migration\/zerodev1_command_clump_Gate2F_BilateralConstitution_90seconds.sh\r\n\r\nResolved local script file: \/usr\/local\/src\/ble-reticulum\/migration\/zerodev1_command_clump_Gate2F_BilateralConstitution_90seconds.sh\r\n  #!\/usr\/bin\/bash\r\n  #\r\n  #\r\n  #\r\n  # Gate 2F Life Field Acceptance Bilateral Constitution 90 seconds\r\n  # zerodev1 CPP Command clump START\r\n  date\r\n  cd \/usr\/local\/src\/ble-reticulum\/\r\n  chronyc tracking\r\n  chronyc sources -v\r\n  echo .\r\n  \r\n  cd migration\/protocol_core\r\n  python3 setup.py build_ext --inplace\r\n  cd ..\/..\r\n  \r\n  PYTHONPATH=src:migration\/protocol_core \\\r\n  BLE_RETICULUM_SESSION_BACKEND=cpp \\\r\n  BLE_RETICULUM_FRAGMENTATION_BACKEND=cpp \\\r\n  python3 - &lt;&lt;'PY'\r\n  import os, sys\r\n  print(\"PYTHON:\", sys.executable)\r\n  print(\"PYTHONPATH:\", os.environ.get(\"PYTHONPATH\"))\r\n  print(\"BLE_RETICULUM_SESSION_BACKEND:\", os.environ.get(\"BLE_RETICULUM_SESSION_BACKEND\"))\r\n  print(\"BLE_RETICULUM_FRAGMENTATION_BACKEND:\", os.environ.get(\"BLE_RETICULUM_FRAGMENTATION_BACKEND\"))\r\n  import ble_protocol_core_cpp\r\n  print(\"ble_protocol_core_cpp:\", ble_protocol_core_cpp.__file__)\r\n  from ble_reticulum.BLEFragmentationBackend import BACKEND as FRAG_BACKEND\r\n  from ble_reticulum.BLESessionBackend import BACKEND as SESSION_BACKEND\r\n  print(\"fragmentation backend:\", FRAG_BACKEND)\r\n  print(\"session backend:\", SESSION_BACKEND)\r\n  if FRAG_BACKEND != \"cpp\":\r\n      raise SystemExit(f\"ERROR: expected fragmentation backend cpp, got {FRAG_BACKEND!r}\")\r\n  if SESSION_BACKEND != \"cpp\":\r\n      raise SystemExit(f\"ERROR: expected session backend cpp, got {SESSION_BACKEND!r}\")\r\n  print(\"CPP backend preflight: OK\")\r\n  PY\r\n  \r\n  echo .\r\n  \r\n  PYTHONPATH=src:migration\/protocol_core \\\r\n  BLE_RETICULUM_SESSION_BACKEND=cpp \\\r\n  BLE_RETICULUM_FRAGMENTATION_BACKEND=cpp \\\r\n  BLE_RETICULUM_FRAGMENTATION_BACKEND_REPORT=1 \\\r\n  timeout 90 python3 examples\/ble_dual_node_echo.py \\\r\n    --ble-role peripheral \\\r\n    --message-file \/usr\/local\/src\/ble-reticulum\/samples\/US_Constitution.txt \\\r\n    --message-chunk-size 900 \\\r\n    --announce-only-when-disconnected \\\r\n    --verbosity debug\r\n  \r\n  echo .\r\n  chronyc tracking\r\n  chronyc sources -v\r\n  # zerodev1 Command clump END  for  Gate 2F Life Field Acceptance Bilateral Constitution 90 seconds\r\n  \r\n\r\n--- tmp\/run17\/20260518_1855_zerodev2_Gate2F_BilateralConstitution_90seconds.txt ---\r\nInvoked from terminal capture:\r\n  cwd    : \/usr\/local\/src\/ble-reticulum\r\n  script : migration\/zerodev2_command_clump_Gate2F_BilateralConstitution_90seconds.sh\r\n\r\nResolved local script file: \/usr\/local\/src\/ble-reticulum\/migration\/zerodev2_command_clump_Gate2F_BilateralConstitution_90seconds.sh\r\n  #!\/usr\/bin\/bash\r\n  #\r\n  #\r\n  #\r\n  \r\n  #  Gate 2F Life Field Acceptance Bilateral Constitution 90 seconds\r\n  # zerodev2 CPP Command clump START\r\n  date\r\n  cd \/usr\/local\/src\/ble-reticulum\/\r\n  chronyc tracking\r\n  chronyc sources -v\r\n  echo .\r\n  \r\n  cd migration\/protocol_core\r\n  python3 setup.py build_ext --inplace\r\n  cd ..\/..\r\n  \r\n  PYTHONPATH=src:migration\/protocol_core \\\r\n  BLE_RETICULUM_SESSION_BACKEND=cpp \\\r\n  BLE_RETICULUM_FRAGMENTATION_BACKEND=cpp \\\r\n  python3 - &lt;&lt;'PY' import os, sys print(\"PYTHON:\", sys.executable) print(\"PYTHONPATH:\", os.environ.get(\"PYTHONPATH\")) print(\"BLE_RETICULUM_SESSION_BACKEND:\", os.environ.get(\"BLE_RETICULUM_SESSION_BACKEND\")) print(\"BLE_RETICULUM_FRAGMENTATION_BACKEND:\", os.environ.get(\"BLE_RETICULUM_FRAGMENTATION_BACKEND\")) import ble_protocol_core_cpp print(\"ble_protocol_core_cpp:\", ble_protocol_core_cpp.__file__) from ble_reticulum.BLEFragmentationBackend import BACKEND as FRAG_BACKEND from ble_reticulum.BLESessionBackend import BACKEND as SESSION_BACKEND print(\"fragmentation backend:\", FRAG_BACKEND) print(\"session backend:\", SESSION_BACKEND) if FRAG_BACKEND != \"cpp\": raise SystemExit(f\"ERROR: expected fragmentation backend cpp, got {FRAG_BACKEND!r}\") if SESSION_BACKEND != \"cpp\": raise SystemExit(f\"ERROR: expected session backend cpp, got {SESSION_BACKEND!r}\") print(\"CPP backend preflight: OK\") PY echo . PYTHONPATH=src:migration\/protocol_core \\ BLE_RETICULUM_SESSION_BACKEND=cpp \\ BLE_RETICULUM_FRAGMENTATION_BACKEND=cpp \\ BLE_RETICULUM_FRAGMENTATION_BACKEND_REPORT=1 \\ timeout 90 python3 examples\/ble_dual_node_echo.py \\ --ble-role both \\ --message-file \/usr\/local\/src\/ble-reticulum\/samples\/US_Constitution.txt \\ --peer 926e6d3b35b7d5940be7edeb47c41b78 \\ --announce-only-when-disconnected \\ --verbosity debug echo . chronyc tracking chronyc sources -v # zerodev2 Command clump END Bilateral Constitution 90 seconds Chrony clock notes from logs: 20260518_1855_zerodev1_Gate2F_BilateralConstitution_90seconds.txt System time : 0.000026430 seconds fast of NTP time System time : 0.000025351 seconds fast of NTP time 20260518_1855_zerodev2_Gate2F_BilateralConstitution_90seconds.txt System time : 0.000424481 seconds slow of NTP time System time : 0.000403937 seconds slow of NTP time Declared outbound sends observed in logs: sender=zerodev1 file=US_Constitution.txt chunks= 140 bytes= 44225 chunk_data_bytes=316 sender=zerodev2 file=US_Constitution.txt chunks= 148 bytes= 44225 chunk_data_bytes=n\/a Direction: zerodev1-&gt;zerodev2\r\n  file                 : US_Constitution.txt\r\n  chunks received      : 140 of 140\r\n  completeness         : 100.00%\r\n  missing chunks       : none\r\n  duplicate chunks     : none\r\n  payload bytes RX     : 44225\r\n  first chunk RX       : 18:51:56.440\r\n  last chunk RX        : 18:52:32.224\r\n  receiver span        : 35.784 s\r\n  sender span          : 14.284 s\r\n  payload rate RX span : 1235.9 B\/s  9887.1 bit\/s\r\n  payload rate TX span : 3096.2 B\/s  24769.5 bit\/s\r\n  one-way latency       min\/median\/mean\/p95\/max\/stddev: 246.149 \/ 11198.795 \/ 11161.263 \/ 21055.598 \/ 21746.446 \/ 6355.931 ms\r\n  receiver inter-chunk gap min\/median\/mean\/p95\/max\/stddev: 183.000 \/ 244.000 \/ 257.439 \/ 294.000 \/ 387.000 \/ 37.358 ms\r\n  sender inter-chunk gap min\/median\/mean\/p95\/max\/stddev: 101.891 \/ 102.930 \/ 102.760 \/ 103.330 \/ 108.815 \/ 0.875 ms\r\n\r\nDirection: zerodev2-&gt;zerodev1\r\n  file                 : US_Constitution.txt\r\n  chunks received      : 148 of 148\r\n  completeness         : 100.00%\r\n  missing chunks       : none\r\n  duplicate chunks     : none\r\n  payload bytes RX     : 44225\r\n  first chunk RX       : 18:51:56.442\r\n  last chunk RX        : 18:52:30.667\r\n  receiver span        : 34.225 s\r\n  sender span          : 15.483 s\r\n  payload rate RX span : 1292.2 B\/s  10337.5 bit\/s\r\n  payload rate TX span : 2856.4 B\/s  22851.6 bit\/s\r\n  one-way latency       min\/median\/mean\/p95\/max\/stddev: 255.098 \/ 9635.558 \/ 9644.813 \/ 18185.079 \/ 18997.584 \/ 5480.514 ms\r\n  receiver inter-chunk gap min\/median\/mean\/p95\/max\/stddev: 145.000 \/ 243.000 \/ 232.823 \/ 244.000 \/ 293.000 \/ 22.165 ms\r\n  sender inter-chunk gap min\/median\/mean\/p95\/max\/stddev: 103.735 \/ 104.058 \/ 105.323 \/ 109.003 \/ 131.558 \/ 3.637 ms\r\n\r\nHello\/handshake RX records:\r\n  zerodev2   -&gt; zerodev1   recv=18:51:56.118 latency= 129.678 ms message='hello'\r\n  zerodev1   -&gt; zerodev2   recv=18:51:56.124 latency= 117.157 ms message='hello back'\r\n\r\nCaution: one-way latency assumes sender and receiver clocks are synchronized.\r\nYour chronyc tracking output helps bound this error, but it is not a substitute for ACK\/round-trip timing.\r\n\r\n<\/pre>\n<p>The preflight output in both consoles confirms that the C++ module was imported and that both the fragmentation backend and the session backend were set to <code>cpp<\/code>. That matters: this was not a silent fallback to the original Python path.<\/p>\n<h2>SQLite<\/h2>\n<p>SQLite became my project manager. Each function or method was a row. I tracked whether it was protocol core, Python glue, platform code, or test scaffolding; then I advanced selected rows through phases such as design, native testing, Python binding, equivalence testing, optional integration, and field acceptance. The schema worked, but I later realized I should have made status changes append-only so the full development progression could be reconstructed.<\/p>\n<h2>Rust<\/h2>\n<p>Rust is tempting here because the BLE session manager is fundamentally a state-ownership problem. But the immediate target is microReticulum on ESP32-S3, and that ecosystem is already C++. So the practical path is to stabilize the protocol\/session model in C++ first, while preserving enough tests and documentation that a future Rust implementation would not be a translation of Python, but a clean implementation of a known protocol model.<\/p>\n<h2>Conclusion<\/h2>\n<p>This is not yet a finished BLE interface for microReticulum on the T-Beam. But it is an important bridge: Torlando\u2019s Python BLE Reticulum protocol behavior has now been partially distilled into a field-tested C++ core. The next challenge is adapting that C++ session layer to microReticulum\u2019s interface model and the ESP32-S3 Bluetooth stack.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>highly technical The goal is simple to state and hard to implement: move the Reticulum node closer to the radio hardware, so the T-Beam is no longer merely a modem for a phone, but a Reticulum participant in its own right. GitHub user torlando-tech designed a Bluetooth protocol for Reticulum. Bluetooth is not easy. A [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":708,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[37,24,121],"tags":[],"class_list":["post-695","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ai","category-raspberry-pi-zero-2-w","category-t-beam"],"_links":{"self":[{"href":"https:\/\/salemdata.net\/johnpress\/index.php?rest_route=\/wp\/v2\/posts\/695","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/salemdata.net\/johnpress\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/salemdata.net\/johnpress\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/salemdata.net\/johnpress\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/salemdata.net\/johnpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=695"}],"version-history":[{"count":5,"href":"https:\/\/salemdata.net\/johnpress\/index.php?rest_route=\/wp\/v2\/posts\/695\/revisions"}],"predecessor-version":[{"id":701,"href":"https:\/\/salemdata.net\/johnpress\/index.php?rest_route=\/wp\/v2\/posts\/695\/revisions\/701"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/salemdata.net\/johnpress\/index.php?rest_route=\/wp\/v2\/media\/708"}],"wp:attachment":[{"href":"https:\/\/salemdata.net\/johnpress\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=695"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/salemdata.net\/johnpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=695"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/salemdata.net\/johnpress\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=695"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}