<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Posts on SyxAxis</title>
    <link>https://SyxAxis.github.io/post/</link>
    <description>Recent content in Posts on SyxAxis</description>
    <generator>Hugo -- gohugo.io</generator>
    <copyright>Copyright © 2021, George Johnson; all rights reserved.</copyright>
    <lastBuildDate>Mon, 04 Jan 2021 07:47:22 +0000</lastBuildDate><atom:link href="https://SyxAxis.github.io/post/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>How-To : Build a Docker Host Using Ubuntu Server</title>
      <link>https://SyxAxis.github.io/post/04_build_ubuntu_docker_box/</link>
      <pubDate>Mon, 04 Jan 2021 07:47:22 +0000</pubDate>
      
      <guid>https://SyxAxis.github.io/post/04_build_ubuntu_docker_box/</guid>
      <description>
        
          &lt;p&gt;&lt;strong&gt;The easiest way to get an installation of Docker up and running is to run it on an virtualiased Ubuntu Server build in VirtualBox&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&#34;virtualbox&#34;&gt;VirtualBox&lt;/h2&gt;
&lt;p&gt;For this demo I will be using Oracle&#39;s VirtualBox system to host the Ubuntu server as a Docker host. It&#39;s free and very easy to use.&lt;/p&gt;
&lt;p&gt;Simply install the latest version of Ubuntu server with bog standard defaults, but be sure to install two network interfaces into the VirtualBox host.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Interface 1 - NAT routable to the outside world - So you can download updates and packages plus Docker images.&lt;/li&gt;
&lt;li&gt;Interface 2 - Host-Only - While not mandatory it can be very useful for internal testing to have an interface back to your desktop/laptop box. Class C usually something like 192.168.56.0 network.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;ubuntu-server&#34;&gt;Ubuntu Server&lt;/h2&gt;
&lt;p&gt;Installing the Ubuntu Server just install with defaults but you may wish to hardcode the host-only Class C address to 192.168.56.111 for example.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use /etc/hosts has the hostname matched to the host-only IP addresss&lt;/li&gt;
&lt;li&gt;Example netplan config YAML file is shown below, note the fixed IP address.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;ln&#34;&gt; 1&lt;/span&gt;# This is the network config written by &amp;#39;subiquity&amp;#39;
&lt;span class=&#34;ln&#34;&gt; 2&lt;/span&gt;network:
&lt;span class=&#34;ln&#34;&gt; 3&lt;/span&gt;  ethernets:
&lt;span class=&#34;ln&#34;&gt; 4&lt;/span&gt;    enp0s3:
&lt;span class=&#34;ln&#34;&gt; 5&lt;/span&gt;      dhcp4: true
&lt;span class=&#34;ln&#34;&gt; 6&lt;/span&gt;    enp0s8:
&lt;span class=&#34;ln&#34;&gt; 7&lt;/span&gt;        addresses:
&lt;span class=&#34;ln&#34;&gt; 8&lt;/span&gt;        - 192.168.56.111/24
&lt;span class=&#34;ln&#34;&gt; 9&lt;/span&gt;        nameservers: {}
&lt;span class=&#34;ln&#34;&gt;10&lt;/span&gt;  version: 2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Ensure you do a full update from the source repos and reboot.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;ln&#34;&gt;1&lt;/span&gt;apt-get update -y
&lt;span class=&#34;ln&#34;&gt;2&lt;/span&gt;apt-get upgrade -y
&lt;span class=&#34;ln&#34;&gt;3&lt;/span&gt;apt autoremove -y
&lt;span class=&#34;ln&#34;&gt;4&lt;/span&gt;reboot
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;install-the-docker-ce-from-the-official-docker-repo&#34;&gt;Install the Docker CE from the official Docker Repo&lt;/h2&gt;
&lt;p&gt;First we remove the Docker that might already be installed, update the local packages and then install the pre-requisite packages we&#39;ll need.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;ln&#34;&gt;1&lt;/span&gt;sudo apt-get remove docker docker-engine docker.io
&lt;span class=&#34;ln&#34;&gt;2&lt;/span&gt;sudo apt-get update
&lt;span class=&#34;ln&#34;&gt;3&lt;/span&gt;sudo apt-get install apt-transport-https ca-certificates curl software-properties-common
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Next we get the GPG key used to verify te Docker repo package can be trusted.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;ln&#34;&gt;1&lt;/span&gt;curl -fsSLk https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Next we need to register the Docker repo locally so we can get the packages down, there&#39;s two ways to do it. Either do it with a fixed reference but note this is version specific, I would only do this if you have to.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;ln&#34;&gt;1&lt;/span&gt;sudo add-apt-repository &amp;#34;deb [arch=amd64] https://download.docker.com/linux/ubuntu focal stable&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The preferred option is to let the O/S find the right version.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;ln&#34;&gt;1&lt;/span&gt;sudo add-apt-repository &amp;#34;deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;If you find that you get certificate errors like &amp;quot;Certificate verification failed: The certificate is NOT trusted.&amp;quot;, especially if you&#39;re behind a proxy, then extract the proxy certificates ( do this using a browser like Firefox or Chrome ) and save them to &amp;quot;/usr/local/share/ca-certificates&amp;quot; then run &amp;quot;sudo update-ca-certificates&amp;quot;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Now we&#39;re ready to install Docker from the official repo. This is a good time to add your user to the docker group so you can use docker commands without having to keep using sudo. You use sudo for all your root commands right, you&#39;d never login with root?!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;ln&#34;&gt;1&lt;/span&gt;sudo apt-get update
&lt;span class=&#34;ln&#34;&gt;2&lt;/span&gt;sudo apt-get install docker-ce
&lt;span class=&#34;ln&#34;&gt;3&lt;/span&gt;sudo groupadd docker
&lt;span class=&#34;ln&#34;&gt;4&lt;/span&gt;sudo usermod -aG docker $USER
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Assuming it all went OK, just check the service came up:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;ln&#34;&gt;1&lt;/span&gt;sudo systemctl status docker
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Finally test Docker is working, log out and log back in to make sure the privs take and then issue this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;ln&#34;&gt;1&lt;/span&gt;docker run --rm hello-world
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;using-docker-with-a-proxy-to-get-images&#34;&gt;Using Docker with a Proxy to get Images&lt;/h3&gt;
&lt;p&gt;If you&#39;re behind a proxy then do the following to get docker to work with a proxy.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;ln&#34;&gt;1&lt;/span&gt;sudo mkdir /etc/systemd/system/docker.service.d
&lt;span class=&#34;ln&#34;&gt;2&lt;/span&gt;sudo vi /etc/systemd/system/docker.service.d/http-proxy.conf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Add this to the open file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;ln&#34;&gt;1&lt;/span&gt;[Service]
&lt;span class=&#34;ln&#34;&gt;2&lt;/span&gt;Environment=&amp;#34;HTTP_PROXY=http://172.26.2.10:9480&amp;#34;
&lt;span class=&#34;ln&#34;&gt;3&lt;/span&gt;Environment=&amp;#34;HTTPS_PROXY=http://172.26.2.10:9480&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then restart Docker.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;ln&#34;&gt;1&lt;/span&gt;sudo systemctl daemon-reload
&lt;span class=&#34;ln&#34;&gt;2&lt;/span&gt;sudo sysyemctl stop docker
&lt;span class=&#34;ln&#34;&gt;3&lt;/span&gt;sudo sysyemctl start docker
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        
      </description>
    </item>
    
    <item>
      <title>Powershell - Find All File and Folder Names with Non-ASCII Characters</title>
      <link>https://SyxAxis.github.io/post/03_powershell_find_all_filenames_with_non_ascii/</link>
      <pubDate>Sun, 03 Jan 2021 13:18:28 +0000</pubDate>
      
      <guid>https://SyxAxis.github.io/post/03_powershell_find_all_filenames_with_non_ascii/</guid>
      <description>
        
          &lt;p&gt;&lt;strong&gt;Despite us being a UTF-8 world file and folder names with non-latin chars can still trip processes up.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I was digging through my MP3 collection, around 420,000 tracks ripped from a spareroom that&#39;s just filled to the brim with CDs, and I found that auto-naming had set the file and folder names with some odd characters that made it hard to rename and locate files. Names like &lt;strong&gt;Händel&lt;/strong&gt; are fine, no issue with those as I expect those but when you get something like this &lt;strong&gt;[ \The Mission\Godʼs Own Medicine ]&lt;/strong&gt; it doesn&#39;t look wrong but note the apostrophe is not a standard ASCII one but one from another part of the wonderful UTF-8 selection.&lt;/p&gt;
