<?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"><channel><title><![CDATA[Jeremiah John Boateng's Blog]]></title><description><![CDATA[Web developer | IoT Enthusiast]]></description><link>https://blog.jjbofficial.com</link><generator>RSS for Node</generator><lastBuildDate>Wed, 15 Apr 2026 16:04:27 GMT</lastBuildDate><atom:link href="https://blog.jjbofficial.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Set Up SonarQube Community Build using Docker Compose]]></title><description><![CDATA[SonarQube is a code quality tool that helps ensure your team adheres to best practices and can catch bugs before merging into production. It allows you to define rules checked anytime SonarQube is run on your code base. This helps reduce friction dur...]]></description><link>https://blog.jjbofficial.com/set-up-sonarqube-community-build-using-docker-compose</link><guid isPermaLink="true">https://blog.jjbofficial.com/set-up-sonarqube-community-build-using-docker-compose</guid><category><![CDATA[Devops]]></category><category><![CDATA[codequality]]></category><category><![CDATA[Docker]]></category><category><![CDATA[Docker compose]]></category><dc:creator><![CDATA[Jeremiah John Boateng]]></dc:creator><pubDate>Thu, 10 Apr 2025 16:33:53 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/JKUTrJ4vK00/upload/b2e78f1c7a749253043dd4efea1b1403.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><a target="_blank" href="https://sonarqube.com">SonarQube</a> is a code quality tool that helps ensure your team adheres to best practices and can catch bugs before merging into production. It allows you to define rules checked anytime SonarQube is run on your code base. This helps reduce friction during code reviews because the rules for what defines 'good code' in your team are predefined and not subject to one person's opinion. Although Sonarqube is a paid tool, it provides a free community version you can install on your server.</p>
<p>SonarQube can be installed in multiple ways. I prefer Docker Compose because it allows you to run multiple containers easily. It uses Docker, so there is no need to install and maintain versions of packages/libraries. Below is a sample <code>docker-compose.yaml</code></p>
<pre><code class="lang-yaml"><span class="hljs-attr">services:</span>
  <span class="hljs-attr">sonarqube:</span>
    <span class="hljs-attr">image:</span> <span class="hljs-string">sonarqube:community</span>
    <span class="hljs-attr">read_only:</span> <span class="hljs-literal">true</span>
    <span class="hljs-attr">volumes:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">sonarqube_data:/opt/sonarqube/data</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">sonarqube_extensions:/opt/sonarqube/extensions</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">sonarqube_logs:/opt/sonarqube/logs</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">sonarqube_temp:/opt/sonarqube/temp</span>
    <span class="hljs-attr">ports:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">"9000:9000"</span>
    <span class="hljs-attr">networks:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">sonar-network</span>
    <span class="hljs-attr">environment:</span>
      <span class="hljs-attr">SONAR_JDBC_URL:</span> <span class="hljs-string">jdbc:{database-url}</span>  
      <span class="hljs-attr">SONAR_JDBC_USERNAME:</span> <span class="hljs-string">XXXXXXXXXX</span>
      <span class="hljs-attr">SONAR_JDBC_PASSWORD:</span> <span class="hljs-string">"XXXXXXXX"</span>
      <span class="hljs-attr">SONAR_WEB_PORT:</span> <span class="hljs-number">9000</span>
      <span class="hljs-attr">SONAR_AUTH_JWTBASE64HS256SECRET:</span> <span class="hljs-string">"XXXXXXXXXXXXXXXXXXXXX"</span>
      <span class="hljs-attr">VIRTUAL_HOST:</span> <span class="hljs-string">sonarqube.yourdomain.com</span>
      <span class="hljs-attr">VIRTUAL_PORT:</span> <span class="hljs-number">9000</span>
      <span class="hljs-attr">LETSENCRYPT_HOST:</span> <span class="hljs-string">sonarqube.yourdomain.com</span>

  <span class="hljs-attr">proxy:</span>
    <span class="hljs-attr">image:</span> <span class="hljs-string">nginxproxy/nginx-proxy:1.6</span>
    <span class="hljs-attr">ports:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">"80:80"</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">"443:443"</span>
    <span class="hljs-attr">volumes:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">/var/run/docker.sock:/tmp/docker.sock:ro</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">certs:/etc/nginx/certs:ro</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">html:/usr/share/nginx/html</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">conf:/etc/nginx/conf.d</span>
    <span class="hljs-attr">environment:</span>
      <span class="hljs-attr">VIRTUAL_HOST:</span> <span class="hljs-string">sonarqube.yourdomain.com</span>
      <span class="hljs-attr">VIRTUAL_PORT:</span> <span class="hljs-number">9000</span>
    <span class="hljs-attr">networks:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">sonar-network</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">sonar-public</span>

  <span class="hljs-attr">acme-companion:</span>
    <span class="hljs-attr">image:</span> <span class="hljs-string">nginxproxy/acme-companion</span>
    <span class="hljs-attr">container_name:</span> <span class="hljs-string">nginx-proxy-acme</span>
    <span class="hljs-attr">environment:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">DEFAULT_EMAIL=dev@yourdomain.co</span>
    <span class="hljs-attr">volumes_from:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">proxy</span>
    <span class="hljs-attr">volumes:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">certs:/etc/nginx/certs:rw</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">acme:/etc/acme.sh</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">/var/run/docker.sock:/var/run/docker.sock:ro</span>
    <span class="hljs-attr">networks:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">sonar-public</span>

