<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Geek Mind]]></title><description><![CDATA[Technical Minded Blog]]></description><link>https://undiluted.org/</link><image><url>https://undiluted.org/favicon.png</url><title>Geek Mind</title><link>https://undiluted.org/</link></image><generator>Ghost 2.27</generator><lastBuildDate>Mon, 06 Apr 2026 08:31:34 GMT</lastBuildDate><atom:link href="https://undiluted.org/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Hot Tub PH Sensor System]]></title><description><![CDATA[<p>This blog post, will describe the process of building out a Hot Tub PH monitoring system.</p><p>There will be four sections:</p><ul><li><a href="https://undiluted.org/raspberry-pi-ph-circuit/">Raspberry Pi PH Circuit</a></li><li>C software to store PH data to PostgreSQL Database (coming soon)</li><li> Node.js REST API to obtain PH data from PostgreSQL Database. (coming soon)</li><li>React</li></ul>]]></description><link>https://undiluted.org/hot-tub-ph-sensor-system/</link><guid isPermaLink="false">5dd2c24fd08840050ff369c5</guid><category><![CDATA[C]]></category><category><![CDATA[javascript]]></category><category><![CDATA[node.js]]></category><category><![CDATA[React]]></category><category><![CDATA[Raspberry Pi]]></category><dc:creator><![CDATA[Nicolas Gosselin]]></dc:creator><pubDate>Sun, 22 Dec 2019 20:23:43 GMT</pubDate><content:encoded><![CDATA[<p>This blog post, will describe the process of building out a Hot Tub PH monitoring system.</p><p>There will be four sections:</p><ul><li><a href="https://undiluted.org/raspberry-pi-ph-circuit/">Raspberry Pi PH Circuit</a></li><li>C software to store PH data to PostgreSQL Database (coming soon)</li><li> Node.js REST API to obtain PH data from PostgreSQL Database. (coming soon)</li><li>React Frontend for display of PH Data to end users. (coming soon)</li></ul><p></p><p> </p>]]></content:encoded></item><item><title><![CDATA[Raspberry Pi PH Circuit]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p><strong>Raspberry Pi PH Circuit</strong></p>
<p>The first section of this project was building the Circuit which would be used to pull the PH from the Hot Tub's water.</p>
<p>To build the circuit, I settled on a <a href="https://www.raspberrypi.org/products/raspberry-pi-zero/">Raspberry Pi Zero v1</a>, and not the newer <a href="https://www.raspberrypi.org/products/raspberry-pi-zero-w/">Raspberry Pi Zero W</a>.</p>
<p>The sensor which</p>]]></description><link>https://undiluted.org/raspberry-pi-ph-circuit/</link><guid isPermaLink="false">5dd2e7e9d08840050ff36a18</guid><dc:creator><![CDATA[Nicolas Gosselin]]></dc:creator><pubDate>Sun, 22 Dec 2019 20:23:25 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p><strong>Raspberry Pi PH Circuit</strong></p>
<p>The first section of this project was building the Circuit which would be used to pull the PH from the Hot Tub's water.</p>
<p>To build the circuit, I settled on a <a href="https://www.raspberrypi.org/products/raspberry-pi-zero/">Raspberry Pi Zero v1</a>, and not the newer <a href="https://www.raspberrypi.org/products/raspberry-pi-zero-w/">Raspberry Pi Zero W</a>.</p>
<p>The sensor which I settled on was the PH sensor from <a href="https://www.atlas-scientific.com/product_pages/kits/ph-kit.html">AtlasScientific</a>.</p>
<p>I initially (and purchased later) purchased the kit without the isolation circuit, but would recommend purchasing the isolation circuit to avoid interference the pumps can cause with the PH sensor.</p>
<p>The main reason for going with the v1 Raspberry Pi Zero vs the Raspberry Pi Zero W, was due to the fact that the UART communication on the Zero W had problems which made it unreliable for polling the PH sensor.</p>
<p>AtlasScientific provides some great <a href="https://www.atlas-scientific.com/_files/_datasheets/_circuit/pH_EZO_Datasheet.pdf">data sheets</a> which outlines exactly how the sensor functions, and how to obtain data via UARt and I²C as well as how to calibrate the sensor.</p>
<p>AtlasScientific also provides some code <a href="https://www.atlas-scientific.com/_files/code/pi_sample_code.pdf">tutorials / samples</a> which can be useful to get things going with setup and data polling.</p>
<p>The breadboard setup that was used for prototyping the circuit:</p>
<p><img src="https://undiluted.org/content/images/2019/11/ph_breadboard.png" alt="Breadboard Circuit Prototype"></p>
<p>The schematic looks like this:</p>
<p><img src="https://undiluted.org/content/images/2019/11/ph-sensor-project_schem.png" alt="Schematic"></p>
<p>The <a href="https://undiluted.org/c-software-to-store-ph-data/">next step</a> was to pull the data from the sensor.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[JSON Parsing in Bash]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>About a month ago, I needed to parse <a href="https://www.json.org/">JSON</a> from in <a href="https://www.gnu.org/software/bash/">Bash</a> scripts.</p>
<p>This was an interesting problem/challenge, enter <a href="https://stedolan.github.io/jq/">./jq</a>.</p>
<p><a href="https://stedolan.github.io/jq/">jq</a> is a sed like tool for JSON data, that can be used to parse JSON, from the command line, and from within <a href="https://www.gnu.org/software/bash/">Bash</a> scripts.</p>
<p><a href="https://stedolan.github.io/jq/">jq</a> is written in</p>]]></description><link>https://undiluted.org/json-parsing-in-bash/</link><guid isPermaLink="false">5d79a11ce6aa895bbcffceb5</guid><category><![CDATA[JSON]]></category><category><![CDATA[BASH]]></category><category><![CDATA[parsing]]></category><category><![CDATA[cli]]></category><category><![CDATA[linux]]></category><dc:creator><![CDATA[Nicolas Gosselin]]></dc:creator><pubDate>Sun, 15 Sep 2019 00:01:49 GMT</pubDate><media:content url="https://undiluted.org/content/images/2019/09/json-document.jpg" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="https://undiluted.org/content/images/2019/09/json-document.jpg" alt="JSON Parsing in Bash"><p>About a month ago, I needed to parse <a href="https://www.json.org/">JSON</a> from in <a href="https://www.gnu.org/software/bash/">Bash</a> scripts.</p>
<p>This was an interesting problem/challenge, enter <a href="https://stedolan.github.io/jq/">./jq</a>.</p>
<p><a href="https://stedolan.github.io/jq/">jq</a> is a sed like tool for JSON data, that can be used to parse JSON, from the command line, and from within <a href="https://www.gnu.org/software/bash/">Bash</a> scripts.</p>
<p><a href="https://stedolan.github.io/jq/">jq</a> is written in C, and is a single binary, that has zero runtime dependencies, meaning that you can simply download the binary and get parsing!</p>
<p>Some simple examples:</p>
<p>Lets say we have the following JSON payload:</p>
<pre><code>sample.json:

[
  {
    &quot;rank&quot;: 1,
    &quot;description&quot;: &quot;Great Search Engine&quot;,
    &quot;url&quot;: &quot;https://google.com&quot;
  },
  {
    &quot;rank&quot;: 2,
    &quot;description&quot;: &quot;Oldie but goodie&quot;,
  	 &quot;url&quot;: &quot;https://www.yahoo.com&quot;
  }
]
</code></pre>
<p>If we wanted to print out the JSON payload in a colorized output, we could do:</p>
<pre><code>cat sample.json | jq

</code></pre>
<p>The output would be:</p>
<p><img src="https://undiluted.org/content/images/2019/09/json-pretty-print.png" alt="JSON Parsing in Bash"></p>
<p>Lets say we wanted just the URLs:</p>
<pre><code>cat sample.json | jq .[].url
</code></pre>
<p>The output would be:</p>
<p><img src="https://undiluted.org/content/images/2019/09/json-just-urls.png" alt="JSON Parsing in Bash"></p>
<p>If we wanted just the first URL:</p>
<pre><code>cat sample.json | jq .[0].url
</code></pre>
<p>This would ouput:</p>
<p><img src="https://undiluted.org/content/images/2019/09/json-just-first-url.png" alt="JSON Parsing in Bash"></p>
<p>The URLs followed by the Ranks:</p>
<pre><code>cat sample.json | jq '.[] | .url,.rank'
</code></pre>
<p>This would output:</p>
<p><img src="https://undiluted.org/content/images/2019/09/json-urls-ranks.png" alt="JSON Parsing in Bash"></p>
<p>Lets do something a little more complex, lets say we want to add <em><strong>1</strong></em> to every rank:</p>
<pre><code>cat sample.json | jq '.[].rank +1'
</code></pre>
<p>This would output:</p>
<p><img src="https://undiluted.org/content/images/2019/09/json-rank-arithmetic.png" alt="JSON Parsing in Bash"></p>
<p>The above are just simple examples, <a href="https://stedolan.github.io/jq/">jq</a> is very powerful, and can do much more!</p>
<p>I recommend checking out the <a href="https://stedolan.github.io/jq/">jq/</a> github page to get more information on this great tool.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[REST API Boilerplate (Node.js + Express)]]></title><description><![CDATA[<!--kg-card-begin: image--><figure class="kg-card kg-image-card"><img src="https://undiluted.org/content/images/2019/08/Node.js_logo-3.svg" class="kg-image"></figure><!--kg-card-end: image--><!--kg-card-begin: hr--><hr><!--kg-card-end: hr--><!--kg-card-begin: markdown--><p>A few years ago, I was working with a <a href="https://www.raspberrypi.org">Raspberry Pi</a> with a Z-Wave adapter to talk to z-wave enabled devices, such as switches, dimmers, and door locks.</p>
<p>I needed a method of keeping track and manipulating user account details, which seemed like the perfect time for me to create</p>]]></description><link>https://undiluted.org/rest-api-node-js-express/</link><guid isPermaLink="false">5d59d15f0d00372ec5997a71</guid><category><![CDATA[node.js]]></category><category><![CDATA[expressjs]]></category><category><![CDATA[javascript]]></category><dc:creator><![CDATA[Nicolas Gosselin]]></dc:creator><pubDate>Mon, 19 Aug 2019 01:33:55 GMT</pubDate><media:content url="https://undiluted.org/content/images/2019/08/Node.js_logo-4.svg" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: image--><figure class="kg-card kg-image-card"><img src="https://undiluted.org/content/images/2019/08/Node.js_logo-3.svg" class="kg-image" alt="REST API Boilerplate (Node.js + Express)"></figure><!--kg-card-end: image--><!--kg-card-begin: hr--><hr><!--kg-card-end: hr--><!--kg-card-begin: markdown--><img src="https://undiluted.org/content/images/2019/08/Node.js_logo-4.svg" alt="REST API Boilerplate (Node.js + Express)"><p>A few years ago, I was working with a <a href="https://www.raspberrypi.org">Raspberry Pi</a> with a Z-Wave adapter to talk to z-wave enabled devices, such as switches, dimmers, and door locks.</p>
<p>I needed a method of keeping track and manipulating user account details, which seemed like the perfect time for me to create something using <a href="https://nodejs.com">Node.js</a> + <a href="https://expressjs.org">Express</a>.</p>
<p>As REST APIs are a useful and popular type of APIs, I thought I would design a boilerplate that could be re-used to quickly build REST APIs with <a href="https://nodejs.com">Node.js</a> + <a href="https://expressjs.org">Express</a>.</p>
<!--kg-card-end: markdown--><!--kg-card-begin: hr--><hr><!--kg-card-end: hr--><!--kg-card-begin: markdown--><p>This REST API boilerplate is available in my <a href="https://gitlab.com/ngosselin/rest-skeleton">Gitlab repo.</a></p>
<p>Below I will go through the basics of how the boilerplate works, and how it can be used.</p>
<p>The overall idea behind the skeleton was to be very close in nature with how<br>
<a href="https://rubyonrails.org">Ruby on Rails</a> APIs are layed out.</p>
<!--kg-card-end: markdown--><!--kg-card-begin: markdown--><p>In the root directory of the repository there is a file called route.json, which is a JSON hash that defines the routes for the API which live in the src/resources/ directory.</p>
<p>As an example the default routes.json file contains the following:</p>
<pre><code class="language-json">&quot;v1/account&quot;: {
  &quot;routes&quot;: [
    &quot;/v1/accounts/:id&quot;,
    &quot;/v1/accounts&quot;
  ]
},
&quot;v2/account&quot;: {
  &quot;routes&quot;: [
    &quot;/v2/accounts/:id&quot;,
    &quot;/v2/accounts&quot;
  ]
}
</code></pre>
<p>The above, maps out both:</p>
<pre><code>/v1/accounts/:id
/v1/accounts
</code></pre>
<p>to the <code>v1/account/</code> resource in <code>src/api/resources/v1/account.js</code> (it also maps out a version 2 of a similar API)</p>
<p><code>src/api/resources/v1/account.js</code>, has a method per HTTP verb (GET, POST, PUT, DELETE), the breakdown of these methods are:</p>
<ul>
<li>index() - GET</li>
<li>create() - POST</li>
<li>update() - PUT</li>
<li>destroy() - DELETE</li>
</ul>
<p>To handle versioning of the API, each resource in <code>src/api/resources/&lt;version&gt;/</code> extends an appropriate resource labeled v1.js, v2.js etc.</p>
<p>This particular resource, sets specific things that are related to the particular version, such as a response header: api-version, which tells the caller which version of the API is being used.</p>
<p>The API skeleton includes integration/behavior tests (mocha + chai + chai-http) which live in the test/ directory and can be run using:</p>
<pre><code>npm run test
</code></pre>
<p>To run the build process for the API skeleton:</p>
<pre><code>npm run build
</code></pre>
<p>To run the API skeleton locally:</p>
<pre><code>npm run start
</code></pre>
<!--kg-card-end: markdown-->]]></content:encoded></item></channel></rss>