<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Developer Blog</title>
  
  <subtitle>by Roman Soldatow</subtitle>
  <link href="/atom.xml" rel="self"/>
  
  <link href="https://rmsol.de/"/>
  <updated>2022-02-10T00:00:52.859Z</updated>
  <id>https://rmsol.de/</id>
  
  <author>
    <name>Roman Soldatow</name>
    
  </author>
  
  <generator uri="http://hexo.io/">Hexo</generator>
  
  <entry>
    <title>Zoom and Compton</title>
    <link href="https://rmsol.de/2022/02/10/Zoom-and-Compton/"/>
    <id>https://rmsol.de/2022/02/10/Zoom-and-Compton/</id>
    <published>2022-02-09T23:01:09.000Z</published>
    <updated>2022-02-10T00:00:52.859Z</updated>
    
    <content type="html"><![CDATA[<p>If you use Zoom and Compton in a combination you might already had the issue that if you start sharing in zoom, you got a grey/dark overlay (shadow).</p><p>The fix for that was to disable Compton shadow in general or exclude Zoom Share Frame (“cpt_frame_window”) in the Compton shadow config.</p><p>E.g. in .config/compton.conf</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">shadow-exclude = [</span><br><span class="line">  &quot;name = &apos;cpt_frame_window&apos;&quot;</span><br><span class="line">];</span><br></pre></td></tr></table></figure><p>But since Zoom version 5.9.3 the problem came back again because Zoom renamed the name of Zoom Share Frame to “cpt_frame_xcb_window”. So that it can be adjusted the same way.</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">shadow-exclude = [</span><br><span class="line">  &quot;name = &apos;cpt_frame_xcb_window&apos;&quot;</span><br><span class="line">];</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;If you use Zoom and Compton in a combination you might already had the issue that if you start sharing in zoom, you got a grey/dark overl
      
    
    </summary>
    
    
      <category term="Linux" scheme="https://rmsol.de/tags/Linux/"/>
    
  </entry>
  
  <entry>
    <title>Caddy v2 examples</title>
    <link href="https://rmsol.de/2021/11/24/Caddy-v2-examples/"/>
    <id>https://rmsol.de/2021/11/24/Caddy-v2-examples/</id>
    <published>2021-11-23T23:09:46.000Z</published>
    <updated>2021-11-23T23:46:14.197Z</updated>
    
    <content type="html"><![CDATA[<p>It’s been a while since I started using caddy v2 in production. Therefore I would like to show some caddy configuration examples that I also use by myself.</p><h3 id="HTTP3-in-Caddy-v2"><a href="#HTTP3-in-Caddy-v2" class="headerlink" title="HTTP3 in Caddy v2"></a>HTTP3 in Caddy v2</h3><p>In the last <a href="https://rmsol.de/2020/09/17/Caddy-v2/">caddy post</a> I mentioned how to setup HTTP3, however the syntax has changed slightly.</p><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  servers :443 &#123;</span><br><span class="line">    protocol &#123;</span><br><span class="line">      experimental_http3</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="Reverse-proxy"><a href="#Reverse-proxy" class="headerlink" title="Reverse proxy"></a>Reverse proxy</h3><p>Simple reverse proxy (to a specific port)</p><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">matrix.rmsol.de &#123;</span><br><span class="line">  reverse_proxy localhost:8008</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="File-server"><a href="#File-server" class="headerlink" title="File server"></a>File server</h3><p>Serving a static page (html/css). In that case with <strong>gzip</strong> and extended <strong>Cache-Control</strong>.</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">rmsol.de &#123;</span><br><span class="line">  root * /var/www/rmsol.de</span><br><span class="line">  encode gzip</span><br><span class="line">  header Cache-Control max=age=3600</span><br><span class="line">  file_server</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="PHP-website"><a href="#PHP-website" class="headerlink" title="PHP website"></a>PHP website</h4><p>Serving a PHP website.</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">ip-whois.de &#123;</span><br><span class="line">  root * /var/www/ip-whois.de</span><br><span class="line">  file_server</span><br><span class="line">  php_fastcgi unix//var/run/php/php7.4-fpm.sock</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="Nextcloud"><a href="#Nextcloud" class="headerlink" title="Nextcloud"></a>Nextcloud</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line">nextcloud.rmsol.de &#123;</span><br><span class="line">  root * /var/www/nc</span><br><span class="line">  file_server</span><br><span class="line"></span><br><span class="line">  php_fastcgi unix//var/run/php/php7.4-fpm.sock</span><br><span class="line">  header &#123;</span><br><span class="line">    Strict-Transport-Security max-age=31536000; # enable HSTS</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  redir /.well-known/carddav /remote.php/dav 301</span><br><span class="line">  redir /.well-known/caldav /remote.php/dav 301</span><br><span class="line"></span><br><span class="line">  @forbidden &#123;</span><br><span class="line">    path /.htaccess</span><br><span class="line">    path /data/*</span><br><span class="line">    path /config/*</span><br><span class="line">    path /db_structure</span><br><span class="line">    path /.xml</span><br><span class="line">    path /README</span><br><span class="line">    path /3rdparty/*</span><br><span class="line">    path /lib/*</span><br><span class="line">    path /templates/*</span><br><span class="line">    path /occ</span><br><span class="line">    path /console.php</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  respond @forbidden 404</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;It’s been a while since I started using caddy v2 in production. Therefore I would like to show some caddy configuration examples that I a
      
    
    </summary>
    
    
      <category term="Caddy" scheme="https://rmsol.de/tags/Caddy/"/>
    
  </entry>
  
  <entry>
    <title>Polybar modules (Zoom and service)</title>
    <link href="https://rmsol.de/2021/03/31/polybar-modules-1/"/>
    <id>https://rmsol.de/2021/03/31/polybar-modules-1/</id>
    <published>2021-03-30T23:56:50.000Z</published>
    <updated>2021-04-07T21:16:34.131Z</updated>
    
    <content type="html"><![CDATA[<p>Some time ago I wrote several i3 blocklets, in particular <a href="https://rmsol.de/2020/05/08/zoom-i3block-dnd/">Zoom Dunst notification</a> and a service blocklet (to be able easily to enable/disable services). And since I moved from i3blocks to <a href="https://github.com/polybar/polybar" target="_blank" rel="noopener">polybar</a>, I had slightly to adjust the scripts.</p><h2 id="Zoom-Dunst-module"><a href="#Zoom-Dunst-module" class="headerlink" title="Zoom Dunst module"></a>Zoom Dunst module</h2><p>I already wrote a <a href="https://rmsol.de/2020/05/08/zoom-i3block-dnd/">short post</a> about the Zoom dunst module. Here is just a slightly adjusted version for <a href="https://github.com/polybar/polybar" target="_blank" rel="noopener">polybar</a>.</p><p>To integrate the module, just add the snippet to your <a href="https://github.com/polybar/polybar" target="_blank" rel="noopener">polybar</a> modules and adjust the path to the <em>zoom.sh</em> script.</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">[module/zoom]</span><br><span class="line">type = custom/script</span><br><span class="line">exec = ~/polybar-scripts/zoom.sh</span><br><span class="line">interval = 5</span><br><span class="line">label = %output% Zoom</span><br></pre></td></tr></table></figure><h3 id="zoom-sh-script"><a href="#zoom-sh-script" class="headerlink" title="zoom.sh script"></a>zoom.sh script</h3><p>The zoom.sh file looks like that</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#!/bin/bash</span></span><br><span class="line"></span><br><span class="line">DUNST_TIMEOUT=<span class="variable">$&#123;DUNST_TIMEOUT:-3&#125;</span>        <span class="comment"># duration in seconds</span></span><br><span class="line">DUNST_URGENCY=<span class="variable">$&#123;DUNST_URGENCY:-"low"&#125;</span>    <span class="comment"># low, normal or critical</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="title">enable</span></span> () &#123;</span><br><span class="line">    touch /tmp/i3zoom.lock</span><br><span class="line">    notify-send -u <span class="variable">$&#123;DUNST_URGENCY&#125;</span> -t <span class="variable">$&#123;DUNST_TIMEOUT&#125;</span>000 Zoom <span class="string">"Sharing mode activated"</span></span><br><span class="line">    sleep <span class="variable">$&#123;DUNST_TIMEOUT&#125;</span></span><br><span class="line">    notify-send DUNST_COMMAND_PAUSE</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="title">disable</span></span> () &#123;</span><br><span class="line">    rm /tmp/i3zoom.lock</span><br><span class="line">    notify-send DUNST_COMMAND_RESUME</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">xwininfo -name as_toolbar &gt;/dev/null 2&gt;&amp;1</span><br><span class="line"><span class="keyword">if</span> [ $? -eq 0 ]; <span class="keyword">then</span></span><br><span class="line">    <span class="keyword">if</span> ! [ -f <span class="string">"/tmp/i3zoom.lock"</span> ]; <span class="keyword">then</span></span><br><span class="line">        <span class="built_in">enable</span></span><br><span class="line">        <span class="built_in">echo</span> <span class="string">"%&#123;F#ff0000&#125;"</span></span><br><span class="line">    <span class="keyword">else</span></span><br><span class="line">        <span class="built_in">echo</span> <span class="string">"%&#123;F#ff0000&#125;"</span></span><br><span class="line">    <span class="keyword">fi</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">else</span></span><br><span class="line">    <span class="keyword">if</span> [ -f <span class="string">"/tmp/i3zoom.lock"</span> ]; <span class="keyword">then</span></span><br><span class="line">        <span class="built_in">disable</span></span><br><span class="line">    <span class="keyword">fi</span></span><br><span class="line">    <span class="built_in">echo</span> <span class="string">"%&#123;F#ff0000&#125;"</span></span><br><span class="line"><span class="keyword">fi</span></span><br></pre></td></tr></table></figure><h2 id="Service-module"><a href="#Service-module" class="headerlink" title="Service module"></a>Service module</h2><p>The service module is an easy integration of your Linux service, which you can enable/disable/toggle. E.g. I use it often to enable/disable the OpenVPN service or other frequently toggled services.</p><p>It can be turned on/off just by clicking on the name of the service.</p><img src="/2021/03/31/polybar-modules-1/openvpn_on.png" title="Enabled OpenVPN"> <img src="/2021/03/31/polybar-modules-1/openvpn_off.png" title="Disabled OpenVPN"><p>To integrate the module, just add the snippet to your <a href="https://github.com/polybar/polybar" target="_blank" rel="noopener">polybar</a> modules and adjust the path to the <em>service.sh</em> script.</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">[module/service]</span><br><span class="line">type = custom/script</span><br><span class="line">exec = ~/polybar-scripts/service.sh</span><br><span class="line">interval = 5</span><br><span class="line">click-middle = ~/polybar-scripts/service.sh toggle &amp;</span><br><span class="line">click-left =  ~/polybar-scripts/service.sh enable &amp;</span><br><span class="line">click-right = ~/polybar-scripts/service.sh disable &amp;</span><br><span class="line">label = %output%</span><br></pre></td></tr></table></figure><h3 id="service-sh-script"><a href="#service-sh-script" class="headerlink" title="service.sh script"></a>service.sh script</h3><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#!/bin/bash</span></span><br><span class="line"></span><br><span class="line">SERVICE_NAME=<span class="string">"openvpn"</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> [ <span class="string">"<span class="variable">$(systemctl is-active "$SERVICE_NAME")</span>"</span> != <span class="string">"active"</span> ]</span><br><span class="line"><span class="keyword">then</span></span><br><span class="line">    <span class="built_in">echo</span> <span class="string">'%&#123;F#ff0000&#125; '</span><span class="variable">$SERVICE_NAME</span></span><br><span class="line"><span class="keyword">else</span></span><br><span class="line">    <span class="built_in">echo</span> <span class="string">'%&#123;F#00ff00&#125; '</span><span class="variable">$SERVICE_NAME</span></span><br><span class="line"><span class="keyword">fi</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="title">enable</span></span> () &#123;</span><br><span class="line">    sudo systemctl start <span class="string">"<span class="variable">$SERVICE_NAME</span>"</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="title">disable</span></span> () &#123;</span><br><span class="line">    sudo systemctl stop <span class="string">"<span class="variable">$SERVICE_NAME</span>"</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="title">toggle</span></span> () &#123;</span><br><span class="line">    <span class="keyword">if</span> [ <span class="string">"<span class="variable">$(systemctl is-active $SERVICE_NAME)</span>"</span> != <span class="string">"active"</span> ]</span><br><span class="line">    <span class="keyword">then</span></span><br><span class="line">        sudo systemctl start <span class="variable">$SERVICE_NAME</span></span><br><span class="line">    <span class="keyword">else</span></span><br><span class="line">        sudo systemctl stop <span class="variable">$SERVICE_NAME</span></span><br><span class="line">    <span class="keyword">fi</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="string">"<span class="variable">$@</span>"</span></span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;Some time ago I wrote several i3 blocklets, in particular &lt;a href=&quot;https://rmsol.de/2020/05/08/zoom-i3block-dnd/&quot;&gt;Zoom Dunst notification
      
    
    </summary>
    
    
      <category term="Linux" scheme="https://rmsol.de/tags/Linux/"/>
    
      <category term="i3" scheme="https://rmsol.de/tags/i3/"/>
    
      <category term="polybar" scheme="https://rmsol.de/tags/polybar/"/>
    
  </entry>
  
  <entry>
    <title>Control specific audio device with amixer and i3block</title>
    <link href="https://rmsol.de/2020/12/02/amixer-i3block/"/>
    <id>https://rmsol.de/2020/12/02/amixer-i3block/</id>
    <published>2020-12-01T23:52:55.000Z</published>
    <updated>2021-04-07T21:16:34.116Z</updated>
    
    <content type="html"><![CDATA[<p>I wrote another <a href="https://github.com/vivien/i3blocks-contrib" target="_blank" rel="noopener">blocklet</a> to be able to control my USB headset, next to my normal audio output. So that I was able to control my headset volume and PC speakers at the same time.</p><p>You can identify the audio device you would like to control with:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cat /proc/asound/cards</span><br></pre></td></tr></table></figure><p>The output looks like that:</p><img src="/2020/12/02/amixer-i3block/adevice.png" title="audio device"><p>In my case, I was interested in the USB Audio Device called “C-Media”, which you will also find in the script itself. (Just take the first word, of your device name, from the second row)</p><p>The volume can be easily controlled by scrolling up/down over the icon. <img src="/2020/12/02/amixer-i3block/headset.png" title="headset"></p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#!/bin/bash</span></span><br><span class="line"> </span><br><span class="line">CARD=$(awk <span class="string">'$1 == "C-Media" &#123;print f&#125; &#123;f=$1&#125;'</span> /proc/asound/cards)</span><br><span class="line">VOLUME=$(amixer -M -c <span class="variable">$&#123;CARD&#125;</span> | grep -E -o <span class="string">'[0-9]&#123;1,3&#125;?%'</span> | head -1)</span><br><span class="line"> </span><br><span class="line"><span class="keyword">if</span> [ <span class="variable">$BLOCK_BUTTON</span> == <span class="string">'4'</span> ]</span><br><span class="line"><span class="keyword">then</span></span><br><span class="line">        amixer -D pulse sset Master 5%+ unmute -q</span><br><span class="line">        VOLUME=$(amixer -M -c <span class="variable">$&#123;CARD&#125;</span> | grep -E -o <span class="string">'[0-9]&#123;1,3&#125;?%'</span> | head -1)</span><br><span class="line">        <span class="built_in">echo</span> <span class="string">"&lt;span foreground=\"#00FF00\"&gt;🎧 <span class="variable">$&#123;VOLUME&#125;</span>&lt;/span&gt;"</span></span><br><span class="line"><span class="keyword">fi</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> [ <span class="variable">$BLOCK_BUTTON</span> == <span class="string">'5'</span> ]</span><br><span class="line"><span class="keyword">then</span></span><br><span class="line">        amixer -D pulse sset Master 5%- unmute -q</span><br><span class="line">        VOLUME=$(amixer -M -c <span class="variable">$&#123;CARD&#125;</span> | grep -E -o <span class="string">'[0-9]&#123;1,3&#125;?%'</span> | head -1)</span><br><span class="line">        <span class="built_in">echo</span> <span class="string">"&lt;span foreground=\"#00FF00\"&gt;🎧 <span class="variable">$&#123;VOLUME&#125;</span>&lt;/span&gt;"</span></span><br><span class="line"><span class="keyword">else</span></span><br><span class="line">        <span class="built_in">echo</span> <span class="string">"&lt;span foreground=\"#00FF00\"&gt;🎧 <span class="variable">$&#123;VOLUME&#125;</span>&lt;/span&gt;"</span></span><br><span class="line"><span class="keyword">fi</span></span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;I wrote another &lt;a href=&quot;https://github.com/vivien/i3blocks-contrib&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;blocklet&lt;/a&gt; to be able to control my
      
    
    </summary>
    
    
      <category term="Linux" scheme="https://rmsol.de/tags/Linux/"/>
    
      <category term="i3" scheme="https://rmsol.de/tags/i3/"/>
    
  </entry>
  
  <entry>
    <title>Caddy v2</title>
    <link href="https://rmsol.de/2020/09/17/Caddy-v2/"/>
    <id>https://rmsol.de/2020/09/17/Caddy-v2/</id>
    <published>2020-09-16T22:55:56.000Z</published>
    <updated>2021-11-23T23:40:45.446Z</updated>
    
    <content type="html"><![CDATA[<p>For about 10 years I’m running Nginx as my webserver (also for this blog). That’s why I wanted to look for something new, not because I’m not satisfied with Nginx, but because I just wanted to try another webserver with the hope that there might be something better out there.</p><p>It came handy that <a href="https://caddyserver.com/v2" target="_blank" rel="noopener">Caddy v2</a> was released. At that time I already wanted to test the first version, but I didn’t have the chance. Therefore I decided to use Caddy v2 and have been running it for 3 months. And I must say I like it.</p><h2 id="What-is-different-about-Caddy"><a href="#What-is-different-about-Caddy" class="headerlink" title="What is different about Caddy?"></a>What is different about Caddy?</h2><ul><li><a href="https://caddyserver.com/docs/quick-starts/api" target="_blank" rel="noopener">Live config API</a> (Seamlessly update your server’s config without downtime using elegant and intuitive REST endpoints)</li><li>Secure by Default (Caddy is the only web server that uses HTTPS by default)<ul><li>Auto-renew certificates (with Let’s encrypt)</li><li>It also works with localhost (https)</li></ul></li><li>HTTP/2 out of the box, and HTTP/3 by enabling</li><li>Reverse Proxy/Load balancing</li><li>No Dependencies (Because Caddy is is written in Go, its binaries are entirely self-contained and run on every platform, including containers without libc)</li><li>Modular Stack (Take back control over your compute edge. Caddy can be extended with everything you need using plugins)</li></ul><p>Check more features on the <a href="https://caddyserver.com/" target="_blank" rel="noopener">caddy website</a>.</p><h2 id="How-do-the-Caddyfile-config-looks-like"><a href="#How-do-the-Caddyfile-config-looks-like" class="headerlink" title="How do the Caddyfile (config) looks like?"></a>How do the Caddyfile (config) looks like?</h2><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">    experimental_http3</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">rmsol.de &#123;</span><br><span class="line">    root * /var/www/rmsol.de</span><br><span class="line">    encode gzip</span><br><span class="line">    header Cache-Control max=age=3600</span><br><span class="line">    file_server</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">imagestack.de &#123;</span><br><span class="line">    root * /var/www/imagestack.de</span><br><span class="line">    file_server</span><br><span class="line">    php_fastcgi unix//var/run/php/php7.0-fpm.sock</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>It is much cleaner than Nginx.<br>PS: you can migrate your Nginx config file to Caddy over <a href="https://caddyserver.com/docs/config-adapters" target="_blank" rel="noopener">config adapters</a></p><h2 id="HTTP-3-support"><a href="#HTTP-3-support" class="headerlink" title="HTTP 3 support"></a>HTTP 3 support</h2><p>I also enabled HTTP 3, it is still experimental (not just in Caddy, but in general).<br>Your browser need also to <a href="https://caniuse.com/http3" target="_blank" rel="noopener">support it</a>.</p><ul><li>It can be enabled in Firefox (from version 72) via the network.http.http3.enabled pref in about:config.</li></ul><ul><li>It can be enabled in Chrome (from version 79) via the –enable-quic &amp; –quic-version=h3-23 command line arguments.</li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;For about 10 years I’m running Nginx as my webserver (also for this blog). That’s why I wanted to look for something new, not because I’m
      
    
    </summary>
    
    
      <category term="Caddy" scheme="https://rmsol.de/tags/Caddy/"/>
    
      <category term="Alternative" scheme="https://rmsol.de/tags/Alternative/"/>
    
  </entry>
  
  <entry>
    <title>Gnome and OpenVPN</title>
    <link href="https://rmsol.de/2020/07/05/openvpn-gnome/"/>
    <id>https://rmsol.de/2020/07/05/openvpn-gnome/</id>
    <published>2020-07-05T18:46:03.000Z</published>
    <updated>2020-09-16T23:14:09.641Z</updated>
    
    <content type="html"><![CDATA[<p>In this short blog post, I would like to describe the problems and workarounds I did, to get OpenVPN working with the Gnome VPN Manager.</p><p>Normally I use the OpenVPN client for a VPN, but this time I decided (because I was using Gnome) to use the built-in VPN manager of Gnome. However, I encountered a few problems:</p><p>When you try to import the <strong>.opvn</strong> file, you get an error message saying <strong>“Error: the plugin does not support import capability”</strong>. Because Gnome Network Manager does not support OpenVPN out of the box.</p><ul><li><p>You need to install the OpenVPN plugin for the network manager by:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt install network-manager-openvpn-gnome</span><br></pre></td></tr></table></figure></li><li><p>After installation of the plugin, I still got the same error message. But I could import it over the shell with (replace the filename with yours):</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo nmcli connection import <span class="built_in">type</span> openvpn file &lt;filename&gt;</span><br></pre></td></tr></table></figure></li><li><p>But the import was still not successful. It was failing on a line with “route”. The <strong>route remote_host 255.255.255.255 net_gateway default</strong>. That seems to be a common problem.</p><p>I just commented it out with #. Like: <strong># route remote_host 255.255.255.255 net_gateway</strong></p></li><li><p>I could finally import the OpenVPN configuration. But I could not enable it. The slider went directly back to “off”.</p><p>I could solve it by set the Password to <strong>Store the password for all users</strong>.</p></li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;In this short blog post, I would like to describe the problems and workarounds I did, to get OpenVPN working with the Gnome VPN Manager.&lt;
      
    
    </summary>
    
    
      <category term="Linux" scheme="https://rmsol.de/tags/Linux/"/>
    
  </entry>
  
  <entry>
    <title>Pausing dunst while zoom screen sharing</title>
    <link href="https://rmsol.de/2020/05/08/zoom-i3block-dnd/"/>
    <id>https://rmsol.de/2020/05/08/zoom-i3block-dnd/</id>
    <published>2020-05-07T22:16:47.000Z</published>
    <updated>2021-04-07T21:16:34.141Z</updated>
    
    <content type="html"><![CDATA[<p>I wrote a small script/blocklet to mute the <a href="https://dunst-project.org/screenshots/" target="_blank" rel="noopener">dunst notifications</a> while I’m sharing my screen over <a href="https://zoom.us/" target="_blank" rel="noopener">zoom</a>. To prevent accidentally giving confidential information to other people e.g Slack or Mattermost messages.</p><p>I developed this as a <a href="https://github.com/vivien/i3blocks-contrib" target="_blank" rel="noopener">blocklet</a> for my <a href="https://i3wm.org/" target="_blank" rel="noopener">i3wm</a> (tiling window manager) status bar called <a href="https://github.com/vivien/i3blocks" target="_blank" rel="noopener">i3blocks</a>. It tries to find a specific window on your desktop, called “as_toolbar”, which represents that you share your screen.</p><img src="/2020/05/08/zoom-i3block-dnd/share.png" title="as_toolbar"><p>If the window could be found, the dunst service will be paused and you will be notified over dunst that “Sharing mode” is activated. Upcoming dunst messages will be not removed so that by stop sharing your screen, all the messages will be shown.</p><img src="/2020/05/08/zoom-i3block-dnd/dunst_zoom.png" title="Sharing mode activated"><p>It also shows a small <a href="https://fontawesome.com/icons/bell?style=solid" target="_blank" rel="noopener">bell</a> and <a href="https://fontawesome.com/icons/bell-slash?style=solid" target="_blank" rel="noopener">slashed bell</a> icon (in my case) in the status bar. You can change it to any icon or text you like.<br>PS: Most likely the icon will shown as  in your editor</p><h2 id="Zoom-Dunst-Blocklet"><a href="#Zoom-Dunst-Blocklet" class="headerlink" title="Zoom Dunst Blocklet"></a>Zoom Dunst Blocklet</h2><p>I named it “zoom.sh”</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#!/bin/bash</span></span><br><span class="line"> </span><br><span class="line">DUNST_TIMEOUT=3     <span class="comment"># duration in seconds</span></span><br><span class="line">DUNST_URGENCY=low   <span class="comment"># low, normal or critical</span></span><br><span class="line"> </span><br><span class="line">xwininfo -name as_toolbar &gt;/dev/null 2&gt;&amp;1</span><br><span class="line"><span class="keyword">if</span> [ $? -eq 0 ]; <span class="keyword">then</span></span><br><span class="line">    <span class="keyword">if</span> ! [ -f <span class="string">"/tmp/i3zoom.lock"</span> ]; <span class="keyword">then</span></span><br><span class="line">        touch /tmp/i3zoom.lock</span><br><span class="line">        notify-send -u <span class="variable">$&#123;DUNST_URGENCY&#125;</span> -t <span class="variable">$&#123;DUNST_TIMEOUT&#125;</span>000 Zoom <span class="string">"Sharing mode activated"</span></span><br><span class="line">        sleep <span class="variable">$&#123;DUNST_TIMEOUT&#125;</span></span><br><span class="line">        notify-send DUNST_COMMAND_PAUSE</span><br><span class="line">        <span class="built_in">echo</span> <span class="string">"&lt;span foreground=\"#FF0000\"&gt;&lt;/span&gt;"</span></span><br><span class="line">    <span class="keyword">else</span></span><br><span class="line">        <span class="built_in">echo</span> <span class="string">"&lt;span foreground=\"#FF0000\"&gt;&lt;/span&gt;"</span></span><br><span class="line">    <span class="keyword">fi</span></span><br><span class="line"> </span><br><span class="line"><span class="keyword">else</span></span><br><span class="line">    <span class="keyword">if</span> [ -f <span class="string">"/tmp/i3zoom.lock"</span> ]; <span class="keyword">then</span></span><br><span class="line">        rm /tmp/i3zoom.lock</span><br><span class="line">        notify-send DUNST_COMMAND_RESUME</span><br><span class="line">    <span class="keyword">fi</span></span><br><span class="line">    <span class="built_in">echo</span> <span class="string">"&lt;span foreground=\"#00FF00\"&gt;&lt;/span&gt;"</span></span><br><span class="line"><span class="keyword">fi</span></span><br></pre></td></tr></table></figure><h3 id="Integration-in-i3blocks-config"><a href="#Integration-in-i3blocks-config" class="headerlink" title="Integration in i3blocks config"></a>Integration in i3blocks config</h3><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">[zoom]</span><br><span class="line"><span class="built_in">command</span>=<span class="variable">$HOME</span>/.config/i3blocks/blocks/zoom.sh</span><br><span class="line">interval=5</span><br><span class="line">markup=pango</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;I wrote a small script/blocklet to mute the &lt;a href=&quot;https://dunst-project.org/screenshots/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;dunst notific
      
    
    </summary>
    
    
      <category term="Linux" scheme="https://rmsol.de/tags/Linux/"/>
    
      <category term="i3" scheme="https://rmsol.de/tags/i3/"/>
    
  </entry>
  
  <entry>
    <title>Virtual webcam with v4l2</title>
    <link href="https://rmsol.de/2020/04/25/v4l2/"/>
    <id>https://rmsol.de/2020/04/25/v4l2/</id>
    <published>2020-04-25T00:03:52.000Z</published>
    <updated>2020-04-25T00:12:21.525Z</updated>
    
    <content type="html"><![CDATA[<p>A few weeks ago I discovered Video4Linux (v4l2), which allows you to control video devices like a webcam.</p><p>In my case, I simulated/virtualized a webcam. That means that with the help of v4l2 I could send a video stream (or an image) to a virtual/simulated webcam. And every app that can normally address a webcam (e.g. Zoom or Skype) played my video what I sent to the webcam.</p><p>Here are some of the commands I found useful.</p><h2 id="Setup"><a href="#Setup" class="headerlink" title="Setup"></a>Setup</h2><p>With <a href="https://github.com/umlaeute/v4l2loopback" target="_blank" rel="noopener">v4l2loopback</a> we can virtualize a webcam.</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt install v4l2loopback-dkms</span><br></pre></td></tr></table></figure><p>With v4l2-ctl we can control the video4linux drivers. (It is in the <a href="https://linuxtv.org/wiki/index.php/V4l-utils" target="_blank" rel="noopener">v4l-utils</a> package)</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt install v4l-utils</span><br></pre></td></tr></table></figure><p>With <a href="https://www.ffmpeg.org/" target="_blank" rel="noopener">ffmpeg</a> we can stream our video to the webcam</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt install ffmpeg</span><br></pre></td></tr></table></figure><h2 id="Start"><a href="#Start" class="headerlink" title="Start"></a>Start</h2><p>Let’s load the kernel module v4l2loopback, which creates a virtual video device.</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo modprobe v4l2loopback</span><br></pre></td></tr></table></figure><p>If you need multiple video devices, you can load them as follow</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo modprobe v4l2loopback devices=2</span><br></pre></td></tr></table></figure><p>The video devices will appear under /dev/video[0-9].<br>You can check with v4l2-ctl, which id your video devices have</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">v4l2-ctl --list-devices</span><br></pre></td></tr></table></figure><h3 id="Video-to-webcam"><a href="#Video-to-webcam" class="headerlink" title="Video to webcam"></a>Video to webcam</h3><p>You can stream a video (input.mov in that case) to your virtualized webcam</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ffmpeg -re -i input.mov -f v4l2 /dev/video0</span><br></pre></td></tr></table></figure><h4 id="Loop"><a href="#Loop" class="headerlink" title="Loop"></a>Loop</h4><p>If you would like to send your video in a loop</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ffmpeg -stream_loop -1 -re -i input.mov -f v4l2 /dev/video0</span><br></pre></td></tr></table></figure><h3 id="Picture-to-webcam"><a href="#Picture-to-webcam" class="headerlink" title="Picture to webcam"></a>Picture to webcam</h3><p>If you would like just send a picture to your virtualized webcam.</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ffmpeg -loop 1 -re -i input.jpg -f v4l2 -vcodec rawvideo -pix_fmt yuv420p /dev/video0</span><br></pre></td></tr></table></figure><h3 id="Desktop-to-webcam"><a href="#Desktop-to-webcam" class="headerlink" title="Desktop to webcam"></a>Desktop to webcam</h3><p>If you would like to stream your desktop. Very handy if the application you use doesn’t support screen sharing.</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ffmpeg -f x11grab -framerate 25 -video_size 1920x1080 -i :1 -f v4l2 /dev/video0</span><br></pre></td></tr></table></figure><blockquote><p>In my case the input is “:1”, this could be different e.g :0.<br>You can identify your display by <strong>echo $DISPLAY</strong></p></blockquote><blockquote><p>You can identify your resolution with resolution: <strong>xrandr -q</strong></p></blockquote><blockquote><p>If you have multiple screens, you can just add the resolution you have to the display e.g. <strong>:1+1920</strong></p></blockquote><h3 id="Cloning-a-webcam"><a href="#Cloning-a-webcam" class="headerlink" title="Cloning a webcam"></a>Cloning a webcam</h3><p>You can clone e.g. your real webcam (/dev/video0) to multiple devices. In that case /dev/video1 and /dev/video2</p><p>That is handy if an application is blocking a device (because it will be used), you can bypass it by cloning the webcam and use it in another application the cloned video device.</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ffmpeg -f v4l2 -i /dev/video0 -f v4l2 /dev/video1 -f v4l2 /dev/video2</span><br></pre></td></tr></table></figure><blockquote><p>video1 and video2 need to be created. E.g. sudo modprobe v4l2loopback devices=2</p></blockquote><h2 id="Useful-commands"><a href="#Useful-commands" class="headerlink" title="Useful commands"></a>Useful commands</h2><h3 id="Playing-the-webcam-stream"><a href="#Playing-the-webcam-stream" class="headerlink" title="Playing the webcam stream"></a>Playing the webcam stream</h3><p><a href="http://ffmpeg.org/ffplay.html" target="_blank" rel="noopener">ffplay</a> is a simple media player, which use the FFmpeg library</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ffplay /dev/video0</span><br></pre></td></tr></table></figure><p>If the stream you playing is a bit laggy (that was in my case) you can tune it with:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ffplay /dev/video0  -fflags nobuffer -flags low_delay -framedrop</span><br></pre></td></tr></table></figure><p><a href="https://mpv.io/" target="_blank" rel="noopener">mpv</a> is a free (as in freedom) media player for the command line.</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mpv /dev/video0</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;A few weeks ago I discovered Video4Linux (v4l2), which allows you to control video devices like a webcam.&lt;/p&gt;&lt;p&gt;In my case, I simulated/v
      
    
    </summary>
    
    
      <category term="Linux" scheme="https://rmsol.de/tags/Linux/"/>
    
  </entry>
  
  <entry>
    <title>Coronavirus impact on internet traffic</title>
    <link href="https://rmsol.de/2020/03/24/Corona-impact-on-internet-traffic/"/>
    <id>https://rmsol.de/2020/03/24/Corona-impact-on-internet-traffic/</id>
    <published>2020-03-24T19:50:44.000Z</published>
    <updated>2020-03-24T23:19:27.713Z</updated>
    
    <content type="html"><![CDATA[<p>I was wondering which effect the coronavirus has on Internet traffic. As we all know, many people now work more in home office and people consume more streaming (e.g. YouTube, Netflix etc.) and gaming services (e.g. Steam or Google Stadia).</p><p>For this purpose, I looked at the <a href="https://www.de-cix.net/en/locations/germany/frankfurt/statistics" target="_blank" rel="noopener">statistics from DE-CIX in Frankfurt</a>, which is the second largest exchange point worldwide in terms of peak traffic (source: <a href="https://en.wikipedia.org/wiki/DE-CIX" target="_blank" rel="noopener">Wikipedia</a>).</p><h2 id="So-let’s-check-the-1-year-graph"><a href="#So-let’s-check-the-1-year-graph" class="headerlink" title="So, let’s check the 1-year graph"></a>So, let’s check the 1-year graph</h2><img src="/2020/03/24/Corona-impact-on-internet-traffic/traffic_FRA-1year-1170-400-marked.png" title="1-year graph - Copyright 2020 DE-CIX Management GmbH"><ul><li>Starting with the march 24th 2019 we had averaged traffic around 4200~ gigabits</li><li>At the 14 march 2020 we had around 5600~ gigabits (second mark)</li><li>At the 24 march 2020 we had around 6400~ gigabits (third mark)</li></ul><p>If we look at the growth from the starting point till the 14 march 2020 (almost a whole year), we see a growth by around <strong>1400~</strong> gigabits (in DE-CIX Frankfurt).</p><p>And if we compare between 14 march 2020 and 24 march 2020, we see a growth around <strong>1200~</strong> gigabits.</p><blockquote><p>That means, that in about 10 days (in reality even less) the internet average grew <em>almost</em> as it normally does in a whole year.</p></blockquote>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;I was wondering which effect the coronavirus has on Internet traffic. As we all know, many people now work more in home office and people
      
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>OpenVPN bypass</title>
    <link href="https://rmsol.de/2020/03/19/OpenVPN-bypass/"/>
    <id>https://rmsol.de/2020/03/19/OpenVPN-bypass/</id>
    <published>2020-03-19T19:17:23.000Z</published>
    <updated>2020-03-19T19:17:52.867Z</updated>
    
    <content type="html"><![CDATA[<p>In the time of coronavirus pandemic, many companies rely on home office. While working in the home office, the entire data traffic is transferred via the VPN server. So you can use the internal services/tools but also online services like Google, Spotify, Youtube or Zoom.</p><p>This means a hard time for the VPN servers, which have to transfer the entire traffic from your PC to the internal tools, online services and back to your PC.</p><p>In order not to overload the VPN servers, you don’t want to transfer data intensive services like Youtube over the VPN. Also, you don’t want to send data flow sensitive services like audio/video communication tools over the VPN (unless you want the additional encryption).<br>One solution to this could be an route exception for such services. So that the services will bypass the VPN and will be directly routed to the internet.</p><h2 id="OpenVPN-bypass"><a href="#OpenVPN-bypass" class="headerlink" title="OpenVPN bypass"></a>OpenVPN bypass</h2><p>If your are using OpenVPN, you can easily add routes to bypass VPN for a specific domain.<br>Just open your openvpn client config (.opvn or .conf filetype) and add your bypass/route you like.</p><p>E.g.: just add follow lines after the line:<br>route remote_host 255.255.255.255 net_gateway</p><h3 id="My-VPN-routes"><a href="#My-VPN-routes" class="headerlink" title="My VPN routes"></a>My VPN routes</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">route youtube.com 255.255.255.255 net_gateway     # For youtube</span><br><span class="line">route googlevideo.com 255.255.255.255 net_gateway # For youtube as well (videos itself)</span><br><span class="line">route akamaized.net 255.255.255.255 net_gateway   # Spotify and other services hosted/distributed over akamai</span><br><span class="line">route zoom.us 255.255.255.255 net_gateway         # For Zoom Conferences</span><br></pre></td></tr></table></figure><h2 id="OpenVPN-client-username-password"><a href="#OpenVPN-client-username-password" class="headerlink" title="OpenVPN client username / password"></a>OpenVPN client username / password</h2><p>Another handy OpenVPN client config is “auth-user-pass”, which allows you to save username and password for the VPN. So that you don’t need to input your username/password every time you enable the VPN (E.g. if you have VPN in autostart).</p><p>Just add follow line to the config</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">auth-user-pass pass.txt</span><br></pre></td></tr></table></figure><p>And create a file named “pass.txt” next to the OpenVPN config file. The content of the pass.txt file is just:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">yourusername</span><br><span class="line">yourpassword</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;In the time of coronavirus pandemic, many companies rely on home office. While working in the home office, the entire data traffic is tra
      
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>Projects</title>
    <link href="https://rmsol.de/2020/02/16/Projects/"/>
    <id>https://rmsol.de/2020/02/16/Projects/</id>
    <published>2020-02-16T16:31:32.000Z</published>
    <updated>2020-02-16T17:05:49.497Z</updated>
    
    <content type="html"><![CDATA[<p>I created a new page/space for my <a href="https://rmsol.de/projects/">side projects</a> (still WIP), where I will try to add all my side projects I worked or still work on.<br>It will mainly describe shortly the project itself and why I started that project. The code will be hosted at Github, so that everyone can potentially participate on that project.</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;I created a new page/space for my &lt;a href=&quot;https://rmsol.de/projects/&quot;&gt;side projects&lt;/a&gt; (still WIP), where I will try to add all my side
      
    
    </summary>
    
    
      <category term="Alternative" scheme="https://rmsol.de/tags/Alternative/"/>
    
      <category term="Python" scheme="https://rmsol.de/tags/Python/"/>
    
      <category term="Java" scheme="https://rmsol.de/tags/Java/"/>
    
      <category term="Openfire" scheme="https://rmsol.de/tags/Openfire/"/>
    
  </entry>
  
  <entry>
    <title>GoAcccess Nginx Analysis</title>
    <link href="https://rmsol.de/2019/12/15/Goaccess-Nginx-Analysis/"/>
    <id>https://rmsol.de/2019/12/15/Goaccess-Nginx-Analysis/</id>
    <published>2019-12-15T20:04:54.000Z</published>
    <updated>2019-12-15T20:07:53.590Z</updated>
    
    <content type="html"><![CDATA[<p>Few days ago, I installed <a href="https://goaccess.io/" target="_blank" rel="noopener">GoAcccess</a> which is an (<em>open source real-time web log analyzer and interactive viewer that runs in a terminal in *nix systems or through your browser.</em>), to analyze my NGINX access logs.</p><p>Main reason for that was to identify which files drain the traffic by asking me, do I need to move the libs to CDN to improve the performance.<br>But I was surprised by something else: Bots/Crawlers.</p><p>I mean all of us know, that the internet will be constantly scanned by crawlers like Google or Bing, and by malicious bots.<br>But I didn’t expect, that my blog was scanned around 300 times a day by malicious bots.</p><p>Here are just few examples from my access logs:</p><a id="more"></a><h2 id="Wordpress"><a href="#Wordpress" class="headerlink" title="Wordpress"></a>Wordpress</h2><ul><li>/wp-json/</li><li>/wp-content/plugins/mailcwp/mailcwp-upload.php</li><li>/wp-content/plugins/Premium_Gallery_Manager/uploadify/uploadify.css</li><li>/wp-content/plugins/complete-gallery-manager/frames/upload-images.php</li><li>/wp-load.php?up2018info=f</li><li>/wp-content/plugins/dzs-videogallery/admin/dzsuploader/upload.css</li><li>/xmlrpc.php</li></ul><h2 id="Dot-files-configs"><a href="#Dot-files-configs" class="headerlink" title="Dot files/configs"></a>Dot files/configs</h2><ul><li>/.env</li><li>/sftp-config.json</li><li>/.ftpconfig</li><li>/.remote-sync.json</li><li>/.vscode/ftp-sync.json</li><li>/.vscode/sftp.json</li><li>/deployment-config.json</li><li>/ftpsync.settings</li></ul><h2 id="PHPMyAdmin"><a href="#PHPMyAdmin" class="headerlink" title="PHPMyAdmin"></a>PHPMyAdmin</h2><ul><li>/phpmyadmin/</li><li>/MyAdmin/scripts/setup.php</li><li>/mysql/scripts/setup.php</li><li>/phpmyadmin/scripts/_setup.php</li><li>/pma/scripts/setup.php</li><li>/myadmin/scripts/setup.php</li></ul><h2 id="Others"><a href="#Others" class="headerlink" title="Others"></a>Others</h2><ul><li>/elrekt.php</li><li>/remote/login</li><li>/editBlackAndWhiteList</li><li>/GponForm/diag_Form?images/</li><li>/admin/config.php</li><li>//admin/config.php?password[0]=bebydviyx&amp;username=admin</li><li>/administrator/index.php</li><li>//a2billing/customer/templates/default/footer.tpl</li><li>/thinkphp/html/public/index.php</li><li>/TP/index.php</li><li>/TP/html/public/index.php</li><li>/api/v1/pods</li><li>/install/lib/ajaxHandlers/ajaxServerSettingsChk.php?rootUname=;echo -n HellorConfig|md5sum #</li><li>/scripts/setup.php</li><li>/manager/html</li><li>/_cat/indices</li></ul>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;Few days ago, I installed &lt;a href=&quot;https://goaccess.io/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;GoAcccess&lt;/a&gt; which is an (&lt;em&gt;open source real-time web log analyzer and interactive viewer that runs in a terminal in *nix systems or through your browser.&lt;/em&gt;), to analyze my NGINX access logs.&lt;/p&gt;&lt;p&gt;Main reason for that was to identify which files drain the traffic by asking me, do I need to move the libs to CDN to improve the performance.&lt;br&gt;But I was surprised by something else: Bots/Crawlers.&lt;/p&gt;&lt;p&gt;I mean all of us know, that the internet will be constantly scanned by crawlers like Google or Bing, and by malicious bots.&lt;br&gt;But I didn’t expect, that my blog was scanned around 300 times a day by malicious bots.&lt;/p&gt;&lt;p&gt;Here are just few examples from my access logs:&lt;/p&gt;
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>Insomnia GraphQL File Upload Scalar</title>
    <link href="https://rmsol.de/2019/11/29/Insomnia-GraphQL-File-Upload/"/>
    <id>https://rmsol.de/2019/11/29/Insomnia-GraphQL-File-Upload/</id>
    <published>2019-11-28T23:00:29.000Z</published>
    <updated>2019-11-28T23:07:47.979Z</updated>
    
    <content type="html"><![CDATA[<h2 id="Uploading-a-File-with-Upload-Scalar-and-Insomnia"><a href="#Uploading-a-File-with-Upload-Scalar-and-Insomnia" class="headerlink" title="Uploading a File with Upload Scalar and Insomnia"></a>Uploading a File with Upload Scalar and Insomnia</h2><p>Uploading a File with “Upload” Scalar isn’t a big problem if you are using library like <a href="https://github.com/jaydenseric/graphql-upload" target="_blank" rel="noopener">graphql-upload</a>. But if you like just to try/simulate it with <a href="https://insomnia.rest/" target="_blank" rel="noopener">Insomnia</a>, you need to know what happens under to hood.<br>In fact, you will send a multipart form request to the GraphQL server.</p><img src="/2019/11/29/Insomnia-GraphQL-File-Upload/insomnia_multi.png" width="700" height="325" title="Insomnia"><p>It is split in three parts (be careful, naming is important):</p><ul><li><strong>operations</strong>, which contains the GraphQL <strong>query</strong> and <strong>variables</strong></li></ul><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  <span class="attr">"query"</span>: <span class="string">"mutation($comment: String!  $file: Upload!) &#123;  </span></span><br><span class="line"><span class="string">    uploadFile(comment: $comment, file: $file) &#123;</span></span><br><span class="line"><span class="string">      id,</span></span><br><span class="line"><span class="string">      success</span></span><br><span class="line"><span class="string">    &#125;&#125;"</span>,</span><br><span class="line">  <span class="attr">"variables"</span>: &#123;</span><br><span class="line">    <span class="attr">"comment"</span>: <span class="string">"Just a comment"</span>,</span><br><span class="line">    <span class="attr">"file"</span>: <span class="literal">null</span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ul><li><strong>map</strong>, which maps the file you would like to upload <strong>0</strong>, with the GraphQL variable name <strong>file</strong><ul><li>You can extend it, if you like to upload multiple files</li></ul></li></ul><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;<span class="attr">"0"</span>:[<span class="string">"variables.file"</span>]&#125;</span><br></pre></td></tr></table></figure><ul><li><strong>0</strong>, refers to the file, which you selected and would like to upload</li></ul><blockquote><p>Note: operations and map has the type “Text (Multi-line)” and not “File”.</p></blockquote><blockquote><img src="/2019/11/29/Insomnia-GraphQL-File-Upload/insomnia_text_multi.png" width="700" height="325" title="Insomnia Multi line"></blockquote>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;Uploading-a-File-with-Upload-Scalar-and-Insomnia&quot;&gt;&lt;a href=&quot;#Uploading-a-File-with-Upload-Scalar-and-Insomnia&quot; class=&quot;headerlink&quot; tit
      
    
    </summary>
    
    
      <category term="Insomnia" scheme="https://rmsol.de/tags/Insomnia/"/>
    
  </entry>
  
  <entry>
    <title>Python Logging Benchmark</title>
    <link href="https://rmsol.de/2019/09/08/Logging-Benchmark/"/>
    <id>https://rmsol.de/2019/09/08/Logging-Benchmark/</id>
    <published>2019-09-08T17:46:18.000Z</published>
    <updated>2019-09-11T19:26:57.116Z</updated>
    
    <content type="html"><![CDATA[<p>If you have a heavy logging application, you might want to take into consideration to use the %-format strings for logging.<br>The Python logging module <a href="https://docs.python.org/3/howto/logging-cookbook.html#formatting-styles" target="_blank" rel="noopener">recommends to use the %-format</a>.<br>But I guess most of the developers will prefer the f-string format, which came with the Python 3.6 release, because it simply easier to read.</p><p>My question was: <strong>Which impact does it have on performance?</strong> In case, we use logging with string concatenation.</p><p>So, I wrote a short script to “benchmark” it (and yes, I know it is not a proper benchmark).</p><p>Compared was: logging and <strong>concatenation with ‘+’ vs formatting with % vs f-strings</strong>, over multiple runs in a different order of the benchmark functions. So that, we can at least exclude the cold start issue.</p><h2 id="Benchmark-Diagram"><a href="#Benchmark-Diagram" class="headerlink" title="Benchmark Diagram"></a>Benchmark Diagram</h2><img src="/2019/09/08/Logging-Benchmark/logging_benchmark.jpg" title="Logging Benchmark with concatenation"><p>If we take an average of all measuring points and compare them with each other, we would come to the result:</p><table><thead><tr><th>formatting with %</th><th>concatenation with +</th><th>f-strings</th></tr></thead><tbody><tr><td>7.087545455 sec</td><td>7.588454545 sec</td><td>7.707727273 sec</td></tr><tr><td>100%</td><td>107.06%</td><td>108.75%</td></tr></tbody></table><blockquote><p>That means that, formatting with % is 8.75% faster than with f-string or 7.06% faster than with concatenation. At least in the combination with “deactivated” logging.</p></blockquote><blockquote><p>The reason for that is probably, because the string will be concatenated anyway, even if we don’t log anything. But in case of formatting with %, the string will be <strong>not</strong> concatenated.</p></blockquote><a id="more"></a><h2 id="Benchmark-Script"><a href="#Benchmark-Script" class="headerlink" title="Benchmark Script"></a>Benchmark Script</h2><figure class="highlight py"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> logging</span><br><span class="line"><span class="keyword">import</span> timeit</span><br><span class="line"></span><br><span class="line">logger = logging.getLogger(__name__)</span><br><span class="line">logger.setLevel(logging.ERROR)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">concatenate</span><span class="params">()</span>:</span></span><br><span class="line">  <span class="string">"""Function to benchmark with concatenation (+)"""</span></span><br><span class="line"></span><br><span class="line">  message = <span class="string">"Yeah!"</span></span><br><span class="line">  logger.warning(<span class="string">"Message we would like to benchmark "</span> + message)</span><br><span class="line">  </span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">formatting</span><span class="params">()</span>:</span></span><br><span class="line">  <span class="string">"""Function to benchmark with formatting %s"""</span></span><br><span class="line"></span><br><span class="line">  message = <span class="string">"Yeah!"</span></span><br><span class="line">  logger.warning(<span class="string">"Message we would like to benchmark %s"</span>, message)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">fstring</span><span class="params">()</span>:</span></span><br><span class="line">  <span class="string">"""Function to benchmark with f-string"""</span></span><br><span class="line"></span><br><span class="line">  message = <span class="string">"Yeah!"</span></span><br><span class="line">  logger.warning(<span class="string">f"Message we would like to benchmark <span class="subst">&#123;message&#125;</span>"</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">"__main__"</span>:</span><br><span class="line">  print(<span class="string">"concatenate: "</span>, timeit.timeit(<span class="string">"concatenate()"</span>, setup=<span class="string">"from __main__ import concatenate"</span>, number=<span class="number">10000000</span>))</span><br><span class="line">  print(<span class="string">"formatting: "</span>, timeit.timeit(<span class="string">"formatting()"</span>, setup=<span class="string">"from __main__ import formatting"</span>, number=<span class="number">10000000</span>))</span><br><span class="line">  print(<span class="string">"fstring: "</span>, timeit.timeit(<span class="string">"fstring()"</span>, setup=<span class="string">"from __main__ import fstring"</span>, number=<span class="number">10000000</span>))</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;If you have a heavy logging application, you might want to take into consideration to use the %-format strings for logging.&lt;br&gt;The Python logging module &lt;a href=&quot;https://docs.python.org/3/howto/logging-cookbook.html#formatting-styles&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;recommends to use the %-format&lt;/a&gt;.&lt;br&gt;But I guess most of the developers will prefer the f-string format, which came with the Python 3.6 release, because it simply easier to read.&lt;/p&gt;&lt;p&gt;My question was: &lt;strong&gt;Which impact does it have on performance?&lt;/strong&gt; In case, we use logging with string concatenation.&lt;/p&gt;&lt;p&gt;So, I wrote a short script to “benchmark” it (and yes, I know it is not a proper benchmark).&lt;/p&gt;&lt;p&gt;Compared was: logging and &lt;strong&gt;concatenation with ‘+’ vs formatting with % vs f-strings&lt;/strong&gt;, over multiple runs in a different order of the benchmark functions. So that, we can at least exclude the cold start issue.&lt;/p&gt;&lt;h2 id=&quot;Benchmark-Diagram&quot;&gt;&lt;a href=&quot;#Benchmark-Diagram&quot; class=&quot;headerlink&quot; title=&quot;Benchmark Diagram&quot;&gt;&lt;/a&gt;Benchmark Diagram&lt;/h2&gt;&lt;img src=&quot;/2019/09/08/Logging-Benchmark/logging_benchmark.jpg&quot; title=&quot;Logging Benchmark with concatenation&quot;&gt;&lt;p&gt;If we take an average of all measuring points and compare them with each other, we would come to the result:&lt;/p&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;formatting with %&lt;/th&gt;&lt;th&gt;concatenation with +&lt;/th&gt;&lt;th&gt;f-strings&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;7.087545455 sec&lt;/td&gt;&lt;td&gt;7.588454545 sec&lt;/td&gt;&lt;td&gt;7.707727273 sec&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;100%&lt;/td&gt;&lt;td&gt;107.06%&lt;/td&gt;&lt;td&gt;108.75%&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;blockquote&gt;&lt;p&gt;That means that, formatting with % is 8.75% faster than with f-string or 7.06% faster than with concatenation. At least in the combination with “deactivated” logging.&lt;/p&gt;&lt;/blockquote&gt;&lt;blockquote&gt;&lt;p&gt;The reason for that is probably, because the string will be concatenated anyway, even if we don’t log anything. But in case of formatting with %, the string will be &lt;strong&gt;not&lt;/strong&gt; concatenated.&lt;/p&gt;&lt;/blockquote&gt;
    
    </summary>
    
    
      <category term="Python" scheme="https://rmsol.de/tags/Python/"/>
    
  </entry>
  
  <entry>
    <title>Python Common Style Guidelines</title>
    <link href="https://rmsol.de/2019/08/31/Python-Style-Guide/"/>
    <id>https://rmsol.de/2019/08/31/Python-Style-Guide/</id>
    <published>2019-08-31T16:07:40.000Z</published>
    <updated>2019-08-31T19:36:03.074Z</updated>
    
    <content type="html"><![CDATA[<p>One of the best practices is, to define a common style guideline. So that it would be much easier to understand a codebase when all the code in it, is in a consistent style. Specially if you are working in a team. PEP (Python Enhancement Proposals) provides a good starting point to define those style guide.</p><p>Here are some highlights which are mostly from <a href="https://www.python.org/dev/peps/pep-0008/" target="_blank" rel="noopener">PEP 8</a>, but also from other best practices:</p><h2 id="Naming-Conventions"><a href="#Naming-Conventions" class="headerlink" title="Naming Conventions"></a>Naming Conventions</h2><p>Avoid one letter variables like <em>x</em> and <em>y</em> (Except in very short code blocks). Give your variables and functions a meaningful name and use follow naming convention:</p><ul><li><p>Variables, functions, packages and modules names should be:</p><figure class="highlight py"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">lower_case_with_underscores</span><br></pre></td></tr></table></figure></li><li><p>Classes and Exceptions</p><figure class="highlight py"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">CamelCase</span><br></pre></td></tr></table></figure></li><li><p>Protected methods</p><figure class="highlight py"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">_single_leading_underscore</span><br></pre></td></tr></table></figure></li><li><p>Private methods</p><figure class="highlight py"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">__double_leading_underscore</span><br></pre></td></tr></table></figure></li><li><p>Constants</p><figure class="highlight py"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ALL_CAPS_WITH_UNDERSCORES</span><br></pre></td></tr></table></figure></li></ul><a id="more"></a><h2 id="Programming-Recommendations"><a href="#Programming-Recommendations" class="headerlink" title="Programming Recommendations"></a>Programming Recommendations</h2><ul><li><p>Comparisons to singletons like <em>None</em> should always be done with <strong>is</strong> or <strong>is not</strong>, never the equality operators.</p><figure class="highlight py"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> user <span class="keyword">is</span> <span class="literal">None</span>:  <span class="comment"># Use that</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> user == <span class="literal">None</span>   <span class="comment"># Don't use that</span></span><br></pre></td></tr></table></figure></li><li><p>For sequences, (strings, lists, tuples), use the fact that empty sequences are false. Don’t use the len() function.</p><figure class="highlight py"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> <span class="keyword">not</span> seq:           <span class="comment"># Use that</span></span><br><span class="line"><span class="keyword">if</span> seq:               <span class="comment"># Use that</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> len(seq):          <span class="comment"># Don't use that</span></span><br><span class="line"><span class="keyword">if</span> <span class="keyword">not</span> len(seq):      <span class="comment"># Don't use that</span></span><br></pre></td></tr></table></figure></li><li><p>Don’t compare boolean values to True or False using ==</p><figure class="highlight py"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> greeting:          <span class="comment"># Use that</span></span><br><span class="line"><span class="keyword">if</span> greeting == <span class="literal">True</span>:  <span class="comment"># Don't use that</span></span><br></pre></td></tr></table></figure></li></ul><h2 id="Indentation"><a href="#Indentation" class="headerlink" title="Indentation"></a>Indentation</h2><p><strong>Use spaces</strong>, instead of tabs (your IDE can probably convert tabs automatically to spaces). Taking 2 or 4 spaces are both fine. Just agree a convention in your team. Never mix the indentations.</p><h2 id="Imports"><a href="#Imports" class="headerlink" title="Imports"></a>Imports</h2><p>Put all imports at the top of the file with three sections, each separated by a blank line, in this order:</p><ul><li>System imports</li><li>Third-party imports</li><li>Local source tree imports</li></ul><p>That makes it clear where each module is coming from. Also Imports itself should usually be on separate lines.</p><h2 id="Pylint"><a href="#Pylint" class="headerlink" title="Pylint"></a>Pylint</h2><p><a href="https://www.pylint.org/" target="_blank" rel="noopener">Pylint</a> is a Python static code analysis tool which looks for programming errors and help to enforce the rules of <a href="https://www.python.org/dev/peps/pep-0008/" target="_blank" rel="noopener">PEP 8</a>. Most of the IDE’s have an integration of pylint. Personally I use the <a href="https://www.tensorflow.org/community/contribute/code_style" target="_blank" rel="noopener">TensorFlow code style guide</a>, which is based on <a href="https://www.python.org/dev/peps/pep-0008/" target="_blank" rel="noopener">PEP 8</a> and <a href="https://github.com/google/styleguide/blob/gh-pages/pyguide.md" target="_blank" rel="noopener">Google Python Style Guide</a>. Just download the pylintrc file, which contains all the rules, from e.g. <a href="https://www.tensorflow.org/community/contribute/code_style" target="_blank" rel="noopener">TensorFlow</a> and point your pylint to that file.</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;One of the best practices is, to define a common style guideline. So that it would be much easier to understand a codebase when all the code in it, is in a consistent style. Specially if you are working in a team. PEP (Python Enhancement Proposals) provides a good starting point to define those style guide.&lt;/p&gt;&lt;p&gt;Here are some highlights which are mostly from &lt;a href=&quot;https://www.python.org/dev/peps/pep-0008/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;PEP 8&lt;/a&gt;, but also from other best practices:&lt;/p&gt;&lt;h2 id=&quot;Naming-Conventions&quot;&gt;&lt;a href=&quot;#Naming-Conventions&quot; class=&quot;headerlink&quot; title=&quot;Naming Conventions&quot;&gt;&lt;/a&gt;Naming Conventions&lt;/h2&gt;&lt;p&gt;Avoid one letter variables like &lt;em&gt;x&lt;/em&gt; and &lt;em&gt;y&lt;/em&gt; (Except in very short code blocks). Give your variables and functions a meaningful name and use follow naming convention:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Variables, functions, packages and modules names should be:&lt;/p&gt;&lt;figure class=&quot;highlight py&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;lower_case_with_underscores&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Classes and Exceptions&lt;/p&gt;&lt;figure class=&quot;highlight py&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;CamelCase&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Protected methods&lt;/p&gt;&lt;figure class=&quot;highlight py&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;_single_leading_underscore&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Private methods&lt;/p&gt;&lt;figure class=&quot;highlight py&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;__double_leading_underscore&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Constants&lt;/p&gt;&lt;figure class=&quot;highlight py&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;ALL_CAPS_WITH_UNDERSCORES&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/li&gt;&lt;/ul&gt;
    
    </summary>
    
    
      <category term="Python" scheme="https://rmsol.de/tags/Python/"/>
    
  </entry>
  
  <entry>
    <title>My favorite Visual Studio (VS Code) Extensions</title>
    <link href="https://rmsol.de/2019/08/15/Best-VSCode-Extensions/"/>
    <id>https://rmsol.de/2019/08/15/Best-VSCode-Extensions/</id>
    <published>2019-08-14T22:22:48.000Z</published>
    <updated>2019-08-14T22:25:38.702Z</updated>
    
    <content type="html"><![CDATA[<p>There are a lot of well known extensions like GitLens, Prettier or ESLint, but I would like to show you less known but very helpful extensions.</p><h2 id="Version-Lens"><a href="#Version-Lens" class="headerlink" title="Version Lens"></a><a href="https://marketplace.visualstudio.com/items?itemName=pflannery.vscode-versionlens" target="_blank" rel="noopener">Version Lens</a></h2><p><em>Shows package version information for npm, jspm, dub and dotnet core</em></p><p><img src="https://github.com/vscode-contrib/vscode-versionlens/raw/master/images/animated-preview.gif" alt="&quot;Version Lens&quot;" title="Version Lens"></p><h2 id="Shell-launcher"><a href="#Shell-launcher" class="headerlink" title="Shell launcher"></a><a href="https://marketplace.visualstudio.com/items?itemName=Tyriar.shell-launcher" target="_blank" rel="noopener">Shell launcher</a></h2><p><em>Easily launch multiple shell configurations in the terminal.</em></p><p><img src="https://github.com/Tyriar/vscode-shell-launcher/raw/master/images/quick-pick.png" alt="&quot;Shell launcher&quot;" title="Shell launcher"></p><a id="more"></a><h2 id="Bracket-Pair-Colorizer-2"><a href="#Bracket-Pair-Colorizer-2" class="headerlink" title="Bracket Pair Colorizer 2"></a><a href="https://marketplace.visualstudio.com/items?itemName=CoenraadS.bracket-pair-colorizer-2" target="_blank" rel="noopener">Bracket Pair Colorizer 2</a></h2><p><em>This extension allows matching brackets to be identified with colours. The user can define which tokens to match, and which colours to use.</em></p><p><em>Differences between v1 and v2? v2 Uses the same bracket parsing engine as VSCode, greatly increasing speed and accuracy. A new version was released because settings were cleaned up, breaking backwards compatibility.</em></p><p><img src="https://github.com/CoenraadS/Bracket-Pair-Colorizer-2/raw/master/images/example.png" alt="&quot;Bracket Pair Colorizer 2&quot;" title="Bracket Pair Colorizer 2"></p><h2 id="indent-rainbow"><a href="#indent-rainbow" class="headerlink" title="indent-rainbow"></a><a href="https://marketplace.visualstudio.com/items?itemName=oderwat.indent-rainbow" target="_blank" rel="noopener">indent-rainbow</a></h2><p><em>This extension colorizes the indentation in front of your text alternating four different colors on each step. Some may find it helpful in writing code for Nim or Python.</em></p><p><img src="https://raw.githubusercontent.com/oderwat/vscode-indent-rainbow/master/assets/example.png" alt="&quot;indent-rainbow&quot;" title="indent-rainbow"></p><h2 id="Bookmarks"><a href="#Bookmarks" class="headerlink" title="Bookmarks"></a><a href="https://marketplace.visualstudio.com/items?itemName=alefragnani.Bookmarks" target="_blank" rel="noopener">Bookmarks</a></h2><p><em>It helps you to navigate in your code, moving between important positions easily and quickly. No more need to search for code. It also supports a set of selection commands, which allows you to select bookmarked lines and regions between bookmarked lines. It’s really useful for log file analysis.</em></p><p><img src="https://github.com/alefragnani/vscode-bookmarks/raw/master/images/bookmarks-toggle.png" alt="&quot;Bookmarks&quot;" title="Bookmarks"></p><h2 id="Output-Colorizer"><a href="#Output-Colorizer" class="headerlink" title="Output Colorizer"></a><a href="https://marketplace.visualstudio.com/items?itemName=IBM.output-colorizer" target="_blank" rel="noopener">Output Colorizer</a></h2><p><em>Language extension for VSCode/Bluemix Code that adds syntax colorization for both the output/debug/extensions panel and \</em>.log files.*</p><p><img src="https://raw.githubusercontent.com/IBM-Bluemix/vscode-log-output-colorizer/master/github-assets/screenshot-1.jpg" alt="&quot;Output Colorizer&quot;" title="Output Colorizer"></p><h2 id="TODO-Highlight"><a href="#TODO-Highlight" class="headerlink" title="TODO Highlight"></a><a href="https://marketplace.visualstudio.com/items?itemName=wayou.vscode-todo-highlight" target="_blank" rel="noopener">TODO Highlight</a></h2><p><em>Highlight TODO, FIXME and other annotations within your code.</em></p><blockquote><p>You can also create your own annotations</p></blockquote><p><img src="https://github.com/wayou/vscode-todo-highlight/raw/master/assets/material-night-eighties.png" alt="&quot;TODO Highlight&quot;" title="TODO Highlight"></p><h2 id="Import-Cost"><a href="#Import-Cost" class="headerlink" title="Import Cost"></a><a href="https://marketplace.visualstudio.com/items?itemName=wix.vscode-import-cost" target="_blank" rel="noopener">Import Cost</a></h2><p><em>This extension will display inline in the editor the size of the imported package. The extension utilizes webpack with babili-webpack-plugin in order to detect the imported size.</em></p><p><img src="https://file-wkbcnlcvbn.now.sh/import-cost.gif" alt="&quot;Import Cost&quot;" title="Import Cost"></p><h2 id="Code-Spell-Checker"><a href="#Code-Spell-Checker" class="headerlink" title="Code Spell Checker"></a><a href="https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker" target="_blank" rel="noopener">Code Spell Checker</a></h2><p><em>A basic spell checker that works well with camelCase code.<br>The goal of this spell checker is to help catch common spelling errors while keeping the number of false positives low.</em></p><p><img src="https://raw.githubusercontent.com/streetsidesoftware/vscode-spell-checker/master/packages/client/images/example.gif" alt="&quot;Code Spell Checker&quot;" title="Code Spell Checker"></p><h2 id="Path-Intellisense"><a href="#Path-Intellisense" class="headerlink" title="Path Intellisense"></a><a href="https://marketplace.visualstudio.com/items?itemName=christian-kohler.path-intellisense" target="_blank" rel="noopener">Path Intellisense</a></h2><p><em>Visual Studio Code plugin that autocompletes filenames.</em></p><p><img src="https://i.giphy.com/iaHeUiDeTUZuo.gif" alt="&quot;Path Intellisense&quot;" title="Path Intellisense"></p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;There are a lot of well known extensions like GitLens, Prettier or ESLint, but I would like to show you less known but very helpful extensions.&lt;/p&gt;&lt;h2 id=&quot;Version-Lens&quot;&gt;&lt;a href=&quot;#Version-Lens&quot; class=&quot;headerlink&quot; title=&quot;Version Lens&quot;&gt;&lt;/a&gt;&lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=pflannery.vscode-versionlens&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Version Lens&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;em&gt;Shows package version information for npm, jspm, dub and dotnet core&lt;/em&gt;&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://github.com/vscode-contrib/vscode-versionlens/raw/master/images/animated-preview.gif&quot; alt=&quot;&amp;quot;Version Lens&amp;quot;&quot; title=&quot;Version Lens&quot;&gt;&lt;/p&gt;&lt;h2 id=&quot;Shell-launcher&quot;&gt;&lt;a href=&quot;#Shell-launcher&quot; class=&quot;headerlink&quot; title=&quot;Shell launcher&quot;&gt;&lt;/a&gt;&lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=Tyriar.shell-launcher&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Shell launcher&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;em&gt;Easily launch multiple shell configurations in the terminal.&lt;/em&gt;&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://github.com/Tyriar/vscode-shell-launcher/raw/master/images/quick-pick.png&quot; alt=&quot;&amp;quot;Shell launcher&amp;quot;&quot; title=&quot;Shell launcher&quot;&gt;&lt;/p&gt;
    
    </summary>
    
    
      <category term="VSCode" scheme="https://rmsol.de/tags/VSCode/"/>
    
  </entry>
  
  <entry>
    <title>ESP8266 Weather Station / Temperature Sensor</title>
    <link href="https://rmsol.de/2019/06/18/ESP-Weather/"/>
    <id>https://rmsol.de/2019/06/18/ESP-Weather/</id>
    <published>2019-06-18T20:29:15.000Z</published>
    <updated>2019-09-11T19:47:02.447Z</updated>
    
    <content type="html"><![CDATA[<h2 id="Introduction"><a href="#Introduction" class="headerlink" title="Introduction"></a>Introduction</h2><p>ESP’s are great to give your sensors the possibility to extract the sensor data, because of the on-board WIFI chip, which can connect to your network.<br>Imagine you have multiple sensors, and you would like to access the measured data and show it in Home Assistant. You can either spin up a web server on your ESP and pull the data or send data from your ESP to your Home Assistant.</p><p>The advantage of the push strategy is power saving through deep sleep mode of ESP, which will be explained later.</p><h2 id="Components"><a href="#Components" class="headerlink" title="Components"></a>Components</h2><ul><li>The <a href="https://arduinomodules.info/ky-013-analog-temperature-sensor-module/" target="_blank" rel="noopener">KY-013</a> Analog Temperature Sensor</li><li>ESP8266 from mine <a href="https://rmsol.de/2019/02/03/ESP-Overview/">previous post</a></li></ul><p>In my case the <strong>+</strong> and <strong>-</strong> pin label was incorrect and I had to swap them. So that the orange wire is attached to <strong>+</strong> (and not <strong>-</strong>).</p><a id="more"></a> <img src="/2019/06/18/ESP-Weather/keyes_named.jpg" width="450" height="250" title="Analog Temperature Sensor Keyes"><h2 id="Weather-Station"><a href="#Weather-Station" class="headerlink" title="Weather Station"></a>Weather Station</h2><p>The temperature sensor will be connected with the ESP over the GPIO’s. The ESP itself will send over WIFI the data (temperature) to your Home Assistant <a href="https://en.wikipedia.org/wiki/MQTT" target="_blank" rel="noopener">MQTT (Message Queuing Telemetry Transport)</a>. The Mosquitto broker Add-on (MQTT) need to be activated on your Home Assistant, in Add-on Store Overview. Don’t forget to set the username and password in MQTT config.</p><h3 id="Assembling"><a href="#Assembling" class="headerlink" title="Assembling"></a>Assembling</h3><table><thead><tr><th>WIRE</th><th>PIN</th></tr></thead><tbody><tr><td>yellow</td><td>G (ground)</td></tr><tr><td>orange</td><td>3V3</td></tr><tr><td>cyan</td><td>A0</td></tr></tbody></table><img src="/2019/06/18/ESP-Weather/ground.jpg" width="450" height="250" title="ESP8266 ground connection"> <img src="/2019/06/18/ESP-Weather/w_backside.jpg" width="450" height="250" title="ESP8266 backside"><h3 id="Code"><a href="#Code" class="headerlink" title="Code"></a>Code</h3><blockquote><p>Don’t forget to set WIFI SSID, WIFI Password and also MQTT Server IP, username and password in the code.</p></blockquote><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;ESP8266WiFi.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;PubSubClient.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;ArduinoJson.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> MQTT_VERSION MQTT_VERSION_3_1_1</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// Wifi: SSID and password</span></span><br><span class="line"><span class="keyword">const</span> <span class="keyword">char</span>* WIFI_SSID = <span class="string">"WifiName"</span>;</span><br><span class="line"><span class="keyword">const</span> <span class="keyword">char</span>* WIFI_PASSWORD = <span class="string">"WifiPassword"</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// MQTT: ID, server IP, port, username and password</span></span><br><span class="line"><span class="keyword">const</span> PROGMEM <span class="keyword">char</span>* MQTT_CLIENT_ID = <span class="string">"office_temp"</span>;</span><br><span class="line"><span class="keyword">const</span> PROGMEM <span class="keyword">char</span>* MQTT_SERVER_IP = <span class="string">"192.168.*.*"</span>;</span><br><span class="line"><span class="keyword">const</span> PROGMEM <span class="keyword">uint16_t</span> MQTT_SERVER_PORT = <span class="number">1883</span>;</span><br><span class="line"><span class="keyword">const</span> PROGMEM <span class="keyword">char</span>* MQTT_USER = <span class="string">"mqttUsername"</span>;</span><br><span class="line"><span class="keyword">const</span> PROGMEM <span class="keyword">char</span>* MQTT_PASSWORD = <span class="string">"mqttPassword"</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// MQTT: topic</span></span><br><span class="line"><span class="keyword">const</span> PROGMEM <span class="keyword">char</span>* MQTT_SENSOR_TOPIC = <span class="string">"office/sensor1"</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// sleeping time</span></span><br><span class="line"><span class="keyword">const</span> PROGMEM <span class="keyword">uint16_t</span> SLEEPING_TIME_IN_SECONDS = <span class="number">600</span>; <span class="comment">// 10 minutes x 60 seconds</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// Sensor and led</span></span><br><span class="line"><span class="keyword">const</span> <span class="keyword">int</span> led = <span class="number">13</span>;</span><br><span class="line"><span class="keyword">const</span> <span class="keyword">int</span> sensorPin = <span class="number">0</span>; <span class="comment">// select the input pin for the potentiometer</span></span><br><span class="line"></span><br><span class="line">WiFiClient wifiClient;</span><br><span class="line"><span class="function">PubSubClient <span class="title">client</span><span class="params">(wifiClient)</span></span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// function called to publish the temperature</span></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">publishData</span><span class="params">(String p_temperature)</span> </span>&#123;</span><br><span class="line">  StaticJsonBuffer&lt;<span class="number">200</span>&gt; jsonBuffer;</span><br><span class="line">  JsonObject&amp; root = jsonBuffer.createObject();</span><br><span class="line">  root[<span class="string">"temperature"</span>] = p_temperature;</span><br><span class="line">  root.prettyPrintTo(Serial);</span><br><span class="line">  Serial.println(<span class="string">""</span>);</span><br><span class="line">  <span class="keyword">char</span> data[<span class="number">200</span>];</span><br><span class="line">  root.printTo(data, root.measureLength() + <span class="number">1</span>);</span><br><span class="line">  client.publish(MQTT_SENSOR_TOPIC, data, <span class="literal">true</span>);</span><br><span class="line">  yield();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// function called when a MQTT message arrived</span></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">callback</span><span class="params">(<span class="keyword">char</span>* p_topic, byte* p_payload, <span class="keyword">unsigned</span> <span class="keyword">int</span> p_length)</span> </span>&#123;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">reconnect</span><span class="params">()</span> </span>&#123;</span><br><span class="line">  <span class="comment">// Loop until we're reconnected</span></span><br><span class="line">  <span class="keyword">while</span> (!client.connected()) &#123;</span><br><span class="line">    Serial.println(<span class="string">"INFO: Attempting MQTT connection..."</span>);</span><br><span class="line">    <span class="comment">// Attempt to connect</span></span><br><span class="line">    <span class="keyword">if</span> (client.connect(MQTT_CLIENT_ID, MQTT_USER, MQTT_PASSWORD)) &#123;</span><br><span class="line">      Serial.println(<span class="string">"INFO: connected"</span>);</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      Serial.print(<span class="string">"ERROR: failed, rc="</span>);</span><br><span class="line">      Serial.print(client.state());</span><br><span class="line">      Serial.println(<span class="string">"DEBUG: try again in 5 seconds"</span>);</span><br><span class="line">      <span class="comment">// Wait 5 seconds before retrying</span></span><br><span class="line">      delay(<span class="number">5000</span>);</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">double</span> <span class="title">Thermistor</span><span class="params">(<span class="keyword">int</span> RawADC)</span> </span>&#123;</span><br><span class="line">  <span class="keyword">double</span> Temp;</span><br><span class="line">  Temp = <span class="built_in">log</span>(((<span class="number">10240000</span> / RawADC) - <span class="number">9000</span>));</span><br><span class="line">  Temp = <span class="number">1</span> / (<span class="number">0.001129148</span> + (<span class="number">0.000234125</span> + (<span class="number">0.0000000876741</span> * Temp * Temp )) * Temp );</span><br><span class="line">  Temp = Temp - <span class="number">273.15</span>; <span class="comment">// Convert Kelvin to Celcius</span></span><br><span class="line">  <span class="keyword">return</span> Temp;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">setup</span><span class="params">()</span> </span>&#123;</span><br><span class="line">  <span class="comment">// init the serial</span></span><br><span class="line">  Serial.begin(<span class="number">115200</span>);</span><br><span class="line"></span><br><span class="line">  <span class="comment">// init the WiFi connection</span></span><br><span class="line">  Serial.println();</span><br><span class="line">  Serial.println();</span><br><span class="line">  Serial.print(<span class="string">"INFO: Connecting to "</span>);</span><br><span class="line">  WiFi.mode(WIFI_STA);</span><br><span class="line">  Serial.println(WIFI_SSID);</span><br><span class="line">  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);</span><br><span class="line"></span><br><span class="line">  <span class="keyword">while</span> (WiFi.status() != WL_CONNECTED) &#123;</span><br><span class="line">    delay(<span class="number">500</span>);</span><br><span class="line">    Serial.print(<span class="string">"."</span>);</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  Serial.println(<span class="string">""</span>);</span><br><span class="line">  Serial.println(<span class="string">"INFO: WiFi connected"</span>);</span><br><span class="line">  Serial.println(<span class="string">"INFO: IP address: "</span>);</span><br><span class="line">  Serial.println(WiFi.localIP());</span><br><span class="line"></span><br><span class="line">  <span class="comment">// init the MQTT connection</span></span><br><span class="line">  client.setServer(MQTT_SERVER_IP, MQTT_SERVER_PORT);</span><br><span class="line">  client.setCallback(callback);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">loop</span><span class="params">()</span> </span>&#123;</span><br><span class="line">  <span class="keyword">if</span> (!client.connected()) &#123;</span><br><span class="line">    reconnect();</span><br><span class="line">  &#125;</span><br><span class="line">  client.loop();</span><br><span class="line"></span><br><span class="line">  digitalWrite(led, <span class="number">1</span>);</span><br><span class="line">  publishData(String(Thermistor(analogRead(sensorPin)), <span class="number">2</span>));</span><br><span class="line">  digitalWrite(led, <span class="number">0</span>);</span><br><span class="line"></span><br><span class="line">  Serial.println(<span class="string">"INFO: Closing the MQTT connection"</span>);</span><br><span class="line">  client.disconnect();</span><br><span class="line"></span><br><span class="line">  Serial.println(<span class="string">"INFO: Closing the Wifi connection"</span>);</span><br><span class="line">  WiFi.disconnect();</span><br><span class="line"></span><br><span class="line">  ESP.deepSleep(SLEEPING_TIME_IN_SECONDS * <span class="number">1000000</span>, WAKE_RF_DEFAULT);</span><br><span class="line">  delay(<span class="number">500</span>); <span class="comment">// wait for deep sleep to happen</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="Home-Assistant-Config"><a href="#Home-Assistant-Config" class="headerlink" title="Home Assistant Config"></a>Home Assistant Config</h2><p>To see the temperature in Home Assistant web interface, we have to add the sensor to configuration.yaml like that:</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Sensors</span></span><br><span class="line"><span class="attr">sensor:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="attr">platform:</span> <span class="string">mqtt</span></span><br><span class="line">    <span class="attr">name:</span> <span class="string">Office</span> <span class="string">Temperature</span></span><br><span class="line">    <span class="attr">state_topic:</span> <span class="string">"office/sensor1"</span></span><br><span class="line">    <span class="attr">value_template:</span> <span class="string">"<span class="template-variable">&#123;&#123; value_json.temperature &#125;&#125;</span>"</span></span><br><span class="line">    <span class="attr">unit_of_measurement:</span> <span class="string">'°C'</span></span><br></pre></td></tr></table></figure><p>It will look like that in your interface:</p><img src="/2019/06/18/ESP-Weather/office_temp2.jpg" title="Home assistant Office temperature"><h2 id="Deep-Sleep"><a href="#Deep-Sleep" class="headerlink" title="Deep Sleep"></a>Deep Sleep</h2><p>ESP provides an excellent power saving feature through the deep sleep mode.<br>Deep sleep mode turns off everything except the RST pin, which is required to turn the ESP on again.<br>The following steps will be done within the code:</p><ul><li>ESP will be started</li><li>Connecting to WIFI</li><li>Measure the temperature with the sensor</li><li>Send the data to MQTT</li><li>Go in deep sleep mode (turn everything off)</li><li>Restart the ESP once the timer ends (which is set in the code)</li></ul><blockquote><p>You need an additional wire from RST to D0 (purple wire in my case) to have that feature work.</p></blockquote><img src="/2019/06/18/ESP-Weather/w_named_sleep.jpg" width="450" height="250" title="ESP8266 sleep mode">]]></content>
    
    <summary type="html">
    
      &lt;h2 id=&quot;Introduction&quot;&gt;&lt;a href=&quot;#Introduction&quot; class=&quot;headerlink&quot; title=&quot;Introduction&quot;&gt;&lt;/a&gt;Introduction&lt;/h2&gt;&lt;p&gt;ESP’s are great to give your sensors the possibility to extract the sensor data, because of the on-board WIFI chip, which can connect to your network.&lt;br&gt;Imagine you have multiple sensors, and you would like to access the measured data and show it in Home Assistant. You can either spin up a web server on your ESP and pull the data or send data from your ESP to your Home Assistant.&lt;/p&gt;&lt;p&gt;The advantage of the push strategy is power saving through deep sleep mode of ESP, which will be explained later.&lt;/p&gt;&lt;h2 id=&quot;Components&quot;&gt;&lt;a href=&quot;#Components&quot; class=&quot;headerlink&quot; title=&quot;Components&quot;&gt;&lt;/a&gt;Components&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;The &lt;a href=&quot;https://arduinomodules.info/ky-013-analog-temperature-sensor-module/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;KY-013&lt;/a&gt; Analog Temperature Sensor&lt;/li&gt;&lt;li&gt;ESP8266 from mine &lt;a href=&quot;https://rmsol.de/2019/02/03/ESP-Overview/&quot;&gt;previous post&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;In my case the &lt;strong&gt;+&lt;/strong&gt; and &lt;strong&gt;-&lt;/strong&gt; pin label was incorrect and I had to swap them. So that the orange wire is attached to &lt;strong&gt;+&lt;/strong&gt; (and not &lt;strong&gt;-&lt;/strong&gt;).&lt;/p&gt;
    
    </summary>
    
    
      <category term="ESP8266" scheme="https://rmsol.de/tags/ESP8266/"/>
    
      <category term="Home Assistant" scheme="https://rmsol.de/tags/Home-Assistant/"/>
    
  </entry>
  
  <entry>
    <title>Home Assistant - Smart Life components</title>
    <link href="https://rmsol.de/2019/02/18/Home-Assistant-Smart-Life/"/>
    <id>https://rmsol.de/2019/02/18/Home-Assistant-Smart-Life/</id>
    <published>2019-02-17T23:31:33.000Z</published>
    <updated>2019-09-11T19:31:50.425Z</updated>
    
    <content type="html"><![CDATA[<p>Home Assistant unfortunately doesn’t support Smart Life components (yet) (e.g. Switches from <a href="https://amzn.to/2Gv2mV8" target="_blank" rel="noopener">Gosund</a>, <a href="https://amzn.to/2SDjajo" target="_blank" rel="noopener">COOSA</a> or <a href="https://amzn.to/2UYxdwE" target="_blank" rel="noopener">Teckin</a>), but fortunately <a href="https://ifttt.com/" target="_blank" rel="noopener">IFTTT</a> works great with Smart Life components, which can be connected to Home Assistant.</p><img src="/2019/02/18/Home-Assistant-Smart-Life/components.jpg" title="Components"><p>In my example, I will show you how to turn on/off lights by using Teckin Switches with help of IFTTT. The result in Home Assistant will like that:</p><img src="/2019/02/18/Home-Assistant-Smart-Life/HA_dashboard.jpg" title="Home Assistant Dashboard"><a id="more"></a><h1 id="UPDATE-2019-03-06-Tuya-Component"><a href="#UPDATE-2019-03-06-Tuya-Component" class="headerlink" title="UPDATE - 2019-03-06 - Tuya Component"></a>UPDATE - 2019-03-06 - Tuya Component</h1><p>Another, and probably the easiest way is to use Smart Life components is by using <a href="https://www.home-assistant.io/components/tuya/" target="_blank" rel="noopener">Tuya component</a>.<br>Just Install <a href="https://play.google.com/store/apps/details?id=com.tuya.smart&hl=en" target="_blank" rel="noopener">Tuya app</a>, create an account, and configure your Smart Life components.<br>It is similar to the Smart Life app.<br>Additionally add the tuya config to your configuration file:</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">tuya:</span></span><br><span class="line">  <span class="attr">username:</span> <span class="string">your@email</span></span><br><span class="line">  <span class="attr">password:</span> <span class="string">yourPassword</span></span><br><span class="line">  <span class="attr">country_code:</span> <span class="number">49</span> <span class="comment"># 49 stands for germany</span></span><br></pre></td></tr></table></figure><h2 id="IFTTT-and-Smart-Life"><a href="#IFTTT-and-Smart-Life" class="headerlink" title="IFTTT and Smart Life"></a>IFTTT and Smart Life</h2><p>IFTTT is a great project, where you can connect your apps and services with each others.<br>Check the <a href="https://ifttt.com/discover" target="_blank" rel="noopener">IFTTT discovery</a> page, to find out which services/apps are supported and there applets.</p><p>At first we connect IFTTT with Smart Life <a href="https://ifttt.com/smartlife" target="_blank" rel="noopener">here</a>.<br>As next, we connect IFTTT with Home Assistant. You can find setting up steps <a href="https://www.home-assistant.io/components/ifttt/" target="_blank" rel="noopener">here</a>.</p><h2 id="Home-Assistant-and-IFTTT"><a href="#Home-Assistant-and-IFTTT" class="headerlink" title="Home Assistant and IFTTT"></a>Home Assistant and IFTTT</h2><ul><li>Create in IFTTT a <a href="https://ifttt.com/create" target="_blank" rel="noopener">New Applet</a>, click on <strong>+this</strong>, select <strong>Webhooks</strong>, on choose <strong>Receive a web request</strong>.</li><li>Give the event a name e.g. “big_light_switch_on” for turning the switch on, and click on <strong>Create Trigger</strong>. Later we will also create an event for <em>off</em>.</li><li>Click on <strong>+that</strong>, search for <strong>Smart Life</strong> and select <strong>Turn on</strong>.</li><li>Select your device/group from a list and click on <strong>Create action</strong> and <strong>Finish</strong> on the next screen.</li></ul><p>Repeat the steps for the <strong>Turn off</strong> state.</p><p>You can test it in Home Assistant, by sending the event to the IFTTT service.</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;<span class="string">"event"</span>: <span class="string">"big_light_switch_on"</span>&#125;</span><br></pre></td></tr></table></figure><img src="/2019/02/18/Home-Assistant-Smart-Life/test.jpg" title="Home Assistant Debugging"><blockquote><p>Note that it takes up to 3 seconds (till it will take effect).</p></blockquote><h3 id="Home-Assistant-Configuration"><a href="#Home-Assistant-Configuration" class="headerlink" title="Home Assistant Configuration"></a>Home Assistant Configuration</h3><p>The Configuration for the lights/switches looks like that: (in my case I have two light/switches)<br>Don’t forget to replace the IFTTT key.</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># IFTTT Configuration</span></span><br><span class="line"><span class="attr">ifttt:</span></span><br><span class="line">  <span class="attr">key:</span> <span class="string">xxxxxxxxxxxxxx</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Light Configuration</span></span><br><span class="line"><span class="attr">light:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="attr">platform:</span> <span class="string">template</span></span><br><span class="line">    <span class="attr">lights:</span></span><br><span class="line">      <span class="attr">living_room_small:</span></span><br><span class="line">        <span class="attr">friendly_name:</span> <span class="string">"Small lamp"</span></span><br><span class="line">        <span class="attr">turn_on:</span></span><br><span class="line">          <span class="attr">service:</span> <span class="string">ifttt.trigger</span></span><br><span class="line">          <span class="attr">data:</span></span><br><span class="line">            <span class="attr">event:</span> <span class="string">small_light_switch_on</span></span><br><span class="line">            <span class="attr">value1:</span> <span class="string">'on'</span></span><br><span class="line">        <span class="attr">turn_off:</span></span><br><span class="line">          <span class="attr">service:</span> <span class="string">ifttt.trigger</span></span><br><span class="line">          <span class="attr">data:</span></span><br><span class="line">            <span class="attr">event:</span> <span class="string">small_light_switch_off</span></span><br><span class="line">            <span class="attr">value1:</span> <span class="string">'off'</span></span><br><span class="line">      <span class="attr">living_room_big:</span></span><br><span class="line">        <span class="attr">friendly_name:</span> <span class="string">"Big lamp"</span></span><br><span class="line">        <span class="attr">turn_on:</span></span><br><span class="line">          <span class="attr">service:</span> <span class="string">ifttt.trigger</span></span><br><span class="line">          <span class="attr">data:</span></span><br><span class="line">            <span class="attr">event:</span> <span class="string">big_light_switch_on</span></span><br><span class="line">            <span class="attr">value1:</span> <span class="string">'on'</span></span><br><span class="line">        <span class="attr">turn_off:</span></span><br><span class="line">          <span class="attr">service:</span> <span class="string">ifttt.trigger</span></span><br><span class="line">          <span class="attr">data:</span></span><br><span class="line">            <span class="attr">event:</span> <span class="string">big_light_switch_off</span></span><br><span class="line">            <span class="attr">value1:</span> <span class="string">'off'</span></span><br></pre></td></tr></table></figure><h2 id="Home-Assistant-UI"><a href="#Home-Assistant-UI" class="headerlink" title="Home Assistant UI"></a>Home Assistant UI</h2><p>Here is an example of, how you can create a Card for your lights:</p><img src="/2019/02/18/Home-Assistant-Smart-Life/HA_card_configuration.jpg" title="Home Assistant Card Configuration">]]></content>
    
    <summary type="html">
    
      &lt;p&gt;Home Assistant unfortunately doesn’t support Smart Life components (yet) (e.g. Switches from &lt;a href=&quot;https://amzn.to/2Gv2mV8&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Gosund&lt;/a&gt;, &lt;a href=&quot;https://amzn.to/2SDjajo&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;COOSA&lt;/a&gt; or &lt;a href=&quot;https://amzn.to/2UYxdwE&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Teckin&lt;/a&gt;), but fortunately &lt;a href=&quot;https://ifttt.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;IFTTT&lt;/a&gt; works great with Smart Life components, which can be connected to Home Assistant.&lt;/p&gt;&lt;img src=&quot;/2019/02/18/Home-Assistant-Smart-Life/components.jpg&quot; title=&quot;Components&quot;&gt;&lt;p&gt;In my example, I will show you how to turn on/off lights by using Teckin Switches with help of IFTTT. The result in Home Assistant will like that:&lt;/p&gt;&lt;img src=&quot;/2019/02/18/Home-Assistant-Smart-Life/HA_dashboard.jpg&quot; title=&quot;Home Assistant Dashboard&quot;&gt;
    
    </summary>
    
    
      <category term="Home Assistant" scheme="https://rmsol.de/tags/Home-Assistant/"/>
    
      <category term="Raspberry Pi" scheme="https://rmsol.de/tags/Raspberry-Pi/"/>
    
  </entry>
  
  <entry>
    <title>ESP8266 Overview - Arduino IDE Setup</title>
    <link href="https://rmsol.de/2019/02/03/ESP-Overview/"/>
    <id>https://rmsol.de/2019/02/03/ESP-Overview/</id>
    <published>2019-02-02T23:13:08.000Z</published>
    <updated>2019-09-11T19:29:24.012Z</updated>
    
    <content type="html"><![CDATA[<p><a href="https://en.wikipedia.org/wiki/ESP8266" target="_blank" rel="noopener">ESP8266</a> is a low cost (2-3$ in begin of 2019) WIFI microchip with a 80/160 MHz CPU, which will be used for a lot of DIY projects.<br>If you are looking for more powerful microchip, or you need Bluetooth capability, check out the successor <a href="https://en.wikipedia.org/wiki/ESP32" target="_blank" rel="noopener">ESP32</a>.</p><p>I bought the “D1 Mini” model of ESP8266 with 4MB flash (you can get them e.g. <a href="http://s.click.aliexpress.com/e/cSdQBlBE" target="_blank" rel="noopener">here</a>).</p><blockquote><p>Note: It is not the WeMos D1 Mini, but a copy of it. The PIN diagram is the same, which you can find <a href="https://escapequotes.net/esp8266-wemos-d1-mini-pins-and-diagram/" target="_blank" rel="noopener">here</a>.</p></blockquote><img src="/2019/02/03/ESP-Overview/esp_wavgat.jpg"><a id="more"></a><h2 id="ESP8266-Firmware-and-Use-Case-Examples"><a href="#ESP8266-Firmware-and-Use-Case-Examples" class="headerlink" title="ESP8266 Firmware and Use Case Examples"></a>ESP8266 Firmware and Use Case Examples</h2><p>There are many Firmware/SDKs for the ESP8266. My favorites are:</p><ul><li><a href="https://github.com/esp8266/Arduino" target="_blank" rel="noopener">Arduino</a> - C++ based firmware</li><li><a href="https://www.nodemcu.com/index_en.html" target="_blank" rel="noopener">NodeMCU</a> - LUA based firmware</li><li><a href="https://esphomelib.com/" target="_blank" rel="noopener">ESP Home</a> - Made for <a href="https://www.home-assistant.io/" target="_blank" rel="noopener">Home Assistant</a></li><li><a href="https://github.com/letscontrolit/ESPEasy" target="_blank" rel="noopener">ESP Easy</a> - Web based configuration for supported <a href="https://www.letscontrolit.com/wiki/index.php?title=Devices" target="_blank" rel="noopener">sensors/devices</a></li></ul><p>You can find many great use cases for your ESP8266 (DIY Projects):</p><ul><li><a href="https://hackaday.io/projects?tag=ESP8266" target="_blank" rel="noopener">https://hackaday.io/projects?tag=ESP8266</a></li><li><a href="https://circuitdigest.com/esp8266-projects" target="_blank" rel="noopener">https://circuitdigest.com/esp8266-projects</a></li></ul><h2 id="Arduino-Setup"><a href="#Arduino-Setup" class="headerlink" title="Arduino Setup"></a>Arduino Setup</h2><p>If you are used to Arduino IDE, you can use it for ESP8266 as well.<br>Install the <a href="https://www.arduino.cc/en/main/software" target="_blank" rel="noopener">Arduino IDE</a> (if not already installed)</p><h3 id="Steps-for-ESP8266"><a href="#Steps-for-ESP8266" class="headerlink" title="Steps for ESP8266"></a>Steps for ESP8266</h3><ul><li><p>Go to File –&gt; Preferences and add the link <a href="http://arduino.esp8266.com/stable/package_esp8266com_index.json" target="_blank" rel="noopener">http://arduino.esp8266.com/stable/package_esp8266com_index.json</a> to the Additional Boards Manager URLS.</p><img src="/2019/02/03/ESP-Overview/arduino_preferences.jpg"></li><li><p>Go to Tools –&gt; Board –&gt; Boards manager</p><img src="/2019/02/03/ESP-Overview/boards_manager.jpg"></li><li><p>Select <strong>WeMos D1 R1</strong> under Tools –&gt; Board</p><img src="/2019/02/03/ESP-Overview/boards_select.jpg"></li></ul><h2 id="Deployment-with-Arduino"><a href="#Deployment-with-Arduino" class="headerlink" title="Deployment with Arduino"></a>Deployment with Arduino</h2><p>ESP8266 library provides many examples e.g. mini web server or let your LED blink.<br>Just to test your ESP, you could directly deploy/upload an example from Arduino IDE to your ESP.<br>Let’s take <strong>Blink</strong> example:</p><ul><li>Go to File –&gt; Examples –&gt; ESP8266 –&gt; Blink (a new window will be opened)<img src="/2019/02/03/ESP-Overview/blink_example.jpg"></li></ul><p>Connect your ESP with USB to your PC and click in IDE on the “Upload” button in the top-left corner.<br>You should see a blinking ESP LED.</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/ESP8266&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;ESP8266&lt;/a&gt; is a low cost (2-3$ in begin of 2019) WIFI microchip with a 80/160 MHz CPU, which will be used for a lot of DIY projects.&lt;br&gt;If you are looking for more powerful microchip, or you need Bluetooth capability, check out the successor &lt;a href=&quot;https://en.wikipedia.org/wiki/ESP32&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;ESP32&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;I bought the “D1 Mini” model of ESP8266 with 4MB flash (you can get them e.g. &lt;a href=&quot;http://s.click.aliexpress.com/e/cSdQBlBE&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;here&lt;/a&gt;).&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;Note: It is not the WeMos D1 Mini, but a copy of it. The PIN diagram is the same, which you can find &lt;a href=&quot;https://escapequotes.net/esp8266-wemos-d1-mini-pins-and-diagram/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;/blockquote&gt;&lt;img src=&quot;/2019/02/03/ESP-Overview/esp_wavgat.jpg&quot;&gt;
    
    </summary>
    
    
      <category term="ESP8266" scheme="https://rmsol.de/tags/ESP8266/"/>
    
      <category term="Home Assistant" scheme="https://rmsol.de/tags/Home-Assistant/"/>
    
  </entry>
  
  <entry>
    <title>JDBC List of common JDBC Drivers and URL&#39;s</title>
    <link href="https://rmsol.de/2018/09/10/JDBC-Url/"/>
    <id>https://rmsol.de/2018/09/10/JDBC-Url/</id>
    <published>2018-09-10T20:50:48.000Z</published>
    <updated>2019-09-11T19:56:31.044Z</updated>
    
    <content type="html"><![CDATA[<p>Simple collection of common JDBC Drivers and JDBC URL’s, with username and password. If you find any mistakes please let me know.</p><h2 id="MySQL"><a href="#MySQL" class="headerlink" title="MySQL"></a>MySQL</h2><p><strong>JDBC Driver:</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">com.mysql.jdbc.Driver</span><br></pre></td></tr></table></figure><p><strong>JDBC Url:</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">jdbc:mysql://&#123;&#123;hostname&#125;&#125;:&#123;&#123;port&#125;&#125;/&#123;&#123;dataBaseName&#125;&#125;?user=&#123;&#123;username&#125;&#125;&amp;password=&#123;&#123;password&#125;&#125;</span><br></pre></td></tr></table></figure><h2 id="MariaDB"><a href="#MariaDB" class="headerlink" title="MariaDB"></a>MariaDB</h2><p><strong>JDBC Driver:</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">org.mariadb.jdbc.Driver</span><br></pre></td></tr></table></figure><p><strong>JDBC Url:</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">jdbc:mariadb://&#123;&#123;hostname&#125;&#125;:&#123;&#123;port&#125;&#125;/&#123;&#123;dataBaseName&#125;&#125;?user=&#123;&#123;username&#125;&#125;&amp;password=&#123;&#123;password&#125;&#125;</span><br></pre></td></tr></table></figure><a id="more"></a><h2 id="PostgreSQL"><a href="#PostgreSQL" class="headerlink" title="PostgreSQL"></a>PostgreSQL</h2><p><strong>JDBC Driver:</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">org.postgresql.Driver</span><br></pre></td></tr></table></figure><p><strong>JDBC Url:</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">jdbc:postgresql://&#123;&#123;hostname&#125;&#125;:&#123;&#123;port&#125;&#125;/&#123;&#123;dataBaseName&#125;&#125;?user=&#123;&#123;username&#125;&#125;&amp;password=&#123;&#123;password&#125;&#125;</span><br></pre></td></tr></table></figure><h2 id="Microsoft-SQL-Server"><a href="#Microsoft-SQL-Server" class="headerlink" title="Microsoft SQL Server"></a>Microsoft SQL Server</h2><p><strong>JDBC Driver:</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">com.microsoft.sqlserver.jdbc.SQLServerDriver</span><br></pre></td></tr></table></figure><p><strong>JDBC Url:</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">jdbc:sqlserver://&#123;&#123;hostname&#125;&#125;:&#123;&#123;port&#125;&#125;;databaseName=&#123;&#123;dataBaseName&#125;&#125;;user=&#123;&#123;username&#125;&#125;;password=&#123;&#123;password&#125;&#125;</span><br></pre></td></tr></table></figure><h2 id="Oracle-Thin"><a href="#Oracle-Thin" class="headerlink" title="Oracle Thin"></a>Oracle Thin</h2><p><strong>JDBC Driver:</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">oracle.jdbc.driver.OracleDriver</span><br></pre></td></tr></table></figure><p><strong>JDBC Url:</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">jdbc:oracle:thin:&#123;&#123;username&#125;&#125;/&#123;&#123;password&#125;&#125;@//&#123;&#123;hostname&#125;&#125;:&#123;&#123;port&#125;&#125;/&#123;&#123;serviceName&#125;&#125;</span><br></pre></td></tr></table></figure><h2 id="Oracle-OCI"><a href="#Oracle-OCI" class="headerlink" title="Oracle OCI"></a>Oracle OCI</h2><p><strong>JDBC Driver:</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">oracle.jdbc.driver.OracleDriver</span><br></pre></td></tr></table></figure><p><strong>JDBC Url:</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">jdbc:oracle:oci:&#123;&#123;username&#125;&#125;/&#123;&#123;password&#125;&#125;@//&#123;&#123;hostname&#125;&#125;:&#123;&#123;port&#125;&#125;/&#123;&#123;serviceName&#125;&#125;</span><br></pre></td></tr></table></figure><h2 id="IBM-DB2-Express-C"><a href="#IBM-DB2-Express-C" class="headerlink" title="IBM DB2 Express-C"></a>IBM DB2 Express-C</h2><p><strong>JDBC Driver:</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">com.ibm.db2.jcc.DB2Driver</span><br></pre></td></tr></table></figure><p><strong>JDBC Url:</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">jdbc:db2://&#123;&#123;hostname&#125;&#125;:&#123;&#123;port&#125;&#125;/&#123;&#123;dataBaseName&#125;&#125;:user=&#123;&#123;username&#125;&#125;;password=&#123;&#123;password&#125;&#125;</span><br></pre></td></tr></table></figure><h2 id="IBM-DB2-Net"><a href="#IBM-DB2-Net" class="headerlink" title="IBM DB2 Net"></a>IBM DB2 Net</h2><p><strong>JDBC Driver:</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">com.ibm.db2.jdbc.net.DB2Driver</span><br></pre></td></tr></table></figure><p><strong>JDBC Url:</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">jdbc:db2://&#123;&#123;hostname&#125;&#125;:&#123;&#123;port&#125;&#125;/&#123;&#123;dataBaseName&#125;&#125;:user=&#123;&#123;username&#125;&#125;;password=&#123;&#123;password&#125;&#125;</span><br></pre></td></tr></table></figure><h2 id="SAP-HANA"><a href="#SAP-HANA" class="headerlink" title="SAP HANA"></a>SAP HANA</h2><p><strong>JDBC Driver:</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">com.sap.db.jdbc.Driver</span><br></pre></td></tr></table></figure><p><strong>JDBC Url:</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">jdbc:sap://&#123;&#123;hostname&#125;&#125;:&#123;&#123;port&#125;&#125;/?database=&#123;&#123;dataBaseName&#125;&#125;&amp;user=&#123;&#123;username&#125;&#125;&amp;password=&#123;&#123;password&#125;&#125;</span><br></pre></td></tr></table></figure><h2 id="Informix"><a href="#Informix" class="headerlink" title="Informix"></a>Informix</h2><p><strong>JDBC Driver:</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">com.informix.jdbc.IfxDriver</span><br></pre></td></tr></table></figure><p><strong>JDBC Url:</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">jdbc:informix-sqli://&#123;&#123;hostname&#125;&#125;:&#123;&#123;port&#125;&#125;/&#123;&#123;dataBaseName&#125;&#125;:INFORMIXSERVER=&#123;&#123;serverName&#125;&#125;;user=&#123;&#123;username&#125;&#125;;password=&#123;&#123;password&#125;&#125;</span><br></pre></td></tr></table></figure><h2 id="HSQLDB-Mem"><a href="#HSQLDB-Mem" class="headerlink" title="HSQLDB Mem"></a>HSQLDB Mem</h2><p><strong>JDBC Driver:</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">org.hsqldb.jdbc.JDBCDriver</span><br></pre></td></tr></table></figure><p><strong>JDBC Url:</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">jdbc:hsqldb:mem:&#123;&#123;dataBaseName&#125;&#125;</span><br></pre></td></tr></table></figure><h2 id="HSQLDB-File"><a href="#HSQLDB-File" class="headerlink" title="HSQLDB File"></a>HSQLDB File</h2><p><strong>JDBC Driver:</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">org.hsqldb.jdbc.JDBCDriver</span><br></pre></td></tr></table></figure><p><strong>JDBC Url:</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">jdbc:hsqldb:file:&#123;&#123;dataBaseName&#125;&#125;</span><br></pre></td></tr></table></figure><h2 id="H2"><a href="#H2" class="headerlink" title="H2"></a>H2</h2><p><strong>JDBC Driver:</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">org.h2.Driver</span><br></pre></td></tr></table></figure><p><strong>JDBC Url:</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">jdbc:h2:mem:&#123;&#123;dataBaseName&#125;&#125;</span><br></pre></td></tr></table></figure><h2 id="Derby"><a href="#Derby" class="headerlink" title="Derby"></a>Derby</h2><p><strong>JDBC Driver:</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">org.apache.derby.jdbc.EmbeddedDriver</span><br></pre></td></tr></table></figure><p><strong>JDBC Url:</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">jdbc:derby://&#123;&#123;hostname&#125;&#125;:&#123;&#123;port&#125;&#125;/&#123;&#123;dataBaseName&#125;&#125;;create=true;user=&#123;&#123;username&#125;&#125;;password=&#123;&#123;password&#125;&#125;</span><br></pre></td></tr></table></figure><h2 id="Teradata"><a href="#Teradata" class="headerlink" title="Teradata"></a>Teradata</h2><p><strong>JDBC Driver:</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">com.teradata.jdbc.TeraDriver</span><br></pre></td></tr></table></figure><p><strong>JDBC Url:</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">jdbc:teradata://&#123;&#123;hostname&#125;&#125;:&#123;&#123;port&#125;&#125;/database=&#123;&#123;dataBaseName&#125;&#125;,user=&#123;&#123;username&#125;&#125;,password=&#123;&#123;password&#125;&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;Simple collection of common JDBC Drivers and JDBC URL’s, with username and password. If you find any mistakes please let me know.&lt;/p&gt;&lt;h2 id=&quot;MySQL&quot;&gt;&lt;a href=&quot;#MySQL&quot; class=&quot;headerlink&quot; title=&quot;MySQL&quot;&gt;&lt;/a&gt;MySQL&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;JDBC Driver:&lt;/strong&gt;&lt;/p&gt;&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;com.mysql.jdbc.Driver&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;p&gt;&lt;strong&gt;JDBC Url:&lt;/strong&gt;&lt;/p&gt;&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;jdbc:mysql://&amp;#123;&amp;#123;hostname&amp;#125;&amp;#125;:&amp;#123;&amp;#123;port&amp;#125;&amp;#125;/&amp;#123;&amp;#123;dataBaseName&amp;#125;&amp;#125;?user=&amp;#123;&amp;#123;username&amp;#125;&amp;#125;&amp;amp;password=&amp;#123;&amp;#123;password&amp;#125;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;h2 id=&quot;MariaDB&quot;&gt;&lt;a href=&quot;#MariaDB&quot; class=&quot;headerlink&quot; title=&quot;MariaDB&quot;&gt;&lt;/a&gt;MariaDB&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;JDBC Driver:&lt;/strong&gt;&lt;/p&gt;&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;org.mariadb.jdbc.Driver&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;p&gt;&lt;strong&gt;JDBC Url:&lt;/strong&gt;&lt;/p&gt;&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;jdbc:mariadb://&amp;#123;&amp;#123;hostname&amp;#125;&amp;#125;:&amp;#123;&amp;#123;port&amp;#125;&amp;#125;/&amp;#123;&amp;#123;dataBaseName&amp;#125;&amp;#125;?user=&amp;#123;&amp;#123;username&amp;#125;&amp;#125;&amp;amp;password=&amp;#123;&amp;#123;password&amp;#125;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
    
    </summary>
    
    
      <category term="Database" scheme="https://rmsol.de/tags/Database/"/>
    
  </entry>
  
</feed>