<span class="hljs-attr">volumes:</span>
  <span class="hljs-attr">sonarqube_data:</span>
  <span class="hljs-attr">sonarqube_extensions:</span>
  <span class="hljs-attr">sonarqube_logs:</span>
  <span class="hljs-attr">sonarqube_temp:</span>
  <span class="hljs-attr">certs:</span>
  <span class="hljs-attr">html:</span>
  <span class="hljs-attr">conf:</span>
  <span class="hljs-attr">acme:</span>

<span class="hljs-attr">networks:</span>
  <span class="hljs-attr">sonar-network:</span>
    <span class="hljs-attr">ipam:</span>
      <span class="hljs-attr">driver:</span> <span class="hljs-string">default</span>
      <span class="hljs-attr">config:</span>
        <span class="hljs-bullet">-</span> <span class="hljs-attr">subnet:</span> <span class="hljs-number">172.28</span><span class="hljs-number">.2</span><span class="hljs-number">.0</span><span class="hljs-string">/24</span>
  <span class="hljs-attr">sonar-public:</span>
    <span class="hljs-attr">driver:</span> <span class="hljs-string">bridge</span>
</code></pre>
<p>This configuration uses an external database (such as GCP Cloud SQL or AWS RDS) and allows you to access SonarQube using HTTPS. The <code>acme-companion</code> service handles auto-renewal of the SSL certificates using Let's Encrypt.</p>
]]></content:encoded></item><item><title><![CDATA[Connecting a Laravel application to AWS IoT Core over MQTT - Part 2]]></title><description><![CDATA[In Part 1, we created a device policy and a thing on AWS IoT core. In this article, we will use the downloaded certificates to connect to the MQTT broker to publish messages and subscribe to topics. We will use the PHP-MQTT library.
AWS IoT core uses...]]></description><link>https://blog.jjbofficial.com/connecting-a-laravel-application-to-aws-iot-core-over-mqtt-part-2</link><guid isPermaLink="true">https://blog.jjbofficial.com/connecting-a-laravel-application-to-aws-iot-core-over-mqtt-part-2</guid><category><![CDATA[Laravel]]></category><category><![CDATA[AWS]]></category><category><![CDATA[aws iot core]]></category><category><![CDATA[mqtt]]></category><dc:creator><![CDATA[Jeremiah John Boateng]]></dc:creator><pubDate>Sun, 07 Apr 2024 22:08:14 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/M5tzZtFCOfs/upload/ee39372e0ab289784ba8dd44f557636b.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In <a target="_blank" href="https://blog.jjbofficial.com/connecting-a-laravel-application-to-aws-iot-core-over-mqtt-part-1">Part 1</a>, we created a device policy and a thing on AWS IoT core. In this article, we will use the downloaded certificates to connect to the MQTT broker to publish messages and subscribe to topics. We will use the <a target="_blank" href="https://github.com/php-mqtt/laravel-client">PHP-MQTT</a> library.</p>
<p>AWS IoT core uses MQTT over TLS. This ensures encrypted data is sent between your devices or applications and the cloud. We need to use the certificates to establish the TLS connection. If you look in the <a target="_blank" href="https://github.com/php-mqtt/laravel-client/blob/54b2fc0cf3aedfb9ddf50429ece670ee7343bd37/config/mqtt-client.php#L70C17-L81C19">config file</a> of the library, you will find the following lines</p>
<pre><code class="lang-php"><span class="hljs-comment">// The TLS settings used for the connection. Must match the specified port.</span>
<span class="hljs-string">'tls'</span> =&gt; [
    <span class="hljs-string">'enabled'</span> =&gt; env(<span class="hljs-string">'MQTT_TLS_ENABLED'</span>, <span class="hljs-literal">false</span>),
    <span class="hljs-string">'allow_self_signed_certificate'</span> =&gt; env(<span class="hljs-string">'MQTT_TLS_ALLOW_SELF_SIGNED_CERT'</span>, <span class="hljs-literal">false</span>),
    <span class="hljs-string">'verify_peer'</span> =&gt; env(<span class="hljs-string">'MQTT_TLS_VERIFY_PEER'</span>, <span class="hljs-literal">true</span>),
    <span class="hljs-string">'verify_peer_name'</span> =&gt; env(<span class="hljs-string">'MQTT_TLS_VERIFY_PEER_NAME'</span>, <span class="hljs-literal">true</span>),
    <span class="hljs-string">'ca_file'</span> =&gt; env(<span class="hljs-string">'MQTT_TLS_CA_FILE'</span>),
    <span class="hljs-string">'ca_path'</span> =&gt; env(<span class="hljs-string">'MQTT_TLS_CA_PATH'</span>),
    <span class="hljs-string">'client_certificate_file'</span> =&gt; env(<span class="hljs-string">'MQTT_TLS_CLIENT_CERT_FILE'</span>),
    <span class="hljs-string">'client_certificate_key_file'</span> =&gt; env(<span class="hljs-string">'MQTT_TLS_CLIENT_CERT_KEY_FILE'</span>),
    <span class="hljs-string">'client_certificate_key_passphrase'</span> =&gt; env(<span class="hljs-string">'MQTT_TLS_CLIENT_CERT_KEY_PASSPHRASE'</span>),
],
</code></pre>
<p>We must provide the path to the certificates so the library can use them when connecting to the cloud. The certificates should be stored in a directory where your application has read access. Also, do not commit the certificates to your repository as it can pose a security risk. You should upload them to the server manually or add a step to your CI to upload the certificates to your servers. Add the following lines to your <strong>.env</strong> file.</p>
<pre><code class="lang-bash">MQTT_TLS_ENABLED=<span class="hljs-literal">true</span>
MQTT_TLS_CA_FILE=/path-to/AmazonRootCA1.pem 
MQTT_TLS_CLIENT_CERT_FILE=/path-to/device_monitor.pem.crt
MQTT_TLS_CLIENT_CERT_KEY_FILE=/path-to/device_monitor-private.pem.key
</code></pre>
<p>We also need to know the host and the port of the MQTT broker. Navigate to <strong>AWS IoT &gt; Settings</strong> page to find the MQTT host for your account.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712326228599/493a751d-6a72-4ce3-9ce9-3e5b46fe9554.png" alt class="image--center mx-auto" /></p>
<p>There are multiple ways to connect to IoT Core as shown in the table below. Since we are using X.509 client certificate and MQTT, we will use port <strong>8883</strong></p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Protocol</strong></td><td><strong>Operations supported</strong></td><td><strong>Authentication</strong></td><td><strong>Port</strong></td><td><strong>ALPN protocol name</strong></td></tr>
</thead>
<tbody>
<tr>
<td>MQTT over WebSocket</td><td>Publish, Subscribe</td><td>Signature Version 4</td><td>443</td><td>N/A</td></tr>
<tr>
<td>MQTT over WebSocket</td><td>Publish, Subscribe</td><td>Custom authentication</td><td>443</td><td>N/A</td></tr>
<tr>
<td>MQTT</td><td>Publish, Subscribe</td><td>X.509 client certificate</td><td>443<sup>†</sup></td><td><code>x-amzn-mqtt-ca</code></td></tr>
<tr>
<td>MQTT</td><td>Publish, Subscribe</td><td>X.509 client certificate</td><td>8883</td><td>N/A</td></tr>
<tr>
<td>MQTT</td><td>Publish, Subscribe</td><td>Custom authentication</td><td>443<sup>†</sup></td><td><code>mqtt</code></td></tr>
<tr>
<td>HTTPS</td><td>Publish only</td><td>Signature Version 4</td><td>443</td><td>N/A</td></tr>
<tr>
<td>HTTPS</td><td>Publish only</td><td>X.509 client certificate</td><td>443<sup>†</sup></td><td><code>x-amzn-http-ca</code></td></tr>
<tr>
<td>HTTPS</td><td>Publish only</td><td>X.509 client certificate</td><td>8443</td><td>N/A</td></tr>
<tr>
<td>HTTPS</td><td>Publish only</td><td>Custom authentication</td><td>443</td><td>N/A</td></tr>
</tbody>
</table>
</div><p>The table was taken from <a target="_blank" href="https://docs.aws.amazon.com/iot/latest/developerguide/protocols.html">https://docs.aws.amazon.com/iot/latest/developerguide/protocols.html</a></p>
<p>We also specified in the device policy that the client ID should be the same as the thing name. The following lines should be added to the <strong>.env</strong> file</p>
<pre><code class="lang-bash">MQTT_HOST=xxxxxxxxxxxxxxxxxxxxx.amazonaws.com
MQTT_PORT=8883
MQTT_CLIENT_ID=device_monitor
</code></pre>
<h2 id="heading-subscribing-to-a-topic">Subscribing to a topic</h2>
<p>We can use the code from my <a target="_blank" href="https://blog.jjbofficial.com/integrating-mqtt-into-a-laravel-project">previous article</a> to subscribe to a topic. We can only subscribe to topics that were defined in the policy. IoT core will close the connection if we attempt to subscribe to topics, not in the device policy.</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-keyword">namespace</span> <span class="hljs-title">App</span>\<span class="hljs-title">Console</span>\<span class="hljs-title">Commands</span>;