&lt;p&gt;So how to trace them down quickly, Powershell is always my go-to scripting language on Windows, it is simply the Swiss Army Knife of Windows admin work tools, or Schweizermesser as they say in German speaking countries.&lt;/p&gt;
&lt;p&gt;Scan up the folder structure and pull out the names that have chars that fall beyond the standard simple, original ASCII set.&lt;/p&gt;
&lt;p&gt;Long version for scripting:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;ln&#34;&gt;1&lt;/span&gt;Get-ChildItem -Path &amp;#34;M:\GWJ\MUSIC\&amp;#34; -Recurse | ForEach-Object {
&lt;span class=&#34;ln&#34;&gt;2&lt;/span&gt;    $currFile = $_
&lt;span class=&#34;ln&#34;&gt;3&lt;/span&gt;
&lt;span class=&#34;ln&#34;&gt;4&lt;/span&gt;    if ( $currFile.Name -cmatch &amp;#34;[^\u0000-\u007F]&amp;#34; ) {
&lt;span class=&#34;ln&#34;&gt;5&lt;/span&gt;        $currFile.
&lt;span class=&#34;ln&#34;&gt;6&lt;/span&gt;        Write-Host &amp;#34;FOUND:[$($currFile.FullName)]&amp;#34;
&lt;span class=&#34;ln&#34;&gt;7&lt;/span&gt;    }
&lt;span class=&#34;ln&#34;&gt;8&lt;/span&gt;}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This can be shortened to this if you need a single command verison:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;ln&#34;&gt;1&lt;/span&gt;Get-ChildItem -Path &amp;#34;M:\GWJ\MUSIC\&amp;#34; -Recurse | Where-Object { $_.Name -cmatch &amp;#34;[^\u0000-\u007F]&amp;#34; }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Alternative:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;ln&#34;&gt;1&lt;/span&gt;Get-ChildItem -Path &amp;#34;M:\GWJ\MUSIC\&amp;#34; -Recurse | Where-Object { $_.Name -cmatch &amp;#34;[^\x20-\x7F]&amp;#34; }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
        
      </description>
    </item>
    
    <item>
      <title>Go - EXIF Scanner and Extractor</title>
      <link>https://SyxAxis.github.io/post/02_golang_exif_scanner/</link>
      <pubDate>Sat, 02 Jan 2021 16:05:26 +0000</pubDate>
      
      <guid>https://SyxAxis.github.io/post/02_golang_exif_scanner/</guid>
      <description>
        
          &lt;p&gt;&lt;strong&gt;Using Go to extract EXIF data from Image files&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Extracting EXIF from a single file is easy but suppose you have a huge folder tree with hundreds or thousands of images, what then? Then suppose you have a publishing deadline for a book. What you need is a super fast, efficient language to do the job for you. Golang is what you need!&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Have you ever wondered how when you take photos using your mobilephone and then upload them to your favourite website, how does it know so much about the phote image file? The secret is the EXIF data stored within the JPG images you capture and then upload. The EXIF data contains the most critical info needed about an image, the camera, the lens, the focal length, aperture size, time and date of the shot and even the GPS info. This is the most basic info, on top of that there are extensions for the IPTC info which has tons more info like keyword trees, descriptions, copyright, all valuable stuff you store and maintain using software like Adobe Lightroom.&lt;/p&gt;