<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Console</span>\<span class="hljs-title">Command</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">PhpMqtt</span>\<span class="hljs-title">Client</span>\<span class="hljs-title">Facades</span>\<span class="hljs-title">MQTT</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SubscribeToTopic</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Command</span>
</span>{
    <span class="hljs-comment">/**
     * The name and signature of the console command.
     *
     * <span class="hljs-doctag">@var</span> string
     */</span>
    <span class="hljs-keyword">protected</span> $signature = <span class="hljs-string">'mqtt:subscribe'</span>;

    <span class="hljs-comment">/**
     * The console command description.
     *
     * <span class="hljs-doctag">@var</span> string
     */</span>
    <span class="hljs-keyword">protected</span> $description = <span class="hljs-string">'Subscribe To MQTT topic'</span>;

    <span class="hljs-comment">/**
     * Execute the console command.
     *
     * <span class="hljs-doctag">@return</span> int
     */</span>
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handle</span>(<span class="hljs-params"></span>)
    </span>{
        $mqtt = MQTT::connection();
        $mqtt-&gt;subscribe(<span class="hljs-string">'devices/+/status'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> $topic, <span class="hljs-keyword">string</span> $message</span>) </span>{
            <span class="hljs-keyword">echo</span> sprintf(<span class="hljs-string">'Received message on topic [%s]: %s'</span>,$topic, $message);
        });

        $mqtt-&gt;loop(<span class="hljs-literal">true</span>);
        <span class="hljs-keyword">return</span> Command::SUCCESS;
    }
}
</code></pre>
<p>Run the <code>php artisan mqtt:subscribe</code> command in your terminal then, navigate to <strong>AWS IoT &gt; MQTT test client</strong> and click on the <code>Publish to a topic</code> tab. Use <code>devices/001/status</code> for the topic, enter any message you want as the payload and click the publish button.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712328118763/5868ae6c-cd2b-4124-a07d-2c4e418e62f9.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712328097792/199fa454-b652-453f-b8c3-0757f7af7d3b.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-publishing-a-message">Publishing a message</h2>
<p>Let's create a command to query the devices for their status</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-keyword">namespace</span> <span class="hljs-title">App</span>\<span class="hljs-title">Console</span>\<span class="hljs-title">Commands</span>;

<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Console</span>\<span class="hljs-title">Command</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">PhpMqtt</span>\<span class="hljs-title">Client</span>\<span class="hljs-title">Facades</span>\<span class="hljs-title">MQTT</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">QueryStatus</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Command</span>
</span>{
    <span class="hljs-comment">/**
     * The name and signature of the console command.
     *
     * <span class="hljs-doctag">@var</span> string
     */</span>
    <span class="hljs-keyword">protected</span> $signature = <span class="hljs-string">'mqtt:query-status'</span>;

    <span class="hljs-comment">/**
     * The console command description.
     *
     * <span class="hljs-doctag">@var</span> string
     */</span>
    <span class="hljs-keyword">protected</span> $description = <span class="hljs-string">'Query device status'</span>;

    <span class="hljs-comment">/**
     * Execute the console command.
     */</span>
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handle</span>(<span class="hljs-params"></span>)
    </span>{
        $command = [
            <span class="hljs-string">'cmd'</span> =&gt; <span class="hljs-string">'status'</span>
        ];

        $mqtt = MQTT::connection();

        $mqtt-&gt;publish(
            <span class="hljs-string">'devices/002/query'</span>,
            json_encode($command)
        );
    }
}
</code></pre>
<p>To test this, navigate to <strong>AWS IoT &gt; MQTT test client</strong> and click the <code>Subscribe to a topic</code> tab. Subscribe to the topic <code>devices/+/query</code> and run <code>php artisan mqtt:query-status</code> in your terminal.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712328685867/c1ad1256-dacd-4a04-b876-ee5c3e25af26.png" alt class="image--center mx-auto" /></p>
<p>Note that, publishing to a topic not in the policy will cause IoT core to terminate the connection.</p>
]]></content:encoded></item><item><title><![CDATA[Connecting a Laravel application to AWS IoT Core over MQTT - Part 1]]></title><description><![CDATA[AWS IoT core provides a suite of features that makes connecting IoT devices to the cloud and managing them a breeze. An MQTT broker is one of the services offered by AWS IoT Core. In this 2-part series, I will go over creating an IoT device or thing ...]]></description><link>https://blog.jjbofficial.com/connecting-a-laravel-application-to-aws-iot-core-over-mqtt-part-1</link><guid isPermaLink="true">https://blog.jjbofficial.com/connecting-a-laravel-application-to-aws-iot-core-over-mqtt-part-1</guid><category><![CDATA[Laravel]]></category><category><![CDATA[AWS]]></category><category><![CDATA[iot]]></category><category><![CDATA[aws iot core]]></category><dc:creator><![CDATA[Jeremiah John Boateng]]></dc:creator><pubDate>Sat, 17 Feb 2024 19:18:49 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/M5tzZtFCOfs/upload/c28ee55afdcec81baed6d3fa0a2b7157.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>AWS IoT core provides a suite of features that makes connecting IoT devices to the cloud and managing them a breeze. An MQTT broker is one of the services offered by AWS IoT Core. In this 2-part series, I will go over creating an IoT device or <code>thing</code> in AWS parlance on IoT core and how a Laravel application can connect to IoT core to publish and receive messages.</p>
<p>Unlike other MQTT brokers such as Mosquitto, IoT Core requires that you define the topics that devices would be allowed to subscribe, publish messages to and receive data from. This is called a <code>policy</code>. A policy is associated with a thing and gives it the permissions defined in the policy document. We will use two topics in our policy. A topic to send commands to the device and another to receive data from the device.</p>
<p>One thing to note is that the AWS IoT core has a different notation when specifying wildcards in your MQTT topic. You can read more about this <a target="_blank" href="https://docs.aws.amazon.com/iot/latest/developerguide/pub-sub-policy.html#pub-sub-policy-cert">here</a>. To summarise, you should use <strong>*</strong> and <strong>?</strong> for wildcards instead of <strong>+</strong> and <strong>#.</strong></p>
<p>Before connecting to IoT Core over MQTT, we must create a policy and a <code>thing</code>.</p>
<h2 id="heading-create-a-policy">Create a policy</h2>
<ol>
<li>Log in to your AWS console and search for IoT Core in the search bar at the top right.</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1708178778717/c53fc6bd-0712-4aae-adc6-10fdf6151fd0.png" alt class="image--center mx-auto" /></p>
<ol>
<li>Navigate to <strong>Manage &gt; Security &gt; Policies</strong> and click the <strong>Create Policy</strong> button.</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1708182329258/08ab8579-b2ef-40e0-81cc-e5738eb8676f.png" alt class="image--center mx-auto" /></p>
<ol>
<li><p>Give your policy a name. I will be using <strong>DevicePolicy</strong>. In the policy statement section below, select the JSON view and paste the JSON below into the text box.</p>
<pre><code class="lang-json"> {
   <span class="hljs-attr">"Version"</span>: <span class="hljs-string">"2012-10-17"</span>,
   <span class="hljs-attr">"Statement"</span>: [
     {
       <span class="hljs-attr">"Effect"</span>: <span class="hljs-string">"Allow"</span>,
       <span class="hljs-attr">"Action"</span>: <span class="hljs-string">"iot:Connect"</span>,
       <span class="hljs-attr">"Resource"</span>: <span class="hljs-string">"arn:aws:iot:us-east-1:*:client/${iot:Connection.Thing.ThingName}"</span>
     },
     {
       <span class="hljs-attr">"Effect"</span>: <span class="hljs-string">"Allow"</span>,
       <span class="hljs-attr">"Action"</span>: <span class="hljs-string">"iot:Subscribe"</span>,
       <span class="hljs-attr">"Resource"</span>: <span class="hljs-string">"arn:aws:iot:us-east-1:*:topicfilter/devices/*/status"</span>
     },
     {
       <span class="hljs-attr">"Effect"</span>: <span class="hljs-string">"Allow"</span>,
       <span class="hljs-attr">"Action"</span>: <span class="hljs-string">"iot:Publish"</span>,
       <span class="hljs-attr">"Resource"</span>: <span class="hljs-string">"arn:aws:iot:us-east-1:*:topic/devices/*/query"</span>
     },
     {
       <span class="hljs-attr">"Effect"</span>: <span class="hljs-string">"Allow"</span>,
       <span class="hljs-attr">"Action"</span>: <span class="hljs-string">"iot:Receive"</span>,
       <span class="hljs-attr">"Resource"</span>: <span class="hljs-string">"arn:aws:iot:us-east-1:*:topic/devices/*/status"</span>
     }
   ]
 }