&lt;p&gt;When I worked on my first photo book for FotoVue I&#39;d shot and edited around 3,000 images files, from those we selected around 1,000 images to go into the book. The books FotoVue produce are for photographers and that means you need to have the key informaiton like location, camera, lens, focal length, aperture, ISO, all that good stuff and one place that&#39;s stored is in the EXIF of every image. When you edit all the info is kept and stored so it can be used to correctly catalogue your images.&lt;/p&gt;
&lt;p&gt;Getting the EXIF from a single image is dead easy, right-click on it select Propeties ( Windows ) or &amp;quot;Get Info&amp;quot; ( Mac ), there it is. How the heck do you do that for 1,000+ images that are scattered through sub-folders? The London book I worked on had 12 chapters with 14 locations per chapter, that&#39;s around 200+ sub-folders. We needed the key critical EXIF data into something we could pass to the page designers, so we needed the filename plus the EXIF data, they would then copy and paste it into the 1,000 images in the book&#39;s layout.&lt;/p&gt;
&lt;p&gt;We thought Lightroom could be used to get the info but despite it begin one of the best photo image organisers available it&#39;s useless at allowing you access to it&#39;s internal database, it demands you jump through some severley archais hoops using LUA, I&#39;ve no wish to learn a dead language from scratch just to get a CSV.&lt;/p&gt;
&lt;h2 id=&#34;enter-the-gopher&#34;&gt;Enter the Gopher!&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;https://SyxAxis.github.io/images/golang_gopher_with_camera.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;Luckily Go is a best damned language on the planet and I needed a simple Go project to get me started as I was learning Go.&lt;/p&gt;
&lt;h2 id=&#34;go-exif-libary&#34;&gt;Go-Exif Libary&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/dsoprea/go-exif&#34;&gt;DSOprea go-exif library&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We need a library that can extract EXIF data from any JPG file and hand it over in a simple text based format.&lt;/p&gt;
&lt;p&gt;The examples supplied with the library are superb and ready to be built, so I stripped out the requied code and then built myself a file-folder scanner using the &lt;strong&gt;filewalk&lt;/strong&gt; function from the standard library. From that I was able to put together a suitable struct, read the info from file in a tree and dump the whole damned thing back out to a CSV file that could be loaded into any suitable spreadsheet app.&lt;/p&gt;
&lt;p&gt;You can find the code for my EXIF scanner extractor here: &lt;a href=&#34;https://github.com/SyxAxis/GOEXIFExtractor&#34;&gt;GOExifExtractor on Github&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;the-goexifextractor-utility&#34;&gt;The GOExifExtractor Utility&lt;/h2&gt;
&lt;p&gt;The reason for choosing Go was that I use Windows and Linux but others may use Mac, most togs will use Macs to manage photos and while it&#39;s a command line only util I needed a way to use it on any of the major platforms, Go can cross compile, so that&#39;s sorted.&lt;/p&gt;
&lt;p&gt;The utility allows you to choose the fields you like to extract or simply all of them, filling in blanks where it can. The most common EXIF fields are shown below:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;ln&#34;&gt; 1&lt;/span&gt;constEXIFFields = []string{
&lt;span class=&#34;ln&#34;&gt; 2&lt;/span&gt;		&amp;#34;ImageDescription&amp;#34;,
&lt;span class=&#34;ln&#34;&gt; 3&lt;/span&gt;		&amp;#34;Make&amp;#34;,
&lt;span class=&#34;ln&#34;&gt; 4&lt;/span&gt;		&amp;#34;Model&amp;#34;,
&lt;span class=&#34;ln&#34;&gt; 5&lt;/span&gt;		&amp;#34;Software&amp;#34;,
&lt;span class=&#34;ln&#34;&gt; 6&lt;/span&gt;		&amp;#34;DateTime&amp;#34;,
&lt;span class=&#34;ln&#34;&gt; 7&lt;/span&gt;		&amp;#34;Artist&amp;#34;,
&lt;span class=&#34;ln&#34;&gt; 8&lt;/span&gt;		&amp;#34;Copyright&amp;#34;,
&lt;span class=&#34;ln&#34;&gt; 9&lt;/span&gt;		&amp;#34;ExposureTime&amp;#34;,
&lt;span class=&#34;ln&#34;&gt;10&lt;/span&gt;		&amp;#34;FNumber&amp;#34;,
&lt;span class=&#34;ln&#34;&gt;11&lt;/span&gt;		&amp;#34;ISOSpeedRatings&amp;#34;,
&lt;span class=&#34;ln&#34;&gt;12&lt;/span&gt;		&amp;#34;DateTimeOriginal&amp;#34;,
&lt;span class=&#34;ln&#34;&gt;13&lt;/span&gt;		&amp;#34;DateTimeDigitized&amp;#34;,
&lt;span class=&#34;ln&#34;&gt;14&lt;/span&gt;		&amp;#34;FocalLength&amp;#34;,
&lt;span class=&#34;ln&#34;&gt;15&lt;/span&gt;		&amp;#34;CameraOwnerName&amp;#34;,
&lt;span class=&#34;ln&#34;&gt;16&lt;/span&gt;		&amp;#34;BodySerialNumber&amp;#34;,
&lt;span class=&#34;ln&#34;&gt;17&lt;/span&gt;		&amp;#34;LensModel&amp;#34;,
&lt;span class=&#34;ln&#34;&gt;18&lt;/span&gt;		&amp;#34;GPSLatitudeRef&amp;#34;,
&lt;span class=&#34;ln&#34;&gt;19&lt;/span&gt;		&amp;#34;GPSLatitude&amp;#34;,
&lt;span class=&#34;ln&#34;&gt;20&lt;/span&gt;		&amp;#34;GPSLongitudeRef&amp;#34;,
&lt;span class=&#34;ln&#34;&gt;21&lt;/span&gt;		&amp;#34;GPSLongitude&amp;#34;,
&lt;span class=&#34;ln&#34;&gt;22&lt;/span&gt;	}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The folder scanned it really simple, nothing more than a simple JPG scanner. ( yeah hardcoded JPG only, it was my first Go project! )&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;ln&#34;&gt;1&lt;/span&gt;err := filepath.Walk(filepathArg, func(path string, info os.FileInfo, err error) error {
&lt;span class=&#34;ln&#34;&gt;2&lt;/span&gt;		if filepath.Ext(path) == &amp;#34;.jpg&amp;#34; || filepath.Ext(path) == &amp;#34;.JPG&amp;#34; {
&lt;span class=&#34;ln&#34;&gt;3&lt;/span&gt;			files = append(files, path)
&lt;span class=&#34;ln&#34;&gt;4&lt;/span&gt;		}
&lt;span class=&#34;ln&#34;&gt;5&lt;/span&gt;		return nil
&lt;span class=&#34;ln&#34;&gt;6&lt;/span&gt;	})
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;One thing that I did have problems with was how the raw EXIF data is stored from some attributes, the two problematic ones were &lt;strong&gt;Exposuretime&lt;/strong&gt; and &lt;strong&gt;Aperture&lt;/strong&gt; setting sometimes called the F-number, often expressed as &lt;strong&gt;f/16&lt;/strong&gt; for example.&lt;/p&gt;
&lt;h4 id=&#34;exposure&#34;&gt;Exposure&lt;/h4&gt;
&lt;p&gt;Exposure is stored in EXIF as an expression of a fraction of a second. Sub-second that is something like 1/128, which is 1/128th of a second. That&#39;s easy enough.  However anything longer than a second, long exposure images can be minutes, is stored as fraction 60/1, which is obviously 60 seconds. So that needed to be split and converted to decimal then have &amp;quot;sec&amp;quot; appended. Simple enough with a couple of floats.&lt;/p&gt;
&lt;h4 id=&#34;aperature&#34;&gt;Aperature&lt;/h4&gt;
&lt;p&gt;Aperature is expressed as a ratio of the the focal length and width of the aperture, so f/8 or f/16. There is no actual value on a lens of f/8 or f/16, they are simply ratios of the relationship between the settings of where the lens has been set and the aperture. Once again, we take the value from the EXIF and convert it from fractional to decimal then append &amp;quot;f/&amp;quot; to the result so that it makes sense when shown in the CSV.&lt;/p&gt;
&lt;h4 id=&#34;go-exif-library&#34;&gt;Go-Exif Library&lt;/h4&gt;
&lt;p&gt;The core function of the Go-Exif library is to be presented with an image file, it then extracts all the EXIF data a JSON based struct. We then cycle the info brought back from the image file in the struct and pull the EXIF field we actually asked for, converting those mentioned where required for the CSV output. The real magic is that the Go-Exif library is able to extract the data into a really easy to use data format where the fields are just sets of tagged data.&lt;/p&gt;
&lt;h2 id=&#34;is-it-worth-the-effort&#34;&gt;Is it Worth The Effort?&lt;/h2&gt;
&lt;p&gt;All I can say is that when FotoVue books are put together gathering the EXIF data and extracting it can take one person around a week to get all the info if they spend every day copy and pasting the info from Lightroom into Excel! That&#39;s a week of click and image, copy 8-10 pieces of text per image from Lightroom into row in Excel, then repeat around 1,000 times!! No fecking way! I didn&#39;t spend 30 years of my life in IT for nothing!&lt;/p&gt;
&lt;p&gt;I use Lightroom along with Jeffrey Friedl&#39;s superb &amp;quot;Collection Publisher&amp;quot; plugin for Lightroom to extract and dump all the images in the correct folder structure on disk to match the collections from within Lightroom. Then I run my scanner over it and I can have a 1,000 JPG file&#39;s worth of data into a CSV in less than 2 mins! 2 mins versus 60 hours of manual copy&#39;n&#39;paste, f**k yeah it&#39;s worth it!&lt;/p&gt;
&lt;p&gt;If the EXIF data is wrong or not quite right, then I don&#39;t have to spend hours and hours fixing a spreadsheet, I simply fix the odd entries, re-dump the images I need and then re-run the util, all of which can be done in a few minutes. This means the data can be off to the book editor and layout artists same day, it&#39;s easier to fix if there&#39;s problems so the turnaround is infinitely faster and it means me, the editor and layout artist have much more time to do the creative stuff we enjoy. All thanks to Go and a will to automate.&lt;/p&gt;
&lt;p&gt;Links:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/SyxAxis/GOEXIFExtractor&#34;&gt;My GOExifExtractor on Github&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/dsoprea/go-exif&#34;&gt;DSOpera go-exif library&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://regex.info/blog/lightroom-goodies&#34;&gt;Jeffrey Friedl Lightroom Plugins&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
        
      </description>
    </item>
    
    <item>
      <title>Flashing Arduino Nano Bootloader from Arduino Uno</title>
      <link>https://SyxAxis.github.io/post/01_arduino_bootloader/</link>
      <pubDate>Sat, 02 Jan 2021 15:00:20 +0000</pubDate>
      
      <guid>https://SyxAxis.github.io/post/01_arduino_bootloader/</guid>
      <description>
        
          &lt;p&gt;&lt;strong&gt;Arduino Bootloader - How-To (Re)Install the Aruduino Nano Bootloader&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;How to flash the Aruduino Nano bootloader and what to do if it doesn&#39;t work.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;I recently obtained an Arduino Nano unit from my Dad ( he&#39;s 82 and loves playing with gadgets and electronics! ) and decided to have a play with it but I found it wouldn&#39;t take a sketch, it refused to accept the upload of sketch code. Turns out cheaper non-genunine Arduino boards are sometimes shipped without bootloaders. Sounds like a serious issue but not at all, the designers of the Arduino system thought about this.&lt;/p&gt;
&lt;h2 id=&#34;what-is-the-arduino-bootloader&#34;&gt;What is the Arduino bootloader?&lt;/h2&gt;
&lt;p&gt;The Arduino bootloader is a small piece of code, as the name suggests, that allows the compiled sketch code to be installed and started. It&#39;s 512 bytes in size and sits in an area of &amp;quot;memory&amp;quot; within the 328P microprocessor chip.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://SyxAxis.github.io/arduino/ATmega328P_MemoryMap.jpg&#34; alt=&#34;Memory Map of the ATMega328 Microprocessor&#34;&gt;&lt;/p&gt;
&lt;p&gt;Believe it or not, there&#39;s actually not a lot to an Arduino board and you can simply buy an ATmega328P microprocessor chip and flush a bootloader to it if you wish! The Arduino system is mainly about the supporting boards that hold the processor chips, the processor chips on the boards are, well, cheap as chips!&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A special piece of code that is executed at every reset of the microcontroller and that looks for a sketch to be uploaded from the serial/USB port using a specific protocol and speed. If no connection is detected, the execution is passed to the code of your sketch. This little (usually 512 bytes) piece of code is called the &amp;quot;Bootloader&amp;quot; and it is in an area of the memory of the microcontroller - at the end of the address space - that can&#39;t be reprogrammed as a regular sketch and had been designed for such purpose.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;use-an-arduino-uno-to-reprogram-an-arduino-nano&#34;&gt;Use an Arduino Uno to ReProgram An Arduino Nano&lt;/h2&gt;
&lt;p&gt;So you&#39;ll need the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Working Arduino Uno board&lt;/li&gt;
&lt;li&gt;Arduino Nano board&lt;/li&gt;
&lt;li&gt;Jumper wires with pins&lt;/li&gt;
&lt;li&gt;10uF Capacitor ( must be 10uF )&lt;/li&gt;
&lt;li&gt;Breadboard if you have one&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;First you need to do is to flash a specific sketch, supplied from within the standard Arduino IDE, to the Arduino Uno.&lt;/p&gt;
&lt;p&gt;Plugin the Arduino Uno and from the Examples menu locate the &amp;quot;ArduinoISP&amp;quot; sketch, upload it to the Arduino Uno.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://SyxAxis.github.io/arduino/LoadFlashSketch.jpg&#34; alt=&#34;ArdiunoISP Base Sketch for flashing another Arduino&#34;&gt;&lt;/p&gt;
&lt;p&gt;Disconnect the Uno from the USB and wire it up as shown below. Note the use of the capacitor slotted into the line to GND.&lt;/p&gt;
&lt;p&gt;Most boot flashing tutorials and diagrams will simply show the GND being wired up between the two board but note that if you attempt to flash the bootloader with just the lines you may find it will fail. The line is hot and when you go to flash the target board needs its reset line hit and dropped, if the line is simply hot the reset not happen and the reprogram will fail. The capacitor is put in line to drop the voltage and pull the line back up when the flash is started this triggers the Uno to Nano reset and the Nano will be open to accept the boot flash. It needs to be 10uF anthing bigger or smaller will take too long to pull the reset.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://SyxAxis.github.io/arduino/arduino_isp_wires.png&#34; alt=&#34;Wiring up the Uno and Nano for bootloader flash&#34;&gt;&lt;/p&gt;
&lt;p&gt;Once you have this wired up as shown the next step is to flip the Arduino IDE into a programmer using the Uno as the hardware programmer passing through to the Nano.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Plug the USB into the Arduino UNO board NOT the Nano, the Uno is a programmer and will instruct the Nano.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;You need the board set to the target, the Nano.&lt;/li&gt;
&lt;li&gt;You need the chip set to ATMega328P. ( pre 2018 this would be &amp;quot;old bootloader&amp;quot; )&lt;/li&gt;
&lt;li&gt;Port is set to the Uno&#39;s USB link.&lt;/li&gt;
&lt;li&gt;Select &amp;quot;Arduino as ISP&amp;quot; from the &lt;strong&gt;Programmer&lt;/strong&gt; options.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&#34;https://SyxAxis.github.io/arduino/burn_bootloader_ide_settings.jpg&#34; alt=&#34;Arduino IDE Bootloader Burn Settings&#34;&gt;&lt;/p&gt;
&lt;p&gt;Finally hit &lt;strong&gt;Burn Bootloader&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&#34;what-happens-if-it-doesnt-work&#34;&gt;What Happens if it Doesn&#39;t Work?&lt;/h2&gt;
&lt;p&gt;One issue I had with my Nano board was that it would not take the bootloader when I first tried and I kept getting failures. It took me 2 days to find the proble,.&lt;/p&gt;
&lt;p&gt;If you see this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;ln&#34;&gt;1&lt;/span&gt;avrdude: stk500_recv(): programmer is not responding
&lt;span class=&#34;ln&#34;&gt;2&lt;/span&gt;avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x03
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You may see this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;ln&#34;&gt;1&lt;/span&gt;avrdude: Yikes!  Invalid device signature.
&lt;span class=&#34;ln&#34;&gt;2&lt;/span&gt;         Double check connections and try again, or use -F to override
&lt;span class=&#34;ln&#34;&gt;3&lt;/span&gt;         this check.
&lt;span class=&#34;ln&#34;&gt;4&lt;/span&gt;
&lt;span class=&#34;ln&#34;&gt;5&lt;/span&gt;Error while burning bootloader.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I was also seeing random signatures from the Nano board!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;ln&#34;&gt;1&lt;/span&gt;Reading | ################################################## | 100% 0.05s
&lt;span class=&#34;ln&#34;&gt;2&lt;/span&gt;
&lt;span class=&#34;ln&#34;&gt;3&lt;/span&gt;     avrdude: Device signature = 0x000000
&lt;span class=&#34;ln&#34;&gt;4&lt;/span&gt;     avrdude: Yikes!  Invalid device signature.
&lt;span class=&#34;ln&#34;&gt;5&lt;/span&gt;     Double check connections and try again, or use -F to override
&lt;span class=&#34;ln&#34;&gt;6&lt;/span&gt;     this check.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;All these errors mean one thing, you have bad wiring! The lines between the boards must be good and you will need to ensure the cap in the GND line is good.&lt;/p&gt;
&lt;p&gt;It turned out in my case that the VCC pin on my Nano board had a bad solder joint and it was joined to the pin next door to it. This meant the second it was flashed the VCC bled over and reset the board and kept producing random signatures. 5 secs with the soldering iron to clean up the bad solder joint and the flash worked perfect.&lt;/p&gt;
&lt;h2 id=&#34;moral-of-the-story&#34;&gt;Moral of the Story&lt;/h2&gt;
&lt;p&gt;Genuine Arduino boards will have a higher quality check from the factory but clones may not be subject to quite such high standards. You can get 5 Nano boards for £10 from Amazon, well worth buying the clone boards as they&#39;re far cheaper than the genuine boards, but just be sure that your ready to check them over and you&#39;re ready to dig deeper into the Arduino guts when things don&#39;t work out of the box.&lt;/p&gt;
        
      </description>
    </item>
    
  </channel>
</rss>