</code></pre>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1708182803569/7220f56d-1929-42f1-8d51-6e5e9007283c.png" alt class="image--center mx-auto" /></p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1708185625224/4338a6c6-9942-4f3c-ba8b-a5c8b6660e05.png" alt class="image--center mx-auto" /></p>
<p> The <code>iot:Connect</code> action allows devices to connect to the MQTT broker. Two devices with the same client ID cannot connect to the broker simultaneously. The variable <code>iot:Connection.Thing.ThingName</code> is a placeholder for the client ID. You must use the thing name when connecting to the MQTT broker. You can find a breakdown of all the IoT core policy actions <a target="_blank" href="https://docs.aws.amazon.com/iot/latest/developerguide/iot-policy-actions.html">here</a> and example policies <a target="_blank" href="https://docs.aws.amazon.com/iot/latest/developerguide/example-iot-policies.html">here</a>.</p>
</li>
<li><p>Click on the <strong>Create</strong> button on your bottom left to save the policy.</p>
</li>
</ol>
<blockquote>
<p>If you ever encounter the error <strong>The action failed because the input is not valid. Policy cannot be created - size exceeds hard limit (2048),</strong> which means you have too many topics. You have to consolidate some of your topics into one or create an extra policy to handle some of your topics.</p>
</blockquote>
<h2 id="heading-create-a-thing">Create a thing</h2>
<ol>
<li><p>Navigate to <strong>Manage &gt; All Devices &gt; Things</strong> and click the <strong>Create Things</strong> button.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1708183080860/9e6b4e9b-5a27-4e7b-98d6-385e2befcdc6.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>Select <strong>Create Single Thing</strong> and click on the <strong>Next</strong> button.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1708183161548/ebb477cf-1358-466b-b2a3-db859995967d.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>Give the thing a name. I will be using <strong>device_monitor</strong>. Then, scroll down and click on the <strong>Next</strong> button.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1708183633597/a1ff47c4-c300-464e-98de-0cb15e2c7017.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>Select <strong>Auto-generate a new certificate</strong> and click on the <strong>Next</strong> button.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1708183657645/2c7c1e50-db41-4d45-8e66-72adb9915806.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>Select <strong>DevicePolicy</strong> from the list of policies and click on the <strong>Create Thing</strong> button.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1708183770731/2c5cbf9a-6d61-4abe-846e-e80b88833327.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>Download the device certificate, public key, private key, and the Amazon Root Certificate CA 1</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1708184035782/ce1d20f9-c0cf-4cab-a54d-1eea34fe4b69.png" alt class="image--center mx-auto" /></p>
<p> You must download the device certificates at this step. You will not be able to download them after you close the pop-up.</p>
</li>
</ol>
<p>In Part 2, I go over how to use the device certificates to connect a laravel application to AWS IoT core over MQTT.</p>
]]></content:encoded></item><item><title><![CDATA[Hardware Debuggers Save Time]]></title><description><![CDATA[My entry into embedded systems like most other people started with an Arduino Uno. The UNO didn't have a hardware debugger on board so If I made a mistake, I had to place well-structured Serial.println statements throughout my code so that I could fo...]]></description><link>https://blog.jjbofficial.com/hardware-debuggers-save-time</link><guid isPermaLink="true">https://blog.jjbofficial.com/hardware-debuggers-save-time</guid><category><![CDATA[embedded systems]]></category><category><![CDATA[Ghana]]></category><category><![CDATA[iot]]></category><category><![CDATA[Electronics]]></category><dc:creator><![CDATA[Jeremiah John Boateng]]></dc:creator><pubDate>Tue, 23 May 2023 11:47:11 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/tTugjw8f4Ms/upload/8f1734307ae3dafd43be02e8866f357d.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>My entry into embedded systems like most other people started with an Arduino Uno. The UNO didn't have a hardware debugger on board so If I made a mistake, I had to place well-structured <code>Serial.println</code> statements throughout my code so that I could follow the logic and find out where things went wrong. Anyone who has done this enough times knows how frustrating it can be and I knew at the back of my mind that there definitely had to be a better way.</p>
<p>When I started programming STM32 microcontrollers, I got introduced to using a hardware debugger and the experience was surreal. The ability to step through my code line-by-line and see the values of registers and variables change in real-time made debugging a better experience. Most microcontroller platforms have some kind of hardware debugger that you can use. ESP32s have <a target="_blank" href="https://espressif-docs.readthedocs-hosted.com/projects/espressif-esp-iot-solution/en/latest/hw-reference/ESP-Prog_guide.html">ESP-PROG</a>, and STM32s have <a target="_blank" href="https://www.youtube.com/watch?v=wt8uwz7eJDE">ST-LINK</a>. If you have never tried using a hardware debugger before, I encourage you to treat yourself.</p>
<p>If you don't know where to get these programmers, you can read my previous article on <a target="_blank" href="https://blog.jjbofficial.com/getting-electronic-components-for-your-next-project-in-ghana">how I source components in Ghana</a></p>
]]></content:encoded></item><item><title><![CDATA[Integrating MQTT into a Laravel project]]></title><description><![CDATA[Recently, I have been experimenting with MQTT, a lightweight messaging protocol that is designed to provide efficient, reliable, and real-time communication between devices and applications in machine-to-machine (M2M) and Internet of Things (IoT) con...]]></description><link>https://blog.jjbofficial.com/integrating-mqtt-into-a-laravel-project</link><guid isPermaLink="true">https://blog.jjbofficial.com/integrating-mqtt-into-a-laravel-project</guid><category><![CDATA[iot]]></category><category><![CDATA[embedded systems]]></category><category><![CDATA[mqtt]]></category><category><![CDATA[Laravel]]></category><dc:creator><![CDATA[Jeremiah John Boateng]]></dc:creator><pubDate>Fri, 10 Mar 2023 17:50:50 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/sPLLVFJXlb8/upload/8e5969c898705d012ddc3430beb266c4.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Recently, I have been experimenting with <a target="_blank" href="https://www.hivemq.com/mqtt-essentials/">MQTT</a>, a lightweight messaging protocol that is designed to provide efficient, reliable, and real-time communication between devices and applications in machine-to-machine (M2M) and Internet of Things (IoT) contexts. It's a popular communication protocol used by IoT devices. For the project I am working on, I plan to send data from my device to an MQTT broker and have a web application subscribe to a topic to get data the device is publishing.</p>
<p>I installed <a target="_blank" href="https://mosquitto.org/">Mosquitto</a>, a popular MQTT broker and <a target="_blank" href="https://mqttx.app/">MQTTX</a>, an easy-to-use GUI MQTT client. I found a PHP library called <a target="_blank" href="https://github.com/php-mqtt/laravel-client">PHP-MQTT</a> that makes integrating MQTT into your Laravel project easy. The code I used to get data from the MQTT broker is quite simple.</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-keyword">namespace</span> <span class="hljs-title">App</span>\<span class="hljs-title">Console</span>\<span class="hljs-title">Commands</span>;

<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Console</span>\<span class="hljs-title">Command</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">PhpMqtt</span>\<span class="hljs-title">Client</span>\<span class="hljs-title">Facades</span>\<span class="hljs-title">MQTT</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SubscribeToTopic</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Command</span>
</span>{
    <span class="hljs-comment">/**
     * The name and signature of the console command.
     *
     * <span class="hljs-doctag">@var</span> string
     */</span>
    <span class="hljs-keyword">protected</span> $signature = <span class="hljs-string">'mqtt:subscribe'</span>;

    <span class="hljs-comment">/**
     * The console command description.
     *
     * <span class="hljs-doctag">@var</span> string
     */</span>
    <span class="hljs-keyword">protected</span> $description = <span class="hljs-string">'Subscribe To MQTT topic'</span>;

    <span class="hljs-comment">/**
     * Execute the console command.
     *
     * <span class="hljs-doctag">@return</span> int
     */</span>
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handle</span>(<span class="hljs-params"></span>)
    </span>{
        $mqtt = MQTT::connection();
        $mqtt-&gt;subscribe(<span class="hljs-string">'devices/+/status'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> $topic, <span class="hljs-keyword">string</span> $message</span>) </span>{
            <span class="hljs-keyword">echo</span> sprintf(<span class="hljs-string">'Received message on topic [%s]: %s'</span>,$topic, $message);
        });

        $mqtt-&gt;loop(<span class="hljs-literal">true</span>);
        <span class="hljs-keyword">return</span> Command::SUCCESS;
    }
}
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677678517367/b535f1c1-dbf0-4d37-95a8-c165e0e81b5b.png" alt="Publishing data to the MQTT Topic" class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677678567033/871ed8ed-e8e8-4f0b-a594-72de466465cd.png" alt="Data received by laravel application" class="image--center mx-auto" /></p>
<p>The code worked well locally, but I started thinking about how to run the command when deploying the project to production. My initial idea was to create a command and run it with Laravel's scheduler, but this approach did not work well.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677679090622/ec875518-b6e1-4952-b7ab-268d0e530942.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677679339694/957093ed-2735-4438-9808-366d6ded252a.png" alt class="image--center mx-auto" /></p>
<p>The issue is that the command runs an infinite loop, causing the function to never return. Consequently, the scheduler creates multiple processes, all subscribed to the same topic. The code that runs when new data is received (e.g., storing the data in a database) will be executed multiple times, with the exact number depending on the number of processes created. To solve this problem, you can use a process monitor, such as <a target="_blank" href="http://supervisord.org/">supervisor</a>, to run the command in the background and restart it if it crashes. I copied the configuration example for running the queue worker command from the <a target="_blank" href="https://laravel.com/docs/10.x/queues#configuring-supervisor">Laravel documentation</a> and edited it as follows:</p>
<pre><code class="lang-plaintext">[program:laravel-mqtt-subscriber]
process_name=%(program_name)s_%(process_num)02d
command=php /home/forge/app.com/artisan mqtt:subscribe
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
user=forge
numprocs=1
redirect_stderr=true
stdout_logfile=/home/forge/app.com/worker.log
stopwaitsecs=3600
</code></pre>
<p>The main point to note is that I changed the value of <strong><em>numprocs</em></strong> to 1 to prevent multiple processes from running the same command, which resolved the issue.</p>
]]></content:encoded></item><item><title><![CDATA[So you learnt Arduino, What next?]]></title><description><![CDATA[Like many others, I learned of Arduino very early when I was learning about embedded systems. It felt great to be able to build pretty complex projects like a remote-controlled fan without much of a more profound knowledge of electronics and the best...]]></description><link>https://blog.jjbofficial.com/you-have-learned-arduino-what-next</link><guid isPermaLink="true">https://blog.jjbofficial.com/you-have-learned-arduino-what-next</guid><category><![CDATA[embedded systems]]></category><category><![CDATA[Ghana]]></category><category><![CDATA[C++]]></category><category><![CDATA[arduino]]></category><dc:creator><![CDATA[Jeremiah John Boateng]]></dc:creator><pubDate>Sun, 22 Jan 2023 15:49:35 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/yQpAaMsQzYE/upload/6e4042a85d2805d10cbcfaaba48675bd.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Like many others, I learned of Arduino very early when I was learning about embedded systems. It felt great to be able to build pretty complex projects like a remote-controlled fan without much of a more profound knowledge of electronics and the best part was how quickly I could build these projects.</p>
<p>Arduino is a great platform to learn about electronics but I realised that it abstracted a lot of the details away and I wanted to learn about those more in-depth things that were hidden. The resources below helped me learn more about the inner workings of microcontrollers and they are beginner-friendly too</p>
<ul>
<li><p><strong>Make: AVR Programming</strong> <br />
This book goes into the details of AVR microcontrollers and shows you how the peripherals like UART, I<sup>2</sup>C, etc. After completing this book, you will have a better understanding of the abstractions provided by Arduino</p>
</li>
<li><p><strong>Programming with STM32: Getting Started with the Nucleo Board and C/C++ by Donald Norris</strong> <br />
This book teaches you how about the STM32 family of microcontrollers. These microcontrollers are based on ARM Cortex-M and have a more complicated architecture than AVR microcontrollers. You can get the Nucleo boards from Aliexpress or if that is too expensive, you can follow along using the Bluepill STM32F103 which you can get locally in Ghana from <br />
<a target="_blank" href="https://nauvitel.com/product/bluepill-stm32f103/">Nauvitel Electronics</a> <br />
<a target="_blank" href="https://www.okuelectronics.com/shop/stm32f103c8t6-microcomputer-stm32-arm-core-board/">OkuElectronics</a></p>
</li>
</ul>
<p>I hope you enjoy your journey of learning the inner workings of microcontrollers as I did.</p>
]]></content:encoded></item><item><title><![CDATA[Getting electronic components for your next project in Ghana]]></title><description><![CDATA[Once I started trying to follow online tutorials to build electronic projects, I quickly ran into an issue of finding where I can buy these modules and electronic components. I wanted to find local shops that I could buy from since shipping everythin...]]></description><link>https://blog.jjbofficial.com/getting-electronic-components-for-your-next-project-in-ghana</link><guid isPermaLink="true">https://blog.jjbofficial.com/getting-electronic-components-for-your-next-project-in-ghana</guid><category><![CDATA[arduino]]></category><category><![CDATA[Ghana]]></category><category><![CDATA[Electronics]]></category><dc:creator><![CDATA[Jeremiah John Boateng]]></dc:creator><pubDate>Tue, 27 Dec 2022 20:57:14 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/e901c3b046c55b5e3658959d1966c45a.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Once I started trying to follow online tutorials to build electronic projects, I quickly ran into an issue of finding where I can buy these modules and electronic components. I wanted to find local shops that I could buy from since shipping everything would be too expensive. The list below is all shops which I have personally purchased components from.</p>
<ul>
<li><a target="_blank" href="https://okuelectronics.com">Okuelectronics</a></li>
<li><a target="_blank" href="https://geekelectronics.io">Geekelectronics</a></li>
<li><a target="_blank" href="https://anycomponentlab.com">AnyComponentLab</a></li>
<li><a target="_blank" href="https://nauvitel.com">Nauvitel Electronics</a></li>
</ul>
<p>Although the shops above usually had the parts that I needed, I sometimes had to buy some parts from outside Ghana especially when I wanted to work on projects that used surface mount components. The main thing I looked for was cheap shipping since I don't buy in high volume and the site delivers products to Ghana. I found two sites that work for me</p>
<ul>
<li><a target="_blank" href="https://lcsc.com">LCSC</a> </li>
<li><a target="_blank" href="https://aliexpress.com">Aliexpress</a></li>
</ul>
<p><strong>Note: You can sometimes order parts from Aliexpress that don't work. You should make sure to compare prices on Aliexpress to other sites and read the comments.</strong></p>
]]></content:encoded></item><item><title><![CDATA[Embedded Developer Communities in Ghana 🇬🇭]]></title><description><![CDATA[I am very passionate about embedded systems and electronics. Programming devices to respond to real-life stimuli hits differently and I knew that there was no way that I am the only one in Ghana that thinks like that. However, it was hard for me to f...]]></description><link>https://blog.jjbofficial.com/embedded-developer-communities-in-ghana</link><guid isPermaLink="true">https://blog.jjbofficial.com/embedded-developer-communities-in-ghana</guid><category><![CDATA[embedded systems]]></category><category><![CDATA[Ghana]]></category><dc:creator><![CDATA[Jeremiah John Boateng]]></dc:creator><pubDate>Fri, 16 Dec 2022 21:32:57 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1671146720008/clg-EcK3R.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I am very passionate about embedded systems and electronics. Programming devices to respond to real-life stimuli hits differently and I knew that there was no way that I am the only one in Ghana that thinks like that. However, it was hard for me to find local communities or meet-ups that were focused on embedded systems but I was eventually able to join a few. So I have decided to create a list on GitHub of these communities and also other people that you can follow and network with. I want others to have an easier time finding these communities. You can view the list <a target="_blank" href="https://github.com/jjbofficial/embedded-developer-communities-in-ghana">here</a></p>
]]></content:encoded></item></channel></rss>