tag:blogger.com,1999:blog-20276999932354111722024-02-23T07:43:26.915+00:00Graham White: My NotesGraham Whitehttp://www.blogger.com/profile/03878311939940449093noreply@blogger.comBlogger113125tag:blogger.com,1999:blog-2027699993235411172.post-9192164506435684472023-12-20T20:30:00.001+00:002023-12-20T20:30:00.151+00:00Scouting<p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzEErhdlaAPSf8SD24J24364mYFoKYEtjqbHfy86or2pYYaHDJWpWqpjgqywhnBFme-WDgJzmCilG3XmUmulcdQ9Me0BUj_DBS21ULH7PCs-0la1fCA5a9onsU3qKbqgeGey1eHOMI0rwZPbWZXHnNuKzZSKsJGB2y9naFopv1vMtZNQkGoVVmiM5Doas/s750/Graham_Merlin_White.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img alt="Graham in Scout Uniform" border="0" data-original-height="750" data-original-width="750" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzEErhdlaAPSf8SD24J24364mYFoKYEtjqbHfy86or2pYYaHDJWpWqpjgqywhnBFme-WDgJzmCilG3XmUmulcdQ9Me0BUj_DBS21ULH7PCs-0la1fCA5a9onsU3qKbqgeGey1eHOMI0rwZPbWZXHnNuKzZSKsJGB2y9naFopv1vMtZNQkGoVVmiM5Doas/w320-h320/Graham_Merlin_White.jpg" title="Graham in Scout Uniform" width="320" /></a>A few years back, I decided it would be a good idea to register my little lad on the waiting list for <a href="https://www.scouts.org.uk/beavers/">Beaver Scouts</a> and didn't realise at that point in time quite what a journey would be unfolding in front of us.</p><p>Needless to say, I ended up volunteering. I started on a fairly typical journey by offering to help out occasionally and getting DBS cleared. I found I was attending pretty much every week so from there it was a relatively small step to go into uniform and make my role official. Four years since I started helping out, I'm an "Assistant Beaver Section Leader" known to the children as "Merlin".<br /></p><p>While on the topic of scout names, everyone in my section adopts the name of a creature found in British wildlife. It's customary for the children to use an adult's scouting name when referring to us. In fact, they have no idea what our real names are. I'm not sure why, that's just the way things have evolved. I wanted to use the name "Goshawk" but at the time our section already had someone named "Hawk" which seemed a bit too similar so I considered other small birds of prey such as "Sparrowhawk" (still too similar), "Hobby" (didn't seem right) and eventually settled on "Merlin". Now everyone seems to think I'm a wizard and I have to explain the name all the time. Stupid choice!<br /></p><p>Scouting is a great organisation and charity, run at the top level by paid professionals but the majority of the things that happen are as a result of volunteers, such as myself! The volunteers often go to a lot of lengths, putting in hours of preparation and hard work to make sure all the kids in their section have fun, experience things they wouldn't otherwise do but remain safe. Hence, I thought I would recount some of the stuff I've been doing since signing up. Most of this is a total surprise to me as I was never involved in Scouting as a kid so I'm learning and going through the whole thing at the same time as my son.<br /></p><p><b>Safety, DBS and Training</b></p><p>Our primary goal for each meeting and overall plan each term is to have fun while remaining safe. The safety aspect isn't too onerous, mainly consisting of an initial DBS check that is trivial enough and then risk assessing activities that basically involves common sense to think things through in advance. There is a reasonable amount of red tape involved in all this that the parents never really see. There's also training to be done. To be in uniform, one must have a first aid qualification and undertake a bunch of formal training modules, providing evidence to an assessor that you've qualified to pass each module. This must all be done within 3 years. Once complete, you're awarded your <a href="https://www.scouts.org.uk/volunteers/learning-development-and-awards/awards-and-recognition/wood-badge/">wood beads</a> - I'm currently most of the way there and have 1 year left to complete the remaining few modules.</p><p><b>Activities</b></p><p>Having never been involved in Scouts previously, pretty much everything that goes on comes as something new (if not a surprise) to me. Camp fire, songs, cooking, crafting, knot tying and a raft of other outdoor and adventurous activities are all very cool things to get involved with and organise.<br /></p><p><b>Visits and Visitors<br /></b></p><p>I've not been scouting for particularly long, especially when compared to some of our volunteers that have been in the organisation 30+ years. However, I've already racked up quite a few different venues and experiences:</p><ul style="text-align: left;"><li>Our Scout Hut (obviously), we call it "The Den"</li><li>Other Scout Huts</li><ul><li>8th Alton</li><li>Bentley</li><li>Four Marks</li></ul><li>RAF Odiham</li><li>Boots Opticians</li><li>Local Library</li><li>Marks and Spencer</li><li>War Memorial</li><li>Chawton House</li><li>Uppark House (national trust)<br /></li><li>Scout Camp sites <br /></li><ul><li>Garners Field</li><li>Lyons Copse </li><li>Bentley Cops </li></ul><li>Various locations for walks and hikes e.g. Butser Hill</li><li>Local Care Homes</li><li>Our Visitors are varied, e.g.</li><ul><li>Disabled people/groups</li><li>Dance and music groups</li><li>People with specialist skills/knowledge<br /></li></ul></ul>Graham Whitehttp://www.blogger.com/profile/03878311939940449093noreply@blogger.com0tag:blogger.com,1999:blog-2027699993235411172.post-1629799310485760072022-02-22T18:46:00.002+00:002022-02-22T18:46:25.561+00:00New Thinkpad P15<div><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEiepszV1BrmI6ti0XHIAL192n4eOO1oopJNIZyqAvCGMy9h2vTFWL_LVpGebY7fvUIbDwP2KQc47ZIrmmtAhaRsgr3c5dpd5KaNc8QbJlxgmPx8X10g_oIs7XIcSHbWbtr4rxbsjfyjcLwaNURYZNRKbe5ajlPJO8EI1Xp0oF79So5oghXwnvqtnhNq=s725" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="515" data-original-width="725" height="227" src="https://blogger.googleusercontent.com/img/a/AVvXsEiepszV1BrmI6ti0XHIAL192n4eOO1oopJNIZyqAvCGMy9h2vTFWL_LVpGebY7fvUIbDwP2KQc47ZIrmmtAhaRsgr3c5dpd5KaNc8QbJlxgmPx8X10g_oIs7XIcSHbWbtr4rxbsjfyjcLwaNURYZNRKbe5ajlPJO8EI1Xp0oF79So5oghXwnvqtnhNq=s320" width="320" /></a></div><br />This post continues a long running tradition and series of posts when I'm issued a new laptop at work. I generally get quite a powerful and interesting machine as I'm a member of the IBM Hursley development laboratory and thus am issued a fairly beefy specification for a majority of desktop use rather than being a more mobile laptop. I'm issued a new machine approximately every four years so my previous posts are about my:<p></p><ul style="text-align: left;"><li><a href="http://gibbalog.blogspot.com/search/label/thinkpad">Thinkpad P50</a> (April 2017) <br /></li><li><a href="http://gibbalog.blogspot.com/2013/03/new-thinkpad-w530.html">Thinkpad W530</a> (March 2013)</li><li><a href="http://gibbalog.blogspot.com/2008/06/new-thinkpad-t61p.html">Thinkpad T61p</a> (June 2008)</li></ul></div><p>It's interesting to see how the specification of machine has changed over time. With the slowing (or disappearance) of Moore's Law, the speed advantage of more recent machines has come from other innovations (such as an SSD and an increased number of cores) rather than raw clock speed. The highlight specifications for the P15 Gen 1 I have are...</p><ul style="text-align: left;"><li>Intel(R) Core(TM) i7-10750H CPU @ 2.60GHz (5199.98 bogomips in Linux)</li><li>32GB DDR4 2933MHz</li><li>Toshiba 512GB SSD XG6 M.2 2280</li><li><span dir="ltr" role="presentation" style="font-family: sans-serif; font-size: 15px; left: 264.083px; top: 518.233px; transform: scaleX(1.04358);">15.6" </span>3840 x 2160 <span dir="ltr" role="presentation" style="font-family: sans-serif; font-size: 15px; left: 264.083px; top: 518.233px; transform: scaleX(1.04358);">IPS (non touch)</span></li><li><span dir="ltr" role="presentation" style="font-family: sans-serif; font-size: 15px; left: 28.35px; top: 1053.15px; transform: scaleX(1.00109);">Integrated Li-Po 94Wh battery</span></li><li><span dir="ltr" role="presentation" style="font-family: sans-serif; font-size: 15px; left: 264.083px; top: 518.233px; transform: scaleX(1.04358);">Wi-Fi 6</span></li><li><span dir="ltr" role="presentation" style="font-family: sans-serif; font-size: 15px; left: 264.083px; top: 518.233px; transform: scaleX(1.04358);">NVidia Quadro T1000M 4GB</span></li><li><span dir="ltr" role="presentation" style="font-family: sans-serif; font-size: 15px; left: 264.083px; top: 518.233px; transform: scaleX(1.04358);">Front Facing Web Cam, HDMI Out, Headphone, 2x USB3.2, 2</span><span dir="ltr" role="presentation" style="font-family: sans-serif; font-size: 15px; left: 527.1px; top: 757.483px; transform: scaleX(0.997831);">x USB-C3.2 Gen 2</span><span dir="ltr" role="presentation" style="font-family: sans-serif; font-size: 15px; left: 264.083px; top: 518.233px; transform: scaleX(1.04358);"></span>, GBit Ethernet, Fingerprint Reader, <span dir="ltr" role="presentation" style="font-family: sans-serif; font-size: 15px; left: 113.167px; top: 669.733px; transform: scaleX(0.995739);">SD card reader</span></li></ul><p><span dir="ltr" role="presentation" style="font-family: sans-serif; font-size: 15px; left: 113.167px; top: 669.733px; transform: scaleX(0.995739);">There we have it, the top level specs aren't all that different to the 4 year old P50 machine I had previously. In fact the CPU speeds have dropped slightly although the P15 does have 12 cores to the P50's 8. RAM and GPU memory have both stayed the same and I still have a 512GB SSD. Interestingly, the battery is now integrated which has moved away from the long standing removable battery on these top line Thinkpad machines. There's a huge increase in the screen resolution and I dare say the screen would also have been improved in areas such as peak brightness (600 nits for the P15) and support for Dolby Vision HDR (there's also support for Dolby Atmos sound which will be a bit lost on me for a business machine). While sounding good, if you put a 4k resolution onto a 15" laptop screen you pretty much need a magnifying glass to see anything so it's more or less useless unless you're consuming 4k video content. No wonder then that the Gnome desktop defaulted to running in 4k mode but at 200% scale (which I think takes it back down to HD size unless I'm mistaken).<br /></span></p><p><span dir="ltr" role="presentation" style="font-family: sans-serif; font-size: 15px; left: 113.167px; top: 669.733px; transform: scaleX(0.995739);">The day-to-day running of the new machine has been pretty good. Not noticeably different to that of the old machine. This goes to show the lack of improvement in specifications of these new machines in general. It's something I've noticed with my ageing home machine as well (which is nearly 10 years old) where the processor benchmarks are very similar to today's processors on a core-for-core comparison</span><span dir="ltr" role="presentation" style="font-family: sans-serif; font-size: 15px; left: 113.167px; top: 669.733px; transform: scaleX(0.995739);"></span> and I still have things like a decent PCI 3 bus. It's always nice to have a bit of a refresh though and the thing I'm liking most about the new machine is the addition of the built-in fingerprint reader. This particular piece of hardware is now fully supported on Linux and very easy to configure using the Gnome settings tool. It makes logging in with a massive password much less painful. I hope more apps (such as 1password) will eventually find ways of integrating biometric security on Linux as well. It's worth noting that this functionality hasn't come at all by accident and has been a lot of hard work and a long road between both Red Hat and Lenovo to ensure that all new Lenovo laptop machines are <a href="https://news.lenovo.com/pressroom/press-releases/lenovo-brings-linux-certification-to-thinkpad-and-thinkstation-workstation-portfolio-easing-deployment-for-developers-data-scientists/">fully certified</a> to have a hardware configuration that contains drivers and firmware compatible with Linux.</p><p>There are, of course, teething troubles with the new machine. These are mostly related to graphical issues and NVidia. More recently, I'd taken for granted my old machine just working in these respects. My old machine had similar teething issues when it was new of course and these were gradually ironed out with driver updates as time progressed. So right now it's weird to be back in the dark days of having to use the NVidia settings panel to configure the screen resolutions I want as for some reason the binary driver is only showing up the full 4k resolution to xrandr under Linux (yes I'm still using Xorg, not Wayland, yet). It's also a bit fragile in terms of going into sleep mode and resuming from sleep, it all works but there can be graphical glitches (sometimes and sometimes not) which I may need to restart the gnome shell to cure (Alt+F2 then type r and hit Enter). While this is frustrating for now, I'm fully expecting driver updates to catch up and this machine will gradually settle down into the same level of graphical performance I was used to on my old machine i.e. no problems at all and no need to open up NVidia settings. Perhaps the thing that surprises me most about all this though is the very fact that all of this has regressed. I'm no expert in the graphical stack on Linux but it's rather unfortunate that I seem to experience the same pains and teething problems upon the issue of every new laptop. It'll all get there. One day!<br /></p>Graham Whitehttp://www.blogger.com/profile/03878311939940449093noreply@blogger.com0tag:blogger.com,1999:blog-2027699993235411172.post-56290921378384976582021-12-28T21:40:00.001+00:002021-12-28T21:40:50.335+00:00Solving a Rubik's Cube<div><p></p><p></p><p>We bought a Rubik's Cube while away on our summer holiday this year and spent some time playing around with it and then learning to solve it. We've returned to it over the Christmas break. The solve we're learning is based on a very detailed video (below) from Wired Magazine. I'm at the stage where I can remember most of the solve shown in the video but haven't memorised the final few steps involving the algorithms to position the final corner pieces in the top layer.</p><p><br /></p><div class="separator" style="clear: both; text-align: center;"><iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/R-R0KrXvWbc" title="YouTube video player" width="560"></iframe></div><p></p><p><br />
</p><p>Since the video is so long and detailed, when you're at the stage of being able to remember most of the solve, you just need a quick memory jogger rather than wading through the video (even though it has some nice chapter markings). Hence, this post is my quick reference guide for the future. I'll walk through the whole solve very briefly (use the video for the detail)...<br />
</p><p></p><h4 class="western" style="text-align: left;">Introduction</h4>
<p>Learn the <a href="https://www.youtube.com/watch?v=R-R0KrXvWbc&t=441s">right trigger</a> and <a href="https://www.youtube.com/watch?v=R-R0KrXvWbc&t=460s">left trigger</a> moves (involves holding the cube
correctly)</p>
<p>Learn <a href="https://www.youtube.com/watch?v=R-R0KrXvWbc&t=909s">cube notation</a> (rotate the appropriate face clockwise from
the point of view of you looking straight onto that face)</p>
<ul><li><p>F = Front Face</p>
</li><li><p>B = Back</p>
</li><li><p>L = Left</p>
</li><li><p>R = Right Face</p>
</li><li><p>D = Downward Face</p>
</li><li><p>U = Upward Face</p>
</li><li><p>‘ = Spin anti clockwise e.g. F’ = Front Face anti
clockwise</p>
</li><li><p>2 Spin twice e.g. F2 = Front Face rotates by 180 degrees
(spun twice)</p>
</li></ul>
<h4 class="western" style="text-align: left;"> </h4><h4 class="western" style="text-align: left;">Solve the bottom layer</h4><a href="https://www.youtube.com/watch?v=R-R0KrXvWbc&t=491s">Video Link</a> <br /><ol style="text-align: left;"><li>Make the daisy</li><ol style="text-align: left;"><li>Position white edge pieces around the yellow centre</li></ol><li>Make a white cross on the bottom face</li><ol><li>Line up white edge stickers on the top face with their middle colour on the side face, rotate the twice to move the white sticker from the top face to the bottom face</li><li>The white face should remain pointing down for the rest of
the solve</li></ol><li>Position the bottom row corners</li><ol><li>Search for corner pieces in the top layer that have a white
piece</li><ol><li>If found, match the non-white colour of the corner piece in
the top layer (ignore the top face) with the coloured center.</li><li>With the non-white coloured center facing you observe
whether the white sticker is on the left or right side of the
cube. If left, perform the left trigger; if right, perform the
right trigger.</li></ol><li>If there are no white pieces in the top layer but you have one in the bottom layer. Determine if the white piece in the bottom layer is on the left or right and with the white piece facing you, perform the left or right trigger (depending on whether the white piece is on the left or right side of the cube). The white piece will now be on the top of the cube. <br /></li><li>If there are no white pieces in the top layer but you have
one on the top face. Rotate the top face such that the white
sticker is not opposite a white sticker on the bottom face i.e. the
white sticker on the top face should be opposite a coloured sticker
on the bottom face. Then reposition the sticker so it’s in the
top layer.</li><ol><li>Perform the left or right trigger twice in succession if
depending on whether the white sticker on the top face is on the
left or right side of the cube. Now refer to 3.1 to place the corner correctly onto the bottom face.</li></ol></ol></ol><h4 style="text-align: left;"> </h4><h4 style="text-align: left;">Solve the middle layer</h4><div style="text-align: left;"><a href="https://www.youtube.com/watch?v=R-R0KrXvWbc&t=742s">Video Link</a> </div><ol style="text-align: left;"><li>Search the top layer for edge pieces that do not have any yellow stickers (either on the edge face or the top face). Then once found move that piece to the second layer.<br /></li><ol><li>Rotate the top layer such that the sticker on the edge face is colour matched with its centre sticker.</li><li>Examine the colour of the sticker on the top face of the edge piece you're moving, it should match the left or right centre stickers.</li><ol><li>If it matches the left then rotate the top face anti clockwise by 90 degrees (a U' in notation form) then perform a left trigger</li><li>If it matches the right then rotate the top face clockwise by 90 degrees (a U in notation form) then perform a right trigger</li></ol><li>You've now displaced one of the white stickers. It will be in the top row so simply place it back to the bottom face using the same method as when solving the bottom layer.</li></ol><li>Repeat the above until there are no more non-yellow stickers on the top face.</li><li>You may occasionally find a situation where there are no edge pieces in the top layer without yellow stickers but the second layer is not complete. If this happens:</li><ol><li>Examine the middle layer for the piece that is not right. With that piece facing you, examine if it's on the left or right of the cube. Perform either the left or right trigger according to which side its on.</li><li>Fix the displaced white piece.</li><li>There will now be an edge piece in the top layer that doesn't have a yellow sticker so continue solving as per the first step of the middle layer.</li></ol></ol></div><div style="text-align: left;"> </div><div style="text-align: left;"><h4 style="text-align: left;">Create a Yellow Cross (top face)</h4><div style="text-align: left;"><a href="https://youtu.be/R-R0KrXvWbc?t=987">Video Link</a></div><p style="text-align: left;"><i>Required Algorithm:</i> <span style="font-family: courier;">F U R U' R' F'</span></p><ol style="text-align: left;"><li>Repeat these steps depending on the number of yellow edge pieces (on the top face): <br /></li><ol><li>If there are no yellow edge pieces (on the top face), perform the algorithm.</li><li>If there are two yellow edge pieces in a line, orient the line so it faces up/down, perform the algorithm.</li><li>If there are two yellow edge pieces next to each other, place them in the 12 and 9 position on the top face, perform the algorithm.</li></ol></ol><b> </b></div><div style="text-align: left;"><h4 style="text-align: left;"><b>Solve the Yellow Face</b> </h4></div><div style="text-align: left;"><a href="https://youtu.be/R-R0KrXvWbc?t=1056">Video Link</a> </div><div style="text-align: left;"><br /></div><div style="text-align: left;"><i>Required Algorithm: </i><span style="font-family: courier;">R U R' U R U2 R'</span><br /></div><div style="text-align: left;"><ol style="text-align: left;"><li>Look at the top (yellow) face and repeat these steps depending on the number of yellow corner pieces (on the top face): </li><ol><li>If there are zero or two yellow corner stickers, rotate the top face until there is a yellow sticker in the top right position of the left face, perform the algorithm.</li><li>If there is one yellow corner sticker, rotate the top face until the corner sticker is in the bottom right position, perform the algorithm.</li></ol></ol> </div><div style="text-align: left;"><h4 style="text-align: left;"><b>Position the Top Layer Corners</b> </h4></div><div style="text-align: left;"><a href="https://www.youtube.com/watch?v=R-R0KrXvWbc&t=1151s">Video Link</a></div><div style="text-align: left;"> </div><div style="text-align: left;"><i>Required Algorithm:</i> <span style="font-family: courier;">L' U R U' L U R' R U R' U R U2 R' </span><br /></div><div style="text-align: left;"><br /></div><div style="text-align: left;"><ol style="text-align: left;"><li>Look at the top corner pieces of the top layer, repeat these steps:</li><ol><li>If there are no matching corner pieces, perform the algorithm.</li><li>If one of the faces has matching corner pieces, place that face in the left hand so it's pointing left, perform the algorithm.</li></ol><li>When all of the corner pieces match, rotate the upper face so the corner pieces on each face match up with their centre colour.</li></ol></div><div style="text-align: left;"><br /></div><div style="text-align: left;"><h4 style="text-align: left;"><b>Position the Top Layer Edges </b></h4></div><div style="text-align: left;"><a href="https://youtu.be/R-R0KrXvWbc?t=1308">Video Link</a></div><div style="text-align: left;"><br /></div><div style="text-align: left;">Required Algorithm (Clockwise) i: <span style="font-family: courier;">F2 U R' L F2 L' R U F2</span><br /></div><div style="text-align: left;"> </div><div style="text-align: left;">Required Algorithm (Anticlockwise) ii: <span style="font-family: courier;">F2 U' R' L F2 L' R U' F2</span><br /></div><div style="text-align: left;"><br /></div><div style="text-align: left;"><ol style="text-align: left;"><li>If one of the sides is solved, face it away from you then look at the edge pieces on the remaining unsolved 3 sides</li><ol><li>Swap the edges clockwise, perform algorithm i</li><li>Swap the edges anticlockwise, perform algorithm ii</li></ol><li>If none of the sides are solved, perform algorithm ii, reposition the cube to face the solved face away from you and then perform algorithm ii again.<br /></li></ol></div><div>
<p><style type="text/css">h1 { margin-bottom: 0.21cm; background: transparent; page-break-after: avoid }h1.western { font-family: "Liberation Sans", sans-serif; font-size: 18pt; font-weight: bold }h1.cjk { font-family: "Source Han Sans CN"; font-size: 18pt; font-weight: bold }h1.ctl { font-family: "Mangal"; font-size: 18pt; font-weight: bold }p { margin-bottom: 0.25cm; line-height: 115%; background: transparent }</style></p></div>Graham Whitehttp://www.blogger.com/profile/03878311939940449093noreply@blogger.com0tag:blogger.com,1999:blog-2027699993235411172.post-83226306022935228832021-11-23T18:21:00.000+00:002021-11-23T18:21:15.752+00:00IoT Christmas Tree Tech<p>In <a href="https://gibbalog.blogspot.com/2021/11/iot-christmas-trees.html">my previous post</a> where I was showing off my IoT Christmas Trees, I described the project and what the trees are intended to do. This post features the inside track information about how I put the project together. So the first post is supposed to be non-technical if you will and this post details the info more of interest to those interested in the technical make-up of the project. Since this is effectively a recipe for how to create one of my IoT Christmas Trees, we'll start with the list of things needed.</p><h3 style="text-align: left;">Ingredients <br /></h3><h4 style="text-align: left;">For the Tree</h4><div style="text-align: left;">Bits you need to make one tree:<br /></div><ul style="text-align: left;"><li>Wood</li><li>Paint<br /></li><li>Arduino ESP32</li><li>Micro USB Cable</li><li>Veroboard</li><li>LED String</li><li>Buttons<br /></li></ul><h4 style="text-align: left;">Server and Connection Requirements</h4><div style="text-align: left;">These are Internet connected of course so needed here are:</div><div style="text-align: left;"><ul style="text-align: left;"><li>An MQTT Broker<br /></li><li>An HTTP Server</li><li>WiFi with Internet Connection</li><li>Another WiFi capable device<br /></li></ul></div><h4 style="text-align: left;">Other Useful Bits</h4><div style="text-align: left;">Probably staple provisions of any maker's tool box:<br /></div><ul style="text-align: left;"><li>Glue Gun</li><li>Soldering Iron and Solder</li><li>Heat Shrink Tubing</li><li>Wire (22AWG Solid Core)</li></ul><p> </p><h3 style="text-align: left;">Putting it all together <br /></h3><p> </p><h3 style="text-align: left;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKUVlkbAjz1j19NDsxELtSAYnpv-cKodqePl8_GHiyEOTJQM-RCYgdohbXBS3hN9h0f5Axh4oWtUSV7fIDsR6p80AiCMFRfUncR0QHNbstFAz9Laefpq0n8A5GLb8IQulQ0yN-kA4J_Kc/s1635/PXL_20211104_203315934.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="919" data-original-width="1635" height="360" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKUVlkbAjz1j19NDsxELtSAYnpv-cKodqePl8_GHiyEOTJQM-RCYgdohbXBS3hN9h0f5Axh4oWtUSV7fIDsR6p80AiCMFRfUncR0QHNbstFAz9Laefpq0n8A5GLb8IQulQ0yN-kA4J_Kc/w640-h360/PXL_20211104_203315934.jpg" width="640" /></a></div><br /></h3><h4 style="text-align: left;">The wooden bits <br /></h4><div><p>You need enough wood in whatever design you prefer. I made a point of making each of my trees in a different style. It caused more work that way of course but there's something nice about each tree being unique. My designs are all between about 25cm and 40cm tall without much thought put into why. However, this sort of size seems to work well with the light string I chose. Given the light string is 5 metres long and I used half a string for each tree I needed to hang 2.5m of string around each tree (containing 25 lights per tree). Therefore, you need to size the wooden structure appropriately for the length of string or number of lights you intend to hang. </p><h4 style="text-align: left;">Painting <br /></h4><p>I decided to use spray paint to try and achieve a really smooth and high quality finish. I selected <a href="https://www.montana-cans.com">Montana</a> paints as they provided all the types of paint I wanted to use (<a href="https://www.montana-cans.com/en/spray-cans/montana-tech-sprays/primer-400ml/montana-primer-400ml-aluminium">primer</a>, <a href="https://www.montana-cans.com/en/spray-cans/montana-effect-sprays/metallic-400ml/montana-metallic-400ml">metallic top coat</a>, <a href="https://www.montana-cans.com/en/spray-cans/montana-effect-sprays/glitter-400ml/montana-glitter-400ml ">glitter</a> and <a href="https://www.montana-cans.com/en/spray-cans/montana-tech-sprays/varnish-400ml/montana-varnish-400ml">varnish</a>). I went with 4 of their colours, Aztec Gold, Avocado Green, Titanium, Red; and glitter effects in Silver and Dusty Gold. Everything came from <a href="https://www.graff-city.com">Graff City</a>.</p><p>A couple of coats of primer were needed followed by a couple of coats of metallic. The glitter paint goes on as a varnish layer with particles of coloured glitter in it and they recommend a top coat of varnish is used to seal the glitter coat and prevent and loose glitter falling off. The result is a really nice layered effect where the fairly reflective metallic coating is set off against a subtle glitter effect and everything is finished off with the sheen of varnish.<br /></p><h4 style="text-align: left;">Electronics</h4><p>The main driver of the project, electronically, is an ESP32 board. The <a href="https://uk.banggood.com/Geekcreit-ESP32-WiFi+bluetooth-Development-Board-Ultra-Low-Power-Consumption-Dual-Cores-Pins-Unsoldered-p-1214159.html">board I chose</a> is a knock off of the <a href="https://www.wemos.cc/en/latest/d32/d32.html">Lolin D32</a> simply because it has everything I needed (including having the pins not soldered) and much cheaper than locally available boards in the UK. While the board was cheaper, I did discover some of the drawbacks in as much as it doesn't have built-in pull up resistors on its GPIO pins and as such I had a lot more soldering to do to work in a 10kΩ resistor into a little <a href="https://www.amazon.co.uk/gp/product/B07ZG3V1FB">veroboard</a> circuit to wire in the <a href="https://www.amazon.co.uk/gp/product/B0811QKG1R">buttons I chose</a>.<br /></p><p>The <a href="https://shop.pimoroni.com/products/rgb-led-wire">string of LED lights</a> looks very cool with some quite presentable wiring between the lights when compared to an LED strip. They're completely WS2812/NeoPixel compatible so they're easy to programme and there's some <a href="https://github.com/adafruit/Adafruit_NeoPixel">nifty</a> <a href="https://github.com/kitesurfer1404/WS2812FX">libraries</a> out there already available. They are, however, fairly hellish to solder since the wires are coated with some very thin plastic insulation which is either difficult to remove or otherwise burn through with your solder.</p><p>Finally, the whole thing is powered via Micro USB so I ordered a pile 3m long USB-A to Micro-USB cables so the trees can be sited a reasonable distance from a power socket and I didn't have to worry about batteries or charging although battery powering these units would definitely be possible.<br /></p><h4 style="text-align: left;">Firmware</h4><p>The firmware is a fairly standard <a href="https://github.com/esp8266/Arduino">Arduino implementation</a> for the main loop and using <a href="https://github.com/tzapu/WiFiManager">WifiManager</a> to configure the ESP32 WiFi to connect to an SSID. It wont come as any surprise to find the messaging component I'm using is based on MQTT and so I'm using Nick's <a href="https://github.com/knolleary/pubsubclient">pubsubclient library</a> on the client side.<br /></p><p>One of the more interesting things I've done with the firmware is to attempt to make it as remotely configurable as possible without the need to rely on over-the-air updates for the firmware. To this end, I'm using the <a href="https://github.com/benhoyt/inih">inih library</a> and the firmware downloads its configuration as an ini formatted file from a remote location that allows me to configure as much as possible, currently: mqtt hostname:port, username, password, SSL settings, publish and subscribe topics, device name; and then configurations for the lights for things like which colours to cycle around, how long the "Merry Christmas" setting is maintained before reverting to the previous setting. The ini file format also allows an easy "global" configuration to apply across each tree while also allowing a per-tree customisation. Should the WiFi connection not be available or the configuration file not be available then the tree reverts to a sensible set of defaults.</p><p>Once running, WiFi connected, MQTT connected and the configuration has been downloaded and applied there's some basic login there to cycle between the different light configurations when the left button on the tree is pressed. This is all done locally on each tree. The right button, when pressed, sends a (configurable) message to the other trees that tells them what to do. So it would be possible for each tree to have its own specific "Merry Christmas" pattern so you could, for example, work out who had sent you the message by the pattern/colour of the light flashes on the receiving tree.</p><p>I have also built in a simple command protocol to further take advantage of the MQTT connectivity. This allows me to send a "ping" to each tree to see which are currently alive, connected and working properly. The second command I have is a "reload" command that will cause the tree to download and re-apply the configuration from its remote location, noting of course that the configuration could have changed and so I can cause a tree to remotely update its configuration. Finally, there is a "reconnect" command that will cause the tree to disconnect and connect to its configured MQTT broker. This is useful in the rare circumstance where the IP address of the broker may have changed in which case I can update the configuration, have the tree read a new configuration, then have the tree disconnect from the current broker and connect to a new broker.<br /></p><p></p><h4 style="text-align: left;">MQTT Broker</h4><p>The MQTT broker is provided courtesy of my still relatively new <a href="http://gibbalog.blogspot.com/2021/09/yet-another-new-home-server.html">Pi4 home server</a> and the rather excellent <a href="https://mosquitto.org/">Mosquitto</a> MQTT broker. Since I'm running this all myself and not using a cloud based MQTT service I've screwed it all down as far as I can from a security perspective but there's nothing like running your own services to make you feel vulnerable!<br /></p></div>Graham Whitehttp://www.blogger.com/profile/03878311939940449093noreply@blogger.com0tag:blogger.com,1999:blog-2027699993235411172.post-77128983473082898952021-11-23T18:20:00.000+00:002021-11-23T18:20:31.753+00:00IoT Christmas Trees<p></p><p>My latest maker project has been running for a good chunk of the year and has been a really cool thing to do to keep me occupied during lockdown since I'm not really one to binge watch box sets. I've been making Internet connected Christmas trees as gifts for close family. They're designed to be ambient ornamental decorative pieces with a funky twist of interactivity. The video I produced probably explains them best...<br /></p><p style="text-align: center;"><iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="405" src="https://www.youtube.com/embed/9px5uKRvKhA" title="YouTube video player" width="720"></iframe></p><p><br /></p><p></p><p>As you can see from the video, each tree is deliberately different. I thought it would be more interesting to have a completely different wooden design for each. My dad did the woodwork which saved me quite a lot of time and allowed me to concentrate on writing the software and doing the electronics not to mention building and painting each tree. There's a good few hours work in each of these things.<br /></p><p>Operation of the trees is pretty simple with the most complicated bit, like with most of these things, being the initial set up to get them onto your WiFi network. For that, and to explain the basics of how they work along with a bit of troubleshooting information, I wrote a little user manual to go with them. After all, it will be our closest family members that receive one of these and so I can always help out remotely (and potentially fix any issues that arise). The left button on each tree cycles round a set of pre-defined colour schemes. However, these can be changed on a per tree basis should someone want a different colour or configuration. Similarly, the trees can be operated remotely but I've yet to write a decent interface to do so. The right button on each tree is where the fun is, causing all the other trees to change light pattern for some period of time. Again, this is all configurable per tree but by default they all cause the same green and red frenzied light pattern which should be very noticeable in the corner of your room should it occur.<br /></p><p></p><p></p><p>Finally, big thanks to <a href="https://jsutton.co.uk/iotree/">James Sutton</a> and his original <a href="https://jsutton.co.uk/iotree/">iotree project</a> was in no small amount an inspiration for my work here. Although, the implementations are different both physically and in software there's still a huge amount of overlap. James was also responsible for running an IoT hackathon at work (we're colleagues) introducing a lot of the technology I would need in order to perform this build. Thanks again, James!</p><p>I've also written more details on the <a href="https://gibbalog.blogspot.com/2021/11/iot-christmas-tree-tech.html">technical implementation</a>. But, I'll sign this post off with a closer look at each tree in pictures...</p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhvNEZ0V0Z_5pfTIgTKgt-ihAv51jK9FNKJwBoAHjz-2bIW7ecMxZ5d_CdcNNF3lACkuMl4YWgR8cj_146zmr0FBcRki8B10jFCTgupRgvvjXXIfH5B7DtSfgy3J3xzH08WTMlcL8P_uQ0/s2046/PXL_20211104_130859684-COLLAGE.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="2046" data-original-width="2046" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhvNEZ0V0Z_5pfTIgTKgt-ihAv51jK9FNKJwBoAHjz-2bIW7ecMxZ5d_CdcNNF3lACkuMl4YWgR8cj_146zmr0FBcRki8B10jFCTgupRgvvjXXIfH5B7DtSfgy3J3xzH08WTMlcL8P_uQ0/w640-h640/PXL_20211104_130859684-COLLAGE.jpg" width="640" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwSiBqsKstcZMWOERxYET4RY29HQZoz_kANBl9DPTc3GM1-rc4i0UA93GmbjSD3Uzoug1aWgAPeRFw3kKB3M2D2au6CKmngpQ6_UulcXQLXXOjgWWs38sd5BtmqQ0klzkN6VMK_IJ1A5A/s2046/PXL_20211104_130939787-COLLAGE.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="2046" data-original-width="2046" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwSiBqsKstcZMWOERxYET4RY29HQZoz_kANBl9DPTc3GM1-rc4i0UA93GmbjSD3Uzoug1aWgAPeRFw3kKB3M2D2au6CKmngpQ6_UulcXQLXXOjgWWs38sd5BtmqQ0klzkN6VMK_IJ1A5A/w640-h640/PXL_20211104_130939787-COLLAGE.jpg" width="640" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-8fLR_PkohXbO1JSbWGQ9dk6VOBSFZmmp9wMxCTjD99BwggEQhvniRiq0bY11TLuwEKwatfccFcqF9hM_1yd0-ND0tp1Hagdhu_BF6cRizTlXRQz-0eKswJi2vu-w35POue7MjsfZDFs/s2046/PXL_20211104_131312410-COLLAGE.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="2046" data-original-width="2046" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-8fLR_PkohXbO1JSbWGQ9dk6VOBSFZmmp9wMxCTjD99BwggEQhvniRiq0bY11TLuwEKwatfccFcqF9hM_1yd0-ND0tp1Hagdhu_BF6cRizTlXRQz-0eKswJi2vu-w35POue7MjsfZDFs/w640-h640/PXL_20211104_131312410-COLLAGE.jpg" width="640" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEha8cioJ5k5zDcs5oUN9wFH4t19W0xSouRJIQVLVmTsj9OjMSW6SbkDnZlUmaGm_1Sn4OvKVseOwzcJIBu5e5gNSdHQEy89f-tUTOlECSSAvd8GJmHPRWdlhwrSWU2dZpU9CNXK97jiJqI/s2046/PXL_20211104_131403845-COLLAGE.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="2046" data-original-width="2046" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEha8cioJ5k5zDcs5oUN9wFH4t19W0xSouRJIQVLVmTsj9OjMSW6SbkDnZlUmaGm_1Sn4OvKVseOwzcJIBu5e5gNSdHQEy89f-tUTOlECSSAvd8GJmHPRWdlhwrSWU2dZpU9CNXK97jiJqI/w640-h640/PXL_20211104_131403845-COLLAGE.jpg" width="640" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXdLGegr5PO0Buhv3Nhjsa4d6JIzeDdUyd1bD-vaFHJcgN_Kyg9fjYlK84sqiAMXnfr_o0x0BvTh2rtfNr3FIzA7mKC5Ea4RzQyjALCpLJUmCJU50ujwZVhTGXxp-vxlgbvj3opHElKVU/s2046/PXL_20211104_131508664-COLLAGE.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="2046" data-original-width="2046" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXdLGegr5PO0Buhv3Nhjsa4d6JIzeDdUyd1bD-vaFHJcgN_Kyg9fjYlK84sqiAMXnfr_o0x0BvTh2rtfNr3FIzA7mKC5Ea4RzQyjALCpLJUmCJU50ujwZVhTGXxp-vxlgbvj3opHElKVU/w640-h640/PXL_20211104_131508664-COLLAGE.jpg" width="640" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhX-UMsA9jifhpcwlUmTjHmOadoJt8KSWndR_9mqsTdC6E5GrEsEnS5gAaeNr8BAXt2efgPWmekAOtU6G2HrTAnEEnIpHb6abTjGy6xUt5Q4G-QQDdBd_TfYbFnvdzRNhz3ASgwfcLXkWY/s2046/PXL_20211104_131616915-COLLAGE.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="2046" data-original-width="2046" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhX-UMsA9jifhpcwlUmTjHmOadoJt8KSWndR_9mqsTdC6E5GrEsEnS5gAaeNr8BAXt2efgPWmekAOtU6G2HrTAnEEnIpHb6abTjGy6xUt5Q4G-QQDdBd_TfYbFnvdzRNhz3ASgwfcLXkWY/w640-h640/PXL_20211104_131616915-COLLAGE.jpg" width="640" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKd6GDZJWZB1Jmhbb6tqiwEAXoR6gTVbshSUgsIhN5aciAJOttpQ3EC7-z2R3qnTRyDGqvTsNWxdGXM9V-n3ScuwI2CltSZhUC3RUufGFeXUIb-vxArU-L8dkXUEOwfL8YysXEQ3ozOL0/s2046/PXL_20211104_130726883-COLLAGE.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="2046" data-original-width="2046" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKd6GDZJWZB1Jmhbb6tqiwEAXoR6gTVbshSUgsIhN5aciAJOttpQ3EC7-z2R3qnTRyDGqvTsNWxdGXM9V-n3ScuwI2CltSZhUC3RUufGFeXUIb-vxArU-L8dkXUEOwfL8YysXEQ3ozOL0/w640-h640/PXL_20211104_130726883-COLLAGE.jpg" width="640" /></a></div><br /> <p></p>Graham Whitehttp://www.blogger.com/profile/03878311939940449093noreply@blogger.com0tag:blogger.com,1999:blog-2027699993235411172.post-41012280061362927242021-09-28T19:21:00.001+01:002021-09-28T19:21:00.233+01:00Yet Another New Home Server<p>This year has seen me doing more in the way of little tech projects at home than I have done for a while, perhaps due to covid lock downs so if that's the case then I'll take this small positive from an otherwise rubbish situation. Typically for me, these projects have focused around open source projects and some IoT. More on those in some separate blog posts when I get around to writing them up. But for now, I wanted to make some notes on my new home server set up.</p><p>I've had an array of different low powered home servers of the years that I've <a href="http://gibbalog.blogspot.com/2011/04/another-new-home-server.html">previously written about</a>, namely the <a href="http://gibbalog.blogspot.com/search/label/nslu2">NSLU2</a>, <a href="http://gibbalog.blogspot.com/search/label/tinytuxbox">TinyTuxBox</a>, <a href="http://gibbalog.blogspot.com/search/label/joggler">Joggler</a> and for the past many years a simple <a href="http://gibbalog.blogspot.com/search/label/readynas">ReadyNAS</a> box that I specifically bought for the Intel processor as it made compiling different bits and pieces a whole lot easier back in the day. However, I have recently relegated the ReadyNAS box from home serving duties, keeping it only for its native NAS services because using it for other things has become increasingly difficult without updating the entire base OS (which is possible by I'm reluctant to do) due to down level software libraries like an ancient version of openssl.</p><p>In with the new then and I moved away from Intel architecture as it's now so much easier to compile for Arm chips and went with the, wait for it, drum roll, rather obvious choice of a Raspberry Pi 4. Specifically, a Pi 4 Model B, 4GB. I've paired it with the official Pi case power supply, micro HDMI cable and shoved in an A2 SanDisk Extreme 64GB SDXC card.</p><p>And so to the notes, my initial target for this new box would be as follows:</p><ul style="text-align: left;"><li><a href="https://thelounge.chat/">The Lounge</a> self hosted web based IRC interface <br /></li><li>A <a href="https://mosquitto.org/">Mosquitto</a> MQTT broker</li><li><a href="https://nodered.org/">Node Red</a> for home automation event processing</li><li>An <a href="https://www.nginx.com/">NGINX</a> reverse proxy<br /></li><li><a href="https://letsencrypt.org/">letsencrypt</a> certificates for all of the above<br /></li></ul><h4 style="text-align: left;">The Lounge</h4><div style="text-align: left;">IRC might be a bit old hat but tons of open source project still use it for their more synchronous communications. <a href="https://znc.in">ZNC</a> is the choice of old for staying connected to your IRC channels. For those not familiar, it acts as a relay to the IRC servers you want to connect to. Effectively, it connects as your IRC client to the servers and presents your local IRC client with an endpoint through which you can connect. This allows you never to miss any messages and see the IRC conversation even when you're not actually online. <a href="https://matrix.org/">Matrix</a> seems to be taking some of the old IRC community's attention with various projects setting up bridges between Matrix and IRC. However, the relative newcomer project called The Lounge shows just how far web technologies and web sockets have come. It's a darned site (pun intended) easier to install configure and use than ZNC so I'm a massive convert and big fan of the project.</div><div style="text-align: left;"><br /></div><div style="text-align: left;">The project is relatively stable in the master branch and doesn't release particularly often so I've open for the <a href="https://thelounge.chat/docs/install-and-upgrade#running-from-source">run from source</a> approach to take advantage of all the latest development. Other than that, I've only made 3 changes to the default configuration prior to starting up my The Lounge server:</div><div style="text-align: left;"><ol style="text-align: left;"><li>host: "127.0.0.1"</li><li>reverseProxy: true</li><li>theme: "morning"</li></ol></div><div style="text-align: left;">As you can see, these are all pretty simple and somewhat trivial changes. The host setting binds the listener to the localhost interface, thus making it suitable for use with a reverse proxy and not exposing the service outside of the Pi 4. The reverseProxy setting tells the server it's expecting to run behind a reverse proxy (the clue is in the name I guess). Finally, I've switched to using a dark mode theme rather than the default light mode. That's it, the remainder of the configuration is all about which IRC servers and channels to connect to along with the usual IRC bits of registering your nick and logging into the nick server.</div><div style="text-align: left;"><br /></div><div style="text-align: left;"><b>Mosquitto</b></div><div style="text-align: left;"><br /></div><div style="text-align: left;">This is even simpler to get going than The Lounge due to the fact it's bundled with Raspbian so you can just apt-get install it. I've created a configuration based on the bundled example config file but changing:</div><div style="text-align: left;"><ol style="text-align: left;"><li>pid_file (probably just because I'm old fashioned like that)</li><li>user (to drop privileges)</li><li>listener (to specify a port number)</li><li>certfile and keyfile (for SSL)</li><li>log_dest (create a specific log file for the broker)</li><li>clientid_prefixes (a bit of added security to only allow certain client IDs to connect to the broker)</li><li>allow_anonymous (quite an important one!)</li><li>password_file (so that connections are authenticated)</li></ol></div><div style="text-align: left;">Hopefully, that gives me something secure as well as providing me with the broker functionality that I need.</div><div style="text-align: left;"><br /></div><div style="text-align: left;"><b>Node Red</b></div><div style="text-align: left;"><br /></div><div style="text-align: left;">Again, simple to install as it's bundled with Raspbian. It does like to run under the default "pi" user though, which is a bit of a shame security wise. All I've done to the configuration is ensure it's listening only on the local interface and enable the adminAuth section such that I'm required to enter a user name and password to access the user interface.</div><div style="text-align: left;"><br /></div><div style="text-align: left;"><b>NGINX</b></div><div style="text-align: left;"><b> </b></div><div style="text-align: left;">Another simple install due to using the bundled version that comes with Raspbian. However, this time around there's a lot more configuration to do since I'm using it to front a reverse proxy onto The Lounge and Node Red. This gives me a few advantages such as being able to restart NGINX in order to load new SSL certificates without interrupting the underlying services i.e. something like IRC can stay connected even though new certs are loaded. Both The Lounge and Node Red support SSL in their configuration so this also means I only need to configure certificates in one place and have a single route through which I can access all my home services. The idea and bulk of the configuration for doing this comes directly from one of the <a href="https://thelounge.chat/docs/guides/reverse-proxies#nginx">guides</a> available for The Lounge.<br /></div><div style="text-align: left;"><br /></div><div style="text-align: left;"><span style="font-size: x-small;"><span style="font-family: courier;">server {</span></span></div><div style="text-align: left;"><span style="font-size: x-small;"><span style="font-family: courier;"> # redirect HTTP traffic to HTTPS<br /> listen 80 default_server;<br /> listen [::]:80 default_server;<br /> server_name _;<br /> return 301 https://$host$request_uri;<br />}<br /><br />server {<br /> # SSL configuration<br /> #<br /> listen 443 ssl default_server;<br /> listen [::]:443 ssl default_server;<br /> ssl_certificate /path/to/your/server.crt; <br /> ssl_certificate_key /path/to/your/server.key;<br /><br /> server_name your.server.name.com;<br /></span></span></div><div style="text-align: left;"><span style="font-size: x-small;"><span style="font-family: courier;"> </span></span></div><div style="text-align: left;"><span style="font-size: x-small;"><span style="font-family: courier;"> # Add this if you want to do web serving as well<span style="font-size: x-small;"><span style="font-family: courier;"><br /> root /var/www/html;<br /> index index.html index.htm;</span></span> </span></span></div><div style="text-align: left;"><span style="font-size: x-small;"><span style="font-family: courier;"> location / {<br /> # First attempt to serve request as file, then<br /> # as directory, then fall back to displaying a 404.<br /> try_files $uri $uri/ =404;<br /> }<br /></span></span></div><div style="text-align: left;"><span style="font-size: x-small;"><span style="font-family: courier;"> </span></span></div><div style="text-align: left;"><span style="font-size: x-small;"><span style="font-family: courier;"> # Configure reverse proxy for The Lounge<br /> location ^~ /YOUR_PREFERRED_IRC_URL_GOES_HERE/ {<br /> proxy_pass http://127.0.0.1:9000/;<br /> proxy_http_version 1.1;<br /> proxy_set_header Connection "upgrade";<br /> proxy_set_header Upgrade $http_upgrade;<br /> proxy_set_header X-Forwarded-For $remote_addr;<br /> proxy_set_header X-Forwarded-Proto $scheme;<br /><br /> # by default nginx times out connections in one minute<br /> proxy_read_timeout 1d;<br /> }<br /></span></span></div><div style="text-align: left;"><span style="font-size: x-small;"><span style="font-family: courier;"></span></span></div><div style="text-align: left;"><span style="font-size: x-small;"><span style="font-family: courier;"></span><span style="font-family: courier;"><br /></span></span><span style="font-size: x-small;"><span style="font-family: courier;"><span style="font-size: x-small;"><span style="font-family: courier;"> # Configure reverse proxy for Node Red</span></span><br /></span></span></div><div style="text-align: left;"><span style="font-size: x-small;"><span style="font-family: courier;"> location ^~ /</span></span><span style="font-size: x-small;"><span style="font-family: courier;"><span style="font-size: x-small;"><span style="font-family: courier;">YOUR_PREFERRED_NODERED_URL_GOES_HERE</span></span>/ {<br /> proxy_pass http://127.0.0.1:1880/;<br /> proxy_http_version 1.1;<br /> proxy_set_header Connection "upgrade";<br /> proxy_set_header Upgrade $http_upgrade;<br /> proxy_set_header X-Forwarded-For $remote_addr;<br /> proxy_set_header X-Forwarded-Proto $scheme;<br /><br /> # by default nginx times out connections in one minute<br /> proxy_read_timeout 1d;<br /> }<br />}</span></span></div><div style="text-align: left;"><span style="font-size: x-small;"><span style="font-family: courier;"> </span></span></div><div style="text-align: left;"><span style="font-family: inherit;"><span style="font-size: x-small;"><span><span><b><span style="font-size: small;">Let's Encrypt</span></b></span></span></span></span></div><div style="text-align: left;"><span>From Wikipedia: "<i>Let's Encrypt is a non-profit certificate authority run by
Internet Security Research Group that provides X.509 certificates for
Transport Layer Security encryption at no charge.</i></span><i><span><span></span></span></i>"<br /><span style="font-family: inherit;"></span></div><div style="text-align: left;"><span style="font-family: inherit;"></span><br /></div><div style="text-align: left;">The model for using letsencrypt is pretty simple. They sign your SSL certificates, free of charge, but their signing expires within 90 days. Hence, they're encouraging a high turnover of certificates by regular renewals. This means that realistically you need to automate the process of certificate signing. To do this I'm using the <a href="https://github.com/srvrco/getssl">getssl</a> script which makes life extremely easy when coupled with a cron job to kick off the script on a regular basis. I'm running it every day and the script decides whether to replace my existing certificates. It all sits there quite nicely running in the background and doesn't get in the way at all, restarting NGINX only when a new certificate is put in place. Due to the fact that NGINX is decoupled from the services it is proxying the other services aren't interrupted.<br /></div>Graham Whitehttp://www.blogger.com/profile/03878311939940449093noreply@blogger.com0tag:blogger.com,1999:blog-2027699993235411172.post-41416094972313252412020-12-02T20:21:00.001+00:002020-12-02T20:21:00.615+00:00Open Sourcing a NetworkManager VPN Plugin<p>It's not every day I find myself publishing a new project to open source and even less so when that requires release approval at work. I hope, over the years, I've written some useful bits and pieces and this time around I was keen to publish my work on the Internet rather than internally within the company. This requires following due process of course and seeking the relevant approval for the publication to take place.</p><p>Fortunately, in the right circumstances, IBM are very amenable to releasing code to open source. I was convinced enough that a <a href="https://en.wikipedia.org/wiki/NetworkManager">NetworkManager</a> plugin to add to the <a href="https://wiki.gnome.org/Projects/NetworkManager/VPN">existing list of VPN plugins</a> would not conflict with the business that an open source approval would be fairly trivial. Happily, I was correct, and going through the process wasn't too arduous with a few forms to fill in. These were, of course, designed much more for bigger releases than I planned so vastly over-engineered for this particular release but at least due diligence was applied.</p><p>On to the project and the code. It's not a world-changer but a small VPN plugin for NetworkManager to drive Cisco AnyConnect and made available as <a href="https://github.com/grahamwhiteuk/Networkmanager-anyconnect">NetworkManager-anyconnect on GitHub</a>. So I now know more than I'd care to mention about the inner workings of NetworkManager VPN plugins. They're not very well documented (hardly documented at all in fact) so they're quite hard work to produce by looking over existing code in available plugins. I started off from the <a href="https://gitlab.gnome.org/GNOME/NetworkManager-openvpn">OpenVPN plugin</a> which turned out to be a mistake as the code base is vastly bigger than that required for a plugin as simple as the one I wanted to write. Were I to start again, I would recommend starting from the <a href="https://github.com/danfruehauf/NetworkManager-ssh">SSH VPN plugin</a> instead as this is actually very nicely set out and doesn't include a lot of the shared bloat that comes with other plugins that are formally a part of NetworkManager.</p><p><br /></p>Graham Whitehttp://www.blogger.com/profile/03878311939940449093noreply@blogger.com0tag:blogger.com,1999:blog-2027699993235411172.post-35450580451074458892019-09-13T09:21:00.000+01:002019-12-09T20:05:21.380+00:00Installing Tensorflow GPU on Fedora LinuxFollowing on from my <a href="http://gibbalog.blogspot.com/2018/11/building-tensorflow-gpu-on-fedora-linux.html">previous notes</a> on building Tensorflow for a GPU on Fedora, I find myself back at it again. I recently upgraded my GPU at home and time has moved on too so this is my current set of notes for what I'm doing with Tensorflow on Fedora. This method, however, differs from my previous notes in as much as I'm using the pre-built Tensorflow rather than building my own. I've found that Tensorflow is so brittle during the build process it's much easier to work with pre-built binaries and set up my system to match their build.<br />
<br />
In my previous blog post I benchmarked the CPU versus GPU using the <a href="https://github.com/keras-team/keras/blob/master/examples/mnist_cnn.py">Keras MNIST CNN example</a> and so I thought it would be interesting to offer the same for this new install on my home machine. The results are :<br />
<ul>
<li>12 minutes and 14 seconds on my CPU</li>
<li>1 minutes and 14 seconds on my GPU</li>
</ul>
<div>
That's just over 9.9 as fast on my GPU as my CPU!<br />
<span style="background-color: white; color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif;"><br /></span>
<span style="background-color: white; color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif;">Some info on my machine and config:</span></div>
<ul>
<li><span style="background-color: white; color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif;">Custom Built Home PC</span></li>
<li><span style="background-color: white;"><span style="color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif;">Intel Core i5-3570K CPU @ 3.40GHz (4 cores)</span></span></li>
<li><span style="background-color: white;"><span style="color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif;">16GB RAM</span></span></li>
<li><span style="background-color: white;"><span style="color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif;">NVidia </span></span><span style="color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif;">GeForce GTX 1660 (CUDA Compute Capability 7.5)</span></li>
<li><span style="color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif;">Fedora 30 Workstation running kernel 5.2.9-200.fc30.x86_64</span></li>
</ul>
<span style="background-color: white; color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif;"><b>Background Information for NVidia Drivers</b></span><br />
<span style="background-color: white; color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif;">Previously, I've always used the <a href="https://negativo17.org/nvidia-driver/">Negativo17</a> repository for all my NVidia driver and CUDA needs. However, the software versions available there are too up-to-date to allow Tensorflow GPU to be installed in a way that works. This repository provides CUDA 10.1 where as Tensorflow, currently at version 1.14, only supports CUDA 10.0. So we must use another source for the NVidia software that provides back-level versions. Fortunately, there is an official <a href="http://developer.download.nvidia.com/compute/cuda/repos/">NVidia repository</a> providing drivers and CUDA for Linux, so let's use that since it also works quite nicely with the <a href="https://rpmfusion.org/">RPM Fusion</a> repositories as well. Hence, this method relies purely on RPM Fusion and the official NVidia repository and does not require or use the Negativo17 repository (although it would be possible to do so).</span><br />
<br />
<b style="background-color: white; color: #333333; font-family: arial, tahoma, helvetica, freesans, sans-serif;">Install Required NVidia Driver</b><br />
<span style="color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif;"><span style="background-color: white;">The <a href="https://rpmfusion.org/Howto/NVIDIA">RPM Fusion NVidia</a> instructions can be used here for more detail, but in brief simply install the display drivers:</span></span><br />
<ul>
<li><span style="background-color: white; color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif;">dnf install xorg-x11-drv-nvidia akmod-nvidia </span><span style="color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif;">xorg-x11-drv-nvidia-cuda</span></li>
</ul>
<span style="color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif;">There are some other bits you might want from this repository as well such as:</span><br />
<ul style="background-color: white; color: #333333; font-family: arial, tahoma, helvetica, freesans, sans-serif; line-height: 1.4; margin: 0.5em 0px; padding: 0px 2.5em;"></ul>
<div>
<ul>
<li><span style="color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif;">dnf install vdpauinfo libva-vdpau-driver libva-utils nvidia-modprobe</span></li>
</ul>
<span style="color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif;">Wait for the driver to build and reboot to get things up and running.</span></div>
<div>
<span style="color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif;"><span style="font-size: 13.86px;"><br /></span></span></div>
<div>
<span style="color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif;"><b>Install Required NVidia CUDA and Machine Learning Libraries</b></span></div>
<div>
<span style="color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif;">This step relies on using the official nvidia repositories with a little more information available in the <a href="https://rpmfusion.org/Howto/CUDA">RPM Fusion CUDA instructions</a>.</span></div>
<div>
<span style="color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif;"><br /></span></div>
<div>
<span style="color: #333333; font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif;">First of all, add a new yum configuration file. Copy the following to /etc/yum.repos.d/nvidia.repo:</span></div>
<div>
<span style="color: #333333;">
</span>
<br />
<div>
<span style="color: #333333; font-family: "courier new" , "courier" , monospace;"><span style="font-size: x-small;">[nvidia-cuda]</span></span></div>
<div>
<span style="color: #333333;"><span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;">name=</span><span style="font-family: "courier new" , "courier" , monospace;">nvidia-</span><span style="font-family: "courier new" , "courier" , monospace;">cuda</span></span></span><br />
<span style="color: #333333;"><span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">enabled=1</span></span><br />
<span style="color: #333333;"><span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">gpgcheck=1</span></span><br />
<span style="color: #333333;"><span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">gpgkey=http://developer.download.nvidia.com/compute/cuda/repos/fedora27/x86_64/7fa2af80.pub</span></span><br />
<span style="color: #333333;"><span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">exclude=akmod-nvidia*,kmod-nvidia*,*nvidia*,nvidia-*,cuda-nvidia-kmod-common,dkms-nvidia,nvidia-libXNVCtrl</span></span><br />
<span style="color: #333333;"><span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span>
<span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;">[</span><span style="font-family: "courier new" , "courier" , monospace;">nvidia-</span><span style="font-family: "courier new" , "courier" , monospace;">machine-learning]</span></span></span><br />
<span style="color: #333333;"><span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;">name=</span><span style="font-family: "courier new" , "courier" , monospace;">nvidia-</span><span style="font-family: "courier new" , "courier" , monospace;">machine-learning</span></span></span><br />
<span style="color: #333333;"><span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">baseurl=http://developer.download.nvidia.com/compute/machine-learning/repos/rhel7/x86_64/</span></span><br />
<span style="color: #333333;"><span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">enabled=1</span></span><br />
<span style="color: #333333;"><span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">gpgcheck=1</span></span><br />
<span style="color: #333333;"><span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">gpgkey=http://developer.download.nvidia.com/compute/machine-learning/repos/rhel7/x86_64/7fa2af80.pub</span></span><br />
<span style="color: #333333;"><span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">exclude=libcudnn7*.cuda10.1,libnccl*.cuda10.1</span></span></div>
<span style="color: #333333;">
</span>
<br />
<div style="font-family: arial, tahoma, helvetica, freesans, sans-serif; font-size: 13.86px;">
<span style="color: #333333;"><br /></span></div>
<span style="color: #333333;">
</span>
<br />
<div style="font-family: arial, tahoma, helvetica, freesans, sans-serif;">
<span style="color: #333333;">Note that the configuration above deliberately targets the fedora27 repository from NVidia. This is because it is the location at which we can find CUDA 10.0 compatible libraries rather than CUDA 10.1 libraries that will be found in later repositories. So the configuration above is likely to need to change over time but essentially the message here is that we can match the version of CUDA required by targeting the appropriate repository from NVidia. These libraries will be binary compatible with future versions of Fedora so this action should be safe to do for some time yet.</span></div>
<span style="color: #333333;">
</span>
<br />
<div style="font-family: arial, tahoma, helvetica, freesans, sans-serif;">
<span style="color: #333333;"><br /></span></div>
<span style="color: #333333;">
</span>
<br />
<div style="font-family: arial, tahoma, helvetica, freesans, sans-serif;">
<span style="color: #333333;">With the following configuration in place we can now install CUDA 10.0 and the machine learning libraries required for Tensorflow GPU support and all of the libraries get installed in the correct places that Tensorflow expects.</span></div>
<span style="color: #333333;">
</span>
<div style="font-family: arial, tahoma, helvetica, freesans, sans-serif;">
<span style="color: #333333;"><br /></span></div>
<span style="color: #333333;">
<div style="font-family: arial, tahoma, helvetica, freesans, sans-serif;">
To install, run:</div>
<div>
<ul>
<li><span style="color: #333333;"><div>
<span style="font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif;">dnf install cuda </span><span style="font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif;">libcudnn7 libnccl</span></div>
</span></li>
</ul>
<span style="font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif;"><b>Install Tensorflow GPU</b></span></div>
<div>
<span style="font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif;">The final piece of the puzzle is to install Tensorflow GPU which is now as easy as:</span></div>
<div>
<ul>
<li><span style="color: #333333;"><div>
<span style="font-family: "arial" , "tahoma" , "helvetica" , "freesans" , sans-serif;">pip3 install tensorflow-gpu</span></div>
</span></li>
</ul>
</div>
</span></div>
Graham Whitehttp://www.blogger.com/profile/03878311939940449093noreply@blogger.com8tag:blogger.com,1999:blog-2027699993235411172.post-84013390481682132322019-08-23T08:28:00.008+01:002023-03-08T09:38:41.909+00:00Migrating to Gnome 3<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOngkmE8bVzaZwZvto-LrPyruAFnxkiSuC-qxvVdW3qKuNDkLwrHPdomyrz3sfqTMR32ev5ditx1KYZapzGOrjX800Sp2JdSGHxVG2IixeqYaX9q0aWsddRxM1rNiDQa_Jb4qcnXA0yyo/s1600/gnome2-logo-text-128.png" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="128" data-original-width="128" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOngkmE8bVzaZwZvto-LrPyruAFnxkiSuC-qxvVdW3qKuNDkLwrHPdomyrz3sfqTMR32ev5ditx1KYZapzGOrjX800Sp2JdSGHxVG2IixeqYaX9q0aWsddRxM1rNiDQa_Jb4qcnXA0yyo/s1600/gnome2-logo-text-128.png" /></a></div>
I'm a massive laggard in the move to a Gnome 3 desktop. Colleagues and friends have been using it for years and to be honest, I've never been comfortable using it. But, that changed recently and I've actually grown to quite like the new desktop environment I find myself working in on a daily basis. So I've made a full-blooded leap to a modern desktop.<br />
<br />
Way-back when I started using Linux as a serious desktop alternative to Windows (in about 2000-2001 ish) I was running Gnome. I migrated away from that to KDE 3 and switched to Gnome 2 when KDE 4 was released as I didn't like the changes they had made and the new KDE 4 desktop was horribly buggy and unstable in my experience. (Maybe there's something about brand new desktops and my not taking a liking to them?) When Gnome released Gnome 3 I absolutely hated the user experience and used XFCE for a while before settling on the MATE desktop which I've been using for quite a few years now.<br />
<br />
Trying out Gnome 3 again recently and I was pleasantly surprised that the desktop has progressed significantly since those first few releases I couldn't get along with. But it's the addition of extensions that are the final straw in my move as I've found with just the right mix I can craft a desktop that gives me a nice balance between the new world and the old, much more familiar, world.<br />
<br />
So, the real purpose of this post is to share the extensions I've discovered. I'll document these below in brief but would also be interested to find others that are useful:<br />
<br />
<a href="https://extensions.gnome.org/extension/6/applications-menu/"><strike>Applications Menu</strike></a> (<i>updated 5th Feb 2021 - no longer in use, see below)</i><br />
This was right at the very top of my list of requirements for Gnome 3 usability. It simply puts an old school applications menu in the top bar, a bit like your old fashioned Windows start menu or similar from other desktops. I am, however, finding I use this very little now as the search hot-key in Gnome 3 does seem to be a quicker way of finding and starting programs.<br />
<br />
<a href="https://extensions.gnome.org/extension/3/bottom-panel/">Frippery Bottom Panel</a><br />
This is another of my top requirements for Gnome 3 usability. It gives you a panel at the bottom of the screen (D'uh) that allows you to switch easily between applications you have running. It also has a small workspace switcher which is why I like the Frippery version of this type of extension versus some of the others that don't have a workspace switcher capability.<br />
<br />
<a href="https://extensions.gnome.org/extension/1031/topicons/"><strike>Top Icons Plus</strike></a> <i>(update 5th Feb 2021 - no longer in use, replaced with AppIndicator, see below)</i><br />
Either the Top Icons or the Top Icons Plus extension that I'm using here seem so ubiquitous for Gnome 3 users I wonder why on earth they're not a default option, aside from the fact the Gnome 3 developers do seem to retain their keen vision on what a modern desktop should look like and "old" system tray icons are not part of that outlook. This extension, if you're not already using it, allows you to see system tray icons such as the ones used by Virt Manager or Slack, for example.<br />
<br />
<strike><a href="https://github.com/Keruspe/GPaste">GPaste</a></strike> (update 4th Nov 2021 - no longer in use, too difficult to configure and doesn't always work the way I expected, <strike>replaced with <a href="https://extensions.gnome.org/extension/779/clipboard-indicator/">Clipboard Indicator</a></strike>, updated again 8th Mar 2023, replaced with <a href="https://extensions.gnome.org/extension/5278/pano/">Pano Clipboard Manager</a>)<br />
A clipboard management system that has a nice integration with the Gnome 3 panel. I was previously using apps like ClipIt or Parcelite that do pretty much the same job.<br />
<br />
<a href="https://extensions.gnome.org/extension/83/lock-screen/"><strike>Lock Screen</strike></a> <i>(update 5th Feb 2021 - no longer in use, I wasn't using this as I just hit Win+L to lock)</i><br />
This adds a button to the gnome panel that, when clicked, locks your desktop. This would be the same as pressing Win+L on the keyboard. I was in the habit of using a graphical button on MATE so having this back in Gnome 3 gives me the experience I'm used to.<br />
<br />
<strike><a href="https://extensions.gnome.org/extension/118/no-topleft-hot-corner/">No TopLeft Hot Corner</a></strike> (update 5th Feb 2021 - no longer in use, Gnome Tweaks as a toggle for "Activities Overview Hot Corner" from the Top Bar options.<br />
I find the Gnome 3 facility to show activities when you mouse to the top left corner really annoying and it detracts from my productivity when it happens automatically. Fortunately, this extension disables that feature. It does make it more awkward to reach activities with the mouse (I'd have to click the applications menu first then select "Activities Overview") but I more or less always use the Windows key anyway.<br />
<br />
<a href="https://extensions.gnome.org/extension/8/places-status-indicator/"><strike>Places Status Indicator</strike></a> (update 8th Mar 2023 - no longer in use, I wasn't using it so have stopped installing it)<br />
This adds the old Gnome 2 style places menu to the Gnome 3 panel. I find I flip between using this menu to start navigating directories and just starting Gnome Files and going from there. Any which way, having this menu back on my desktop just makes it feel a bit more familiar and comfortable.<br />
<br /><strike>
<a href="https://extensions.gnome.org/extension/800/remove-dropdown-arrows/">Remove Dropdown Arrows</a></strike> <i>(update 5th Feb 2021 - no longer in use, Gnome seems to have gotten rid of most of these by default)</i><br />
The Gnome 3 panel insists on having an arrow indicator to show items that pull down a menu when clicked. These menus seem obvious to me and the arrows look rubbish and take up space, so this extension gets rid of them completely. Happy days.<br />
<br />
<a href="https://extensions.gnome.org/extension/826/suspend-button/" style="text-decoration-line: line-through;">Suspend Button</a> (update 5th Feb 2021 - no longer in use, Gnome now has a built-in suspend button)<br />
I run from a laptop most of the time and use the suspend feature every time I "shut down" my laptop. Bizarrely, there's no graphical facility (that I can find) in Gnome to suspend my machine. This extension adds a nice button to the status menu that immediately suspends my machine. Perfect.<br />
<br />
<a href="https://extensions.gnome.org/extension/120/system-monitor/">System Monitor</a><br />
Adds little graphs to the Gnome panel that show resource usage. The extension is pretty configurable but I have it showing CPU, memory and network utilisation. This allows me to keep an easy eye on my machine and how loaded it is at the current time. Extremely useful for spotting those occasional rogue apps that start eating an entire core of my CPU.<br />
<br />
<a href="https://extensions.gnome.org/extension/1101/media-keys/" style="text-decoration-line: line-through;">Media Keys</a> (update 5th Feb 2021 - no longer in use, Gnome has media controls built-in)<br />
I haven't decided how useful this one is going to be yet and it's currently turned off. However, when listening to Music through services like Amazon Music from a web browser it's nice to be able to control the audio without having to revert back to the browser ever time. This extension simply adds a few buttons to the Gnome panel to control your media. Handy if you haven't got the physical buttons on your keyboard too.<br />
<br />
<a href="https://extensions.gnome.org/extension/964/do-not-disturb-button/" style="text-decoration-line: line-through;">Do Not Disturb Button</a> (update 5th Feb 2021 - no longer in use, Gnome has the button built-in)<br />
I generally leave this extension disabled but it's useful to have installed and running when presenting or screen sharing. It saves any embarrassing situations of people being able to read your notifications while they're looking at your screen. Basically, it simply stops notifications being displayed, they're still received so you can go read them later.<br />
<br /><br />
<i>Blog edited with more extensions added on 28th August 2019:</i><br />
<a href="https://extensions.gnome.org/extension/4/panel-favorites/">Frippery Panel Favourites</a><br />
I'm not quite sure how I missed this from my original list as it's an extension I've been using more or less since day one in Gnome 3. It takes your favourite menu and adds this as a set of icons to the top of the Gnome Panel. Makes for extra quick access to your commonly used apps.<br />
<br />
Some more extensions have been brought to my attention since writing the list above. I've tried out all of the ones mentioned to me but these additions (below) are the ones that seem to have stuck.<br />
<br />
<a href="https://extensions.gnome.org/extension/517/caffeine/" style="text-decoration-line: line-through;">Caffeine</a> (update 5th Feb 2021 - no longer in use, using Gnome's built-in do not disturb button instead)<br />
This extension sits fairly well alongside the Do Not Disturb Button extension in my original list. This one simply disables the screen saver and auto suspend. Hence, in conjunction with Do Not Disturb, will make a good presentation or screen sharing environment.<br />
<br />
<a href="https://extensions.gnome.org/extension/28/gtile/">GTile</a><br />
This is a genius little extension that allows you to easily resize your windows in order to tile them across your display. I love the side-snapping in Gnome 3 that allows you to size a window to half the screen size. In my older desktops I also had corner snapping to size a window to a quarter of the screen, Gnome 3 doesn't have this by default. However, GTile adds an icon to your Gnome Panel that, when clicked, allows you to size to any area of your screen across a pre-defined grid - you can even change the grid size. Brilliant for usability with lots of on-screen windows at the same time.<br />
<br /><br />
<i>Blog edited to update the list of extensions I'm using on 5th February 2021:</i><div><b>Applications Menu</b></div><div>Just a note to say that after using Gnome 3 for quite some time now, I rarely (if ever) use the Applications Menu any longer. I tend to start applications either by pressing the Gnome hot key (Windows Key by default) and type in the search box, or by clicking on one of the favourites in the panel via the "Panel Favourites" extension.</div><div><br /></div><div><a href="https://extensions.gnome.org/extension/615/appindicator-support/">AppIndicator and KStatusNotifierItem Support</a></div><div>While the free desktop standard continues to specify the classic "icon tray" that was supported by extensions such as TopIcons, in reality few of the modern desktops (I'm referring to Gnome and KDE) support them. The modern take on the tray icon is an AppIndicator icon and many modern applications are written to use this standard (and perhaps fall back to a tray icon).</div><div><br /></div><div><i>Blog edited to update the list of extensions I'm using on 8th March 2023:</i></div><div>It's interesting to see how much use of extensions has changed over time. I'm using considerably fewer now than I was when I first started using Gnome 3. I put this down to two things: (1) Gnome is better at operating the way user's expect by removing the need for extensions such as the Suspend Button in the list above; and (2) I've become more institutionalised to the way that Gnome works, I'm much more familiar with it and have grown to like much of the way it works.<br /></div>Graham Whitehttp://www.blogger.com/profile/03878311939940449093noreply@blogger.com0tag:blogger.com,1999:blog-2027699993235411172.post-26047149189714463492019-04-03T11:51:00.045+01:002021-06-11T12:05:25.152+01:00Helping Disabled Passengers Travel with Confidence<p>This is a reproduction of a blog post originally made on the IBM Emerging Technology blog at https://www.ibm.com/blogs/emerging-technology/helping-disabled-passengers-travel-with-confidence/ (link now dead). Original article published on 3rd April 2019, re-publication to this blog was on 11th June 2021.<br /></p><p><b>Introduction</b> <br /></p><p>Disabled or disadvantaged passengers have every right to fear travelling with <a href="https://metro.co.uk/2018/05/18/rail-staff-told-not-help-disabled-passengers-board-makes-train-late-7556715/">multiple</a> <a href="https://www.channel4.com/news/how-paralympian-tanni-grey-thompson-had-to-crawl-from-train">high</a> <a href="https://www.channel4.com/news/no-go-britain-disabled-passengers-stranded-and-lost">profile</a> <a href="https://www.thetimes.co.uk/article/worst-rail-firm-leaves-disabled-ex-rugby-star-trapped-on-train-7slphgx20">cases</a>
of unfair and appalling levels of service evident in the media,
particularly for rail passengers. Our team have been tackling this
problem recently in collaboration with the IBM Travel and Transport team
and 50% funding through Innovate UK’s call for <a href="https://www.gov.uk/government/publications/funding-competition-accelerating-innovation-in-rail-round-4/competition-brief-accelerating-innovation-in-rail-round-4">Accelerating Innovation in Rail</a> (round 4). The project was the brain child of <a href="https://www.linkedin.com/in/sam-hopkins-b9245aa1/">Sam Hopkins</a> and won the internal IBM Hybrid Hackathon event in 2016.</p><p><b>The Problem</b></p><p><b> </b>The rail industry in the UK is a complex
one and travelling on our railways can be a difficult experience for
anybody. If you’re disabled then the experience can be difficult at best
and demeaning or impossible at worst. Depending on the type and
severity of their disability, disabled travellers need to plan for
eventualities such as whether a station is fully accessible, whether and
when staff are available to help, when and where they might be able to
use a toilet, how and where to board and alight the train, the list is
as long as the wide range of issues people may have. Today, <a href="http://www.nationalrail.co.uk/stations_destinations/disabled_passengers.aspx">assistance is on offer</a>,
but this is complex due to the nature of our fragmented system and
passengers (or their carers) may need to contact multiple companies 24
hours in advance of travel when planning their journey. This process of
organising their journey is extremely time consuming and can be as much
of a frustration as the journey itself.</p>
<p><b>The Challenges</b> </p><p>The UK rail industry is highly fragmented with different parts of the
operation split among different companies. For example, Network Rail
oversee the infrastructure such as maintaining tracks and signalling;
Rolling Stock Operating Companies (ROSCOs) own the trains; and Train
Operating Companies (TOCs) operate the trains and run passenger services
in different regions around the UK. In order for a disabled passenger
to make a journey, the Train Operating Companies are legally obliged to
provide support both off the train at the station and on board the train
during the journey. However, a passenger may be travelling through a
large number of regions and across services provides and hence need to
understand which company will be responsible for their journey at any
given stage. Understanding this takes quite a bit of research and can be
difficult, it also requires that everything they require on their
journey lines up across the network they’re travelling on and this is
certainly not guaranteed on our network today.</p><p><b>Our Solution</b> <br /></p>
<p><b></b></p><div class="separator" style="clear: both; text-align: center;"><b><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7O-nQ-bOQDkvthiwJpWCOS_By3StGplGICT4qJwZwHzdAztJwRDZ0JhoNlSUU2jvuiwn_jpncbrARvnM_nD-BkpkVLV3FNFzH4k9B2UqFm-bTEpxZtPKZ5Q9Y4qmoY4vriopnEKWB00M/s877/Screenshot+at+2019-04-03+08-25-14.png" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="877" data-original-width="431" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7O-nQ-bOQDkvthiwJpWCOS_By3StGplGICT4qJwZwHzdAztJwRDZ0JhoNlSUU2jvuiwn_jpncbrARvnM_nD-BkpkVLV3FNFzH4k9B2UqFm-bTEpxZtPKZ5Q9Y4qmoY4vriopnEKWB00M/w314-h640/Screenshot+at+2019-04-03+08-25-14.png" width="314" /></a></b></div><b></b><p></p><p>We have created a mobile application for disabled passengers, supported
by an enterprise grade back end architecture. During the project we
established a principle that the disabled passenger should always be
connected to a member of staff. This connection provides continuous
support available whenever required by the passenger and is designed to
help</p>
<p>alleviate the anxiety felt by this group of passengers when
travelling. The connection comes in the form of a chat application
similar to how passengers may already use common applications such as
WhatsApp or Facebook Messenger. The passenger can type anything they
want to the member of staff they’re connected to and get a human-level
response to their query from staff local to their situation. During
their journey, the passenger is handed over between staff members such
that they’re always connected with a local staff member who can offer
physical assistance if required.</p>
<p>A typical journey story starts with the user programming their
journey in a similar way to how they might on existing rail
applications. They search for their departure and destination stations
and select a time and route they wish to travel. Some time later, they
embark upon their journey. When they arrive at the station, they either
press a button to start the process or the app uses geolocation to
detect their arrival at the station. They are connected to a member of
the station staff who can answer questions and provide physical
assistance to board their first train. Once boarded, the station staff
hand the passenger over to a member of staff on board the train. This
hand-over process is transparent to the user and they will simply see a
new greeting from the next member of staff in the chain once they have
been connected. The process continues with the on train staff handing
over to station staff at the destination station in order to provide
assistance alighting the train. This process can repeat as many times as
necessary until the final destination is reached.</p>
<p><b>Technical Implementation</b> </p><p>Our solution has a strong server-side implementation with an MVP level front end to exercise the APIs provided.</p>
<p>We base the solution entirely within the <a href="https://www.ibm.com/uk-en/cloud">IBM Cloud</a>, using a <a href="https://www.ibm.com/uk-en/cloud/cloudant">Cloudant</a> instance for database hosting, <a href="https://www.ibm.com/uk-en/cloud/app-id">App ID</a> for authentication services, <a href="https://www.ibm.com/support/knowledgecenter/en/SSWMAJ_5.0.0/com.ibm.ism.doc/Overview/ov00000_.html">Message Sight</a> for highly reliable messaging built on top of the <a href="http://mqtt.org/">MQTT</a> protocol, and <a href="https://nodejs.org/">NodeJS</a> for writing our APIs on top of the Express framework and where necessary calling out to other APIs such as the <a href="https://www.transportapi.com/">Transport API</a>.
Security and privacy have been key concerns in the design to ensure
chat messages are securely delivered only to their intended recipient.
The application itself is authenticated at each of its routes and all of
the server-side APIs also use the same App ID authentication. Novel to
this solution is the capability of third-party authentication from
Message Sight to App ID, a first-of-a-kind implementation.</p>
<p>The front end application is currently written in VueJS. This has
been designed with accessibility in mind given the intended audience. It
is a simple interface conforming to web accessibility standards that is
compatible with screen readers. This component was never intended to be
the final solution and we see another interface being developed in the
future that is likely to build upon the current one. For example, a
fully native solution or perhaps one written to be more native-like
using technologies such as Native Script.</p>
<p><b>Moving Forward</b> </p><p>The solution is complete and ready, subject to customisation, to be
adopted by the UK train operating companies. However, we do see the need
for an improved user interface to be developed before the solution is
truly ready to be used in the wild.</p>
<p>Further to the current solution for the rail industry, we recognise
the issues faced by disabled travellers don’t stop with the UK rail
system. Similar issues are faced when using our road network, taxi
services, ferries and of course our airports. The principle established
within this project of alleviating anxiety through the connection to a
supporting human member of staff is likely to remain. We hope this is
extended into the other areas we’re considering with the next most
obvious choice to tackle being the airport use case.</p><p> </p>Graham Whitehttp://www.blogger.com/profile/03878311939940449093noreply@blogger.com0tag:blogger.com,1999:blog-2027699993235411172.post-61220118287667881262019-01-18T09:44:00.000+00:002019-01-28T15:23:22.142+00:00Self-Signing SSL/TLS CertificatesThings have changed a bit since I last looked into setting up a Certificate Authority (CA) and using that to self-sign my own certificates, not least that the use of the Common Name (CN) field appears to have changed. Chrome in particular <a href="https://support.google.com/chrome/a/answer/7391219">seems to insist</a> on the use of the Subject Alternative Names (SAN) extension rather than (or in addition to) using the CN field. So these are my notes on how to set up your own CA and use that to sign certificates. I'm conscious this is bound to go out of date so at the time of writing I'm working with Firefox 64, Chrome 71 and OpenSSL 1.1.1.<br />
<b><br /></b>
<b>Setup</b><br />
First of all, create a config file along the lines of the following and call it anything you like but for these notes I'm going to call it <i>ssl.conf</i>. Note, if you want to you can start with a different template or look at your own <i>openssl.cnf</i> file which on Linux is commonly found at <i>/etc/pki/tls/openssl.cnf</i>.<br />
<br />
<pre 10px="" style="background-color: #efefef; overflow: auto; padding: 10px;">[ req ]
default_bits = 4096
distinguished_name = req_distinguished_name
req_extensions = req_ext
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = GB
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = England
localityName = Locality Name (eg, city)
localityName_default = MyCity
organizationName = Organization Name (eg, company)
organizationName_default = MyOrg
commonName = Common Name (e.g. server FQDN or YOUR name)
commonName_max = 64
commonName_default = localhost
[ req_ext ]
subjectAltName = @alt_names
[alt_names]
DNS.1 = localhost
</pre>
<br />
You can change any of this template and indeed you'll need to change the common name for the certificates you're generating. The CN can be changed either on the command line during certificate creation or by changing the default in <i>ssl.conf</i>. You will also <b>need to change</b> the list of names under the "alt_names" section, this list should contain one line for each host name your machine might be known as. The list starts at DNS.1 for the first entry, then you can add DNS.2 for the second entry and so on.
<br />
<br />
NOTE: the specification and a lot of the documents available in this space indicate that an IP address can be used in the CN. My testing seems to indicate that while this is the case, certificates produced in this way will be rejected by modern browsers. Hence, you should list only hostnames as the CN but IP addresses still appear to be acceptable in as "alt_names".<br />
<br />
<b>Create a Certificate Authority</b><br />
You'll need a certificate and key file to act as your own CA:<br />
<br />
<pre style="background-color: #efefef; overflow: auto; padding: 10px;">openssl genrsa -out RootCA.key 4096
openssl req -x509 -new -nodes -key RootCA.key -sha256 -days 3650 -out RootCA.pem -config ssl.conf</pre>
<br />
You can inspect the certificate with:<br />
<pre style="background-color: #efefef; overflow: auto; padding: 10px;">openssl x509 -in RootCA.pem -text -noout</pre>
<br />
<b>Create a Certificate Signing Request (CSR)</b><br />
Now you have a CA you can create a CSR that can be used with your CA certificate to generate a client certificate:<br />
<br />
<pre style="background-color: #efefef; overflow: auto; padding: 10px;">openssl genrsa -out server.key 4096
openssl req -new -key server.key -out server.csr -config ssl.conf</pre>
<br />
You can inspect the certificate with:<br />
<pre style="background-color: #efefef; overflow: auto; padding: 10px;">openssl req -text -noout -verify -in server.csr</pre>
<br />
This time it's <b>really important</b> to ensure your host names are listed under the "X509v3 Subject Alternative Name" section of the certificate.
<br />
<br />
<b>Generate a Signed Certificate</b><br />
You can now use the CSR to create a signed certificate that can be used to serve up content over a secure connection:<br />
<br />
<pre style="background-color: #efefef; overflow: auto; padding: 10px;">openssl x509 -req -in server.csr -CA RootCA.pem -CAkey RootCA.key -CAcreateserial -out server.pem -days 3650 -sha256 -extensions req_ext -extfile ssl.conf</pre>
<br />
Note: if you want to create a different format of certificate here you can simply replace <i>server.pem</i> in the above command with something like <i>server.crt</i>, for example.
<br />
<br />
You can inspect the certificate with:<br />
<pre style="background-color: #efefef; overflow: auto; padding: 10px;">openssl x509 -in server.pem -text -noout</pre>
<br />
Again, it's <b>really important</b> to ensure your host names are listed under the "X509v3 Subject Alternative Name" section of the certificate.
<br />
<br />
<b>Use the Certificate Server Side</b><br />
You can now put your <i>server.pem</i> and <i>server.key</i>files to work and serve up content over a secure connection. There's too many ways to do that to list here but it could be used with a web server to serve HTTPS or a websockets server to serve some sort of socket connection as a couple of examples.<br />
<br />
If you want to inspect the certificate that's being used on the server, replace <hostname> and <port> in the command below:<br />
<br />
<pre style="background-color: #efefef; overflow: auto; padding: 10px;">openssl s_client -connect <hostname>:<port><port> | openssl x509 -noout -text</port></pre>
<br />
<b>Use the Certificate Client Side</b><br />
My use case here is with a web browser and so you'll want to import your <i>RootCA.pem</i> into your browser environment. There are two main ways of achieving this, you can either:<br />
<ol>
<li>Import directly to the browser</li>
<li>Import to the key store on your operating system</li>
</ol>
It's quicker and easier to import directly to the browser but this will of course only cover that one browser on your system whereas if you use the operating system method then any application that consults the OS for certificates will see your CA certificate.<br />
<br />
For Firefox, go to "View Certificates" in the preferences; click the "Authorities" tab and then the "Import" button; select your <i>RootCA.pem</i> file and click OK.<br />
<br />
For Chrome, go to "Manage Certificates" in the settings; click the "Authorities" tab and then the "Import" button; select your <i>RootCA.pem</i> file; click the check boxes to trust the certificate and click OK.Graham Whitehttp://www.blogger.com/profile/03878311939940449093noreply@blogger.com0tag:blogger.com,1999:blog-2027699993235411172.post-50385348732467689262018-11-16T22:44:00.000+00:002019-09-13T09:23:39.520+01:00Building Tensorflow GPU on Fedora Linux<i><update on Sept 13th 2019></i><br />
<i>I have written another post on how to install (rather than build) Tensorflow GPU for Fedora that uses a different and much simpler method. See <a href="http://gibbalog.blogspot.com/2019/09/installing-tensorflow-gpu-on-fedora.html">Installing Tensorflow GPU on Fedora Linux</a>.</i><br />
<i></update></i><br />
<br />
First off, let's say that there are easy ways of configuring Tensorflow for GPU usage such as using one of the <a href="https://www.tensorflow.org/install/docker">docker images</a>. However, I'm a bit old school for some things and having always done so I've recently got Tensorflow going on my machine using my GPU. Tensorflow CPU support is quite easy to do and generally works quite nicely using the <a href="https://www.tensorflow.org/install/pip">pip install</a> method. GPU support, I've always found, is quite a bit more difficult as there are a whole bunch of things that need to be at just the right level for everything to work i.e. it's quite brittle!<br />
<br />
What follows are my notes (it's in the name of the blog) for how to build Tensorflow from scratch to enable GPU support and I do this on Fedora Linux. If you want to know why it's worth bothering going to this effort, I've tested the <a href="https://github.com/keras-team/keras/blob/master/examples/mnist_cnn.py">Keras MNIST CNN example</a> as a bench mark. It takes:<br />
<ul>
<li>11 minutes 7 seconds on my CPU</li>
<li>2 minutes 55 seconds on my GPU</li>
</ul>
That's just over 3.8 as fast on my GPU as per my CPU so for large jobs this will be huge!<br />
<br />
Some info on my machine and config:<br />
<ul>
<li>Lenovo P50 Laptop</li>
<li>Intel Core i7-6820HQ CPU @ 2.70GHz (4 core with hyper threading)</li>
<li>32GB RAM</li>
<li>Nvidia Quadro M1000M (CUDA <a href="https://developer.nvidia.com/cuda-gpus">compute capability</a> 5.0)</li>
<li>Fedora 28 running kernel 4.18.18-200.fc28.x86_64</li>
</ul>
<b>Install Required Nvidia RPMs</b><br />
You need to get everything Nvidia and CUDA installed on your machine first. I quite like the <a href="https://negativo17.org/nvidia-driver/">Negativo17</a> repository for Nvidia on Fedora Linux and so I use this but you could also go with <a href="https://rpmfusion.org/Howto/NVIDIA">RPM Fusion</a> or even download everything directly from <a href="https://www.nvidia.com/object/unix.html">Nvidia</a>. For me, right now, I have this little lot installed:<br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">cuda-9.2.148.1-2.fc28.x86_64</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">cuda-cli-tools-9.2.148.1-2.fc28.x86_64</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">cuda-cublas-9.2.148.1-2.fc28.x86_64</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">cuda-cublas-devel-9.2.148.1-2.fc28.x86_64</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">cuda-cudart-9.2.148.1-2.fc28.x86_64</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">cuda-cudart-devel-9.2.148.1-2.fc28.x86_64</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">cuda-cudnn-7.2.1.38-1.fc28.x86_64</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">cuda-cudnn-devel-7.2.1.38-1.fc28.x86_64</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">cuda-cufft-9.2.148.1-2.fc28.x86_64</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">cuda-cufft-devel-9.2.148.1-2.fc28.x86_64</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">cuda-cupti-9.2.148.1-2.fc28.x86_64</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">cuda-cupti-devel-9.2.148.1-2.fc28.x86_64</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">cuda-curand-9.2.148.1-2.fc28.x86_64</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">cuda-curand-devel-9.2.148.1-2.fc28.x86_64</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">cuda-cusolver-9.2.148.1-2.fc28.x86_64</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">cuda-cusolver-devel-9.2.148.1-2.fc28.x86_64</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">cuda-cusparse-9.2.148.1-2.fc28.x86_64</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">cuda-cusparse-devel-9.2.148.1-2.fc28.x86_64</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">cuda-devel-9.2.148.1-2.fc28.x86_64</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">cuda-docs-9.2.148.1-2.fc28.noarch</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">cuda-gcc-7.3.0-1.fc28.x86_64</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">cuda-gcc-c++-7.3.0-1.fc28.x86_64</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">cuda-gcc-gfortran-7.3.0-1.fc28.x86_64</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">cuda-libs-9.2.148.1-2.fc28.x86_64</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">cuda-npp-9.2.148.1-2.fc28.x86_64</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">cuda-npp-devel-9.2.148.1-2.fc28.x86_64</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">cuda-nvgraph-9.2.148.1-2.fc28.x86_64</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">cuda-nvgraph-devel-9.2.148.1-2.fc28.x86_64</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">cuda-nvml-devel-9.2.148.1-2.fc28.x86_64</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">cuda-nvrtc-9.2.148.1-2.fc28.x86_64</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">cuda-nvrtc-devel-9.2.148.1-2.fc28.x86_64</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">cuda-nvtx-9.2.148.1-2.fc28.x86_64</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">cuda-nvtx-devel-9.2.148.1-2.fc28.x86_64</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">nvidia-driver-cuda-libs-410.73-4.fc28.x86_64</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span>
<span style="font-family: inherit;">You might wonder about some of the above, particularly why you might need a back level version of GCC. When Fedora 28 has a quite capable GCC version 8 why on earth would you want version 7? The answer lies in my comment about things being difficult or brittle, it's quite simply that CUDA doesn't yet support GCC 8 so you do need a back level compiler for this</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;"><b>Install NVidia NCCL</b></span><br />
This library isn't available through an RPM installation or the Negativo17 repository and so you must:<br />
<ul>
<li>Go to the <a href="https://developer.nvidia.com/nccl">Nvidia NCCL home page</a> </li>
<li>Click the link to download NCCL (requires an Nvidia developer login account)</li>
<li>Agree to the Terms and Conditions</li>
<li>Download the NCCL zipped tar file that matches your CUDA version (9.2 for this blog post)</li>
</ul>
<br />
At the time of writing the file required is <a href="https://developer.nvidia.com/compute/machine-learning/nccl/secure/v2.3/prod3/CUDA9.2/txz/nccl_2.3.7-1%2Bcuda9.2_x86_64.txz">nccl_2.3.7-1+cuda9.2_x86_64.txz</a><br />
<br />
I simply untar this file into /usr/local and create a symbolic link as follows:<br />
<ul>
<li>cd /usr/local</li>
<li>sudo tar -xf /path/to/file/nccl_2.3.7-1+cuda9.2_x86_64.txz</li>
<li>sudo ln -s nccl_2.3.7-1+cuda9.2_x86_64.txz nccl</li>
</ul>
<br />
<br />
<span style="font-family: inherit;"><b>Install the Bazel Build Tool</b></span><br />
You're going to need a build tool called <a href="https://bazel.build/">Bazel</a> which isn't directly available in the Fedora repositories (that I know of at least) but fortunately there's a version in a copr repository you can use <a href="https://docs.bazel.build/versions/master/install-redhat.html">as documented</a> run the following commands:<br />
<ul>
<li> dnf copr enable vbatts/bazel</li>
<li> dnf install bazel</li>
</ul>
<b>Get a Copy of Tensorflow Source</b><br />
For this it's just as easy to use git as it is anything else. You can directly clone the 1.12 release of Tensorflow into a new directory by running:<br />
<ul>
<li>git clone --single-branch -b r1.12 https://github.com/tensorflow/tensorflow tensorflow-r1.12</li>
<li>cd tensorflow-r1.12</li>
</ul>
Simply replace r1.12 in the above commands if you want to use a different Tensorflow release.<br />
<br />
<b>Run the Tensorflow Configure Script</b><br />
This step is actually quite simple but you'll need the answers to some questions to hand, simply run:<br />
<ul>
<li>./configure</li>
</ul>
I accept all the default options with the exception of:<br />
<ul>
<li>"location of python" set to /usr/bin/python3 since Fedora still uses Python 2.7 as the default version at /usr/bin/python</li>
<li>"build TensorFlow with CUDA support" set to Yes</li>
<li>"CUDA SDK version" set to 9.2 (this value should match the cuda version you have installed and at the time of writing 9.2 is the current version from the Negativo17 repository)</li>
<li>"location where CUDA 9.2 toolkit is installed" set to /usr</li>
<li>"cuDNN version" set to 7.2 (similar to the cuda version above, this value should match the cuda-cudnn package version and 7.2 is the current version from the Negativo17 repository)</li>
<li>"NCCL version" set to 2.3</li>
<li>"location where NCCL 2 library is installed" set to /usr/local/nccl</li>
<li>"Cuda compute capabilities you want to build with" set to 5.0 (but this value should match the CUDA compute capability of the GPU in the machine you're building for)</li>
<li>"which gcc" set to /usr/bin/cuda-gcc (to use the back level GCC version 7)</li>
</ul>
<br />
<br />
<div>
<b>Fix Bazel Config</b></div>
<div>
The above config command writes a file but the location isn't compatible with the latest version of Bazel. Presumably this issue will be fixed at some point in the future, it's not an issue with Bazel 0.18 and below as far as I'm aware, but has just become an issue on 0.19. Simply copy the config to the correct place:</div>
<div>
<ul>
<li>cat tools/bazel.rc >> .tf_configure.bazelrc</li>
</ul>
</div>
<div>
<b>Build Tensorflow with GPU Support</b></div>
<div>
This took around an hour to complete on my machine:</div>
<div>
<ul>
<li>bazel build --config=opt --config=cuda //tensorflow/tools/pip_package:build_pip_package</li>
<li>bazel-bin/tensorflow/tools/pip_package/build_pip_package /tmp/tensorflow_pkg</li>
</ul>
The first step is the long one for the build, the second simply builds the python wheel file.</div>
<div>
<br />
<b>Install Tensorflow with GPU Support</b></div>
<div>
You've got your wheel file so simply install and enjoy:</div>
<div>
<ul>
<li>pip3 install tensorflow-1.12.0-cp36-cp36m-linux_x86_64.whl </li>
</ul>
</div>
<div>
<b>Run Some Code</b></div>
<div>
The first time I attempted to run some code to test I got an <a href="https://github.com/tensorflow/tensorflow/issues/394">error</a>:</div>
<div>
<ul>
<li>failed call to cuInit: CUDA_ERROR_UNKNOWN</li>
</ul>
This can be solved by making sure you have the nvidia-modprobe package installed. Alternatively, you can run the little script below the following explanation.<br />
<br />
This seems to be some sort of permissions issue and running the following simple script to output the GPUs available on my machine but as root seems to have fixed the above issue i.e. put the following into a script, run that script as root, then any time you want to run code as an unprivileged user the above issue is fixed and the code will work:</div>
<div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">from keras import backend as K</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">K.tensorflow_backend._get_available_gpus()</span></div>
</div>
<div>
<br /></div>
<div>
If the above works then you can try out the <a href="https://github.com/keras-team/keras/blob/master/examples/mnist_cnn.py">Keras MNIST CNN example</a> code.</div>
Graham Whitehttp://www.blogger.com/profile/03878311939940449093noreply@blogger.com10tag:blogger.com,1999:blog-2027699993235411172.post-54212862634521185982018-11-05T16:18:00.000+00:002018-11-05T16:18:17.541+00:00VueJS Example for IBM App IDI was recently working on a project in <a href="https://vuejs.org/">VueJS</a> that needed an authorisation layer added to it. It turns out there aren't any existing examples of how to do this anywhere, unusually not even on <a href="https://stackoverflow.com/questions/tagged/ibm-appid">Stack Overflow</a>. So I set about writing one and thought I would share it. My work was based upon some other useful examples and information, particularly a <a href="https://www.ibm.com/blogs/bluemix/2018/04/securing-angularnode-js-applications-using-app-id/">blog post</a> from the IBM Cloud blog.<br />
<br />
Before I go any further, the code samples are available and documented on GitHub as follows:<br />
<br />
<ol>
<li>IBM App ID <a href="https://github.com/ibmets/appid-api-server">API Server</a></li>
<li>App ID <a href="https://github.com/ibmets/appid-vue-client">VueJS Client</a></li>
</ol>
<br />
The code is deliberately split into two such that:<br />
<ol>
<li>the API Server is used to demonstrate how to secure an API on the server side. This is done with the <a href="https://github.com/ibm-cloud-security/appid-serversdk-nodejs#protecting-web-applications-using-webappstrategy">WebAppStrategy</a> of App ID which is simply an implementation of a <a href="http://www.passportjs.org/packages/">strategy package</a> for <a href="http://www.passportjs.org/">passportjs</a>. The code here isn't anything particularly new over existing examples you can find on the web but it's necessary in order to fully demonstrate the capabilities of the client code.</li>
<li>the VueJS Client is used to demonstrate two things:</li>
<ol>
<li>how to secure a VueJS route for which I can currently find no example implementations on the web</li>
<li>how to call an API that has been secured by App ID by passing credentials through from the client application to the API server</li>
</ol>
</ol>
The API Server should be relatively trivial to get up and running as it's a standard NodeJS API implementation using Express. If you refer to the <a href="https://github.com/ibm-cloud-security/appid-serversdk-nodejs#protecting-web-applications-using-webappstrategy">WebAppStrategy</a> and the <a href="https://www.ibm.com/blogs/bluemix/2018/04/securing-angularnode-js-applications-using-app-id/">blog post</a> I mention above then you'll see the sample code I've come up with is broadly the same i.e. an amalgamation of the two.<br />
<br />
The VueJS Client code can be simple to get up and running as well but it's probably more important to understand how it was created such that you can apply the same principles in your own application(s). For this then, the explanation is a little longer...<br />
<br />
Start by running the VueJS command line client (cli) to create a bare project and for the sample to make sense you will need to add VueX and Router components using the tool:<br />
<blockquote class="tr_bq">
<span style="font-family: Courier New, Courier, monospace;">vue create vue-client</span></blockquote>
Then understand the 3 modifications you need to make in order to have a working set of authenticated routes.<br />
<br />
<b>1. A store for state. </b><br />
It doesn't really matter how you achieve this in VueJS, you can use any form of local state storage. The example code I have come up with uses VueX and a modification to the store.js code you get from the client above. The idea of this is such that the client application can cache whether the user has already authenticated themselves. If they have not then the client must request authentication via the server. If they have, then all the credentials required for making an authenticated call to a server-side API are already available in the browser. Essentially, this is a speed-up mechanism that stops the client from requesting client credentials on each API call since the session store for the authentication actually lives on the server side when using App ID.<br />
<br />
<b>2. A new VueJS Component</b><br />
This is the component whose route is to be protected via authentication. In the case of the example code below the standard vue cli "About" component has been used and modified slightly to include an authenticated call to the server API. The thing to note here is that the credentials from the client side must be sent over to the server with each API call. Using the <a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API">fetch</a> API as per the below to implement your GET request means you have to add the <i>credentials: 'include'</i> parameter.<br />
<br />
<pre style="background-color: #f6f8fa; border-radius: 3px; box-sizing: border-box; color: #24292e; font-family: SFMono-Regular, Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.6px; line-height: 1.45; overflow-wrap: normal; overflow: auto; padding: 16px; word-break: normal;"><span class="pl-k" style="box-sizing: border-box; color: #d73a49;"><</span>template<span class="pl-k" style="box-sizing: border-box; color: #d73a49;">></span>
<span class="pl-k" style="box-sizing: border-box; color: #d73a49;"><</span>div <span class="pl-k" style="box-sizing: border-box; color: #d73a49;">class</span><span class="pl-k" style="box-sizing: border-box; color: #d73a49;">=</span><span class="pl-s" style="box-sizing: border-box; color: #032f62;"><span class="pl-pds" style="box-sizing: border-box;">"</span>about<span class="pl-pds" style="box-sizing: border-box;">"</span></span><span class="pl-k" style="box-sizing: border-box; color: #d73a49;">></span>
<span class="pl-k" style="box-sizing: border-box; color: #d73a49;"><</span>h1<span class="pl-k" style="box-sizing: border-box; color: #d73a49;">></span>This is a <span class="pl-k" style="box-sizing: border-box; color: #d73a49;">protected</span> page<span class="pl-k" style="box-sizing: border-box; color: #d73a49;"><</span><span class="pl-k" style="box-sizing: border-box; color: #d73a49;">/</span>h1<span class="pl-k" style="box-sizing: border-box; color: #d73a49;">></span>
<span class="pl-k" style="box-sizing: border-box; color: #d73a49;"><</span>h2<span class="pl-k" style="box-sizing: border-box; color: #d73a49;">></span>hello<span class="pl-k" style="box-sizing: border-box; color: #d73a49;">:</span> {{ hello }}<span class="pl-k" style="box-sizing: border-box; color: #d73a49;"><</span><span class="pl-k" style="box-sizing: border-box; color: #d73a49;">/</span>h2<span class="pl-k" style="box-sizing: border-box; color: #d73a49;">></span>
<span class="pl-k" style="box-sizing: border-box; color: #d73a49;"><</span><span class="pl-k" style="box-sizing: border-box; color: #d73a49;">/</span>div<span class="pl-k" style="box-sizing: border-box; color: #d73a49;">></span>
<span class="pl-k" style="box-sizing: border-box; color: #d73a49;"><</span><span class="pl-k" style="box-sizing: border-box; color: #d73a49;">/</span>template<span class="pl-k" style="box-sizing: border-box; color: #d73a49;">></span>
<span class="pl-k" style="box-sizing: border-box; color: #d73a49;"><</span>script<span class="pl-k" style="box-sizing: border-box; color: #d73a49;">></span>
<span class="pl-k" style="box-sizing: border-box; color: #d73a49;">export</span> <span class="pl-c1" style="box-sizing: border-box; color: #005cc5;">default</span> {
<span class="pl-en" style="box-sizing: border-box; color: #6f42c1;">data</span><span class="pl-k" style="box-sizing: border-box; color: #d73a49;">:</span> <span class="pl-k" style="box-sizing: border-box; color: #d73a49;">function</span> () {
<span class="pl-k" style="box-sizing: border-box; color: #d73a49;">return</span> {
hello<span class="pl-k" style="box-sizing: border-box; color: #d73a49;">:</span> <span class="pl-c1" style="box-sizing: border-box; color: #005cc5;">undefined</span>
}
},
computed<span class="pl-k" style="box-sizing: border-box; color: #d73a49;">:</span> {
<span class="pl-en" style="box-sizing: border-box; color: #6f42c1;">user</span> () {
<span class="pl-k" style="box-sizing: border-box; color: #d73a49;">return</span> <span class="pl-c1" style="box-sizing: border-box; color: #005cc5;">this</span>.<span class="pl-smi" style="box-sizing: border-box;">$store</span>.<span class="pl-smi" style="box-sizing: border-box;">state</span>.<span class="pl-smi" style="box-sizing: border-box;">user</span>
}
},
methods<span class="pl-k" style="box-sizing: border-box; color: #d73a49;">:</span> {
<span class="pl-en" style="box-sizing: border-box; color: #6f42c1;">getProtectedAPI</span> () {
<span class="pl-en" style="box-sizing: border-box; color: #6f42c1;">fetch</span>(<span class="pl-s" style="box-sizing: border-box; color: #032f62;"><span class="pl-pds" style="box-sizing: border-box;">'</span>http://localhost:3000/protected/get-some-info<span class="pl-pds" style="box-sizing: border-box;">'</span></span>,{
credentials<span class="pl-k" style="box-sizing: border-box; color: #d73a49;">:</span> <span class="pl-s" style="box-sizing: border-box; color: #032f62;"><span class="pl-pds" style="box-sizing: border-box;">'</span>include<span class="pl-pds" style="box-sizing: border-box;">'</span></span>,
}).<span class="pl-c1" style="box-sizing: border-box; color: #005cc5;">then</span>(<span class="pl-smi" style="box-sizing: border-box;">res</span> <span class="pl-k" style="box-sizing: border-box; color: #d73a49;">=></span> <span class="pl-smi" style="box-sizing: border-box;">res</span>.<span class="pl-c1" style="box-sizing: border-box; color: #005cc5;">text</span>())
.<span class="pl-c1" style="box-sizing: border-box; color: #005cc5;">then</span>(<span class="pl-smi" style="box-sizing: border-box;">body</span> <span class="pl-k" style="box-sizing: border-box; color: #d73a49;">=></span> {
<span class="pl-en" style="box-sizing: border-box; color: #6f42c1;">console</span>.<span class="pl-c1" style="box-sizing: border-box; color: #005cc5;">dir</span>(body)
<span class="pl-c1" style="box-sizing: border-box; color: #005cc5;">this</span>.<span class="pl-smi" style="box-sizing: border-box;">hello</span> <span class="pl-k" style="box-sizing: border-box; color: #d73a49;">=</span> <span class="pl-c1" style="box-sizing: border-box; color: #005cc5;">JSON</span>.<span class="pl-c1" style="box-sizing: border-box; color: #005cc5;">parse</span>(body).<span class="pl-smi" style="box-sizing: border-box;">hello</span>
})
},
},
<span class="pl-en" style="box-sizing: border-box; color: #6f42c1;">created</span>() {
<span class="pl-c1" style="box-sizing: border-box; color: #005cc5;">this</span>.<span class="pl-en" style="box-sizing: border-box; color: #6f42c1;">getProtectedAPI</span>()
}
} </pre>
<span class="pl-k" style="box-sizing: border-box; color: #d73a49; font-family: SFMono-Regular, Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.6px;"><</span><span class="pl-k" style="box-sizing: border-box; color: #d73a49; font-family: SFMono-Regular, Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.6px;">/</span><span style="background-color: #f6f8fa; color: #24292e; font-family: SFMono-Regular, Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.6px;">script</span><span class="pl-k" style="box-sizing: border-box; color: #d73a49; font-family: SFMono-Regular, Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.6px;">></span><br />
<br />
<b>3. A VueJS Navigation Guard</b><br />
You need to write a function that will be added as a VueJS middleware upon each route change. The middleware is inserted automatically by the VueJS route code when using the beforeEnter call on a route. This is known in VueJS as a <a href="https://router.vuejs.org/guide/advanced/navigation-guards.html">Navigation Guard</a>.<br />
<br />
<pre style="background-color: #f6f8fa; border-radius: 3px; box-sizing: border-box; color: #24292e; font-family: SFMono-Regular, Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.6px; line-height: 1.45; overflow-wrap: normal; overflow: auto; padding: 16px; word-break: normal;"><span class="pl-k" style="box-sizing: border-box; color: #d73a49;">function</span> <span class="pl-en" style="box-sizing: border-box; color: #6f42c1;">requireAuth</span>(<span class="pl-smi" style="box-sizing: border-box;">to</span>, <span class="pl-smi" style="box-sizing: border-box;">from</span>, <span class="pl-smi" style="box-sizing: border-box;">next</span>) {
<span class="pl-c" style="box-sizing: border-box; color: #6a737d;"><span class="pl-c" style="box-sizing: border-box;">//</span> Testing authentication state of the user</span>
<span class="pl-k" style="box-sizing: border-box; color: #d73a49;">if</span> (<span class="pl-k" style="box-sizing: border-box; color: #d73a49;">!</span><span class="pl-smi" style="box-sizing: border-box;">store</span>.<span class="pl-smi" style="box-sizing: border-box;">state</span>.<span class="pl-smi" style="box-sizing: border-box;">user</span>.<span class="pl-smi" style="box-sizing: border-box;">logged</span>) {
<span class="pl-c" style="box-sizing: border-box; color: #6a737d;"><span class="pl-c" style="box-sizing: border-box;">//</span> Not sure if user is logged in yet, testing their login</span>
<span class="pl-k" style="box-sizing: border-box; color: #d73a49;">const</span> <span class="pl-c1" style="box-sizing: border-box; color: #005cc5;">isLoggedUrl</span> <span class="pl-k" style="box-sizing: border-box; color: #d73a49;">=</span> <span class="pl-s" style="box-sizing: border-box; color: #032f62;"><span class="pl-pds" style="box-sizing: border-box;">"</span>http://localhost:3000/auth/logged<span class="pl-pds" style="box-sizing: border-box;">"</span></span>
<span class="pl-en" style="box-sizing: border-box; color: #6f42c1;">fetch</span>(isLoggedUrl, {credentials<span class="pl-k" style="box-sizing: border-box; color: #d73a49;">:</span> <span class="pl-s" style="box-sizing: border-box; color: #032f62;"><span class="pl-pds" style="box-sizing: border-box;">'</span>include<span class="pl-pds" style="box-sizing: border-box;">'</span></span>}).<span class="pl-c1" style="box-sizing: border-box; color: #005cc5;">then</span>(<span class="pl-smi" style="box-sizing: border-box;">res</span> <span class="pl-k" style="box-sizing: border-box; color: #d73a49;">=></span> <span class="pl-smi" style="box-sizing: border-box;">res</span>.<span class="pl-en" style="box-sizing: border-box; color: #6f42c1;">json</span>()).<span class="pl-c1" style="box-sizing: border-box; color: #005cc5;">then</span>(<span class="pl-smi" style="box-sizing: border-box;">isLogged</span> <span class="pl-k" style="box-sizing: border-box; color: #d73a49;">=></span> {
<span class="pl-k" style="box-sizing: border-box; color: #d73a49;">if</span> (<span class="pl-smi" style="box-sizing: border-box;">isLogged</span>.<span class="pl-smi" style="box-sizing: border-box;">logged</span>) {
<span class="pl-c" style="box-sizing: border-box; color: #6a737d;"><span class="pl-c" style="box-sizing: border-box;">//</span> User is already logged in, storing</span>
<span class="pl-smi" style="box-sizing: border-box;">store</span>.<span class="pl-en" style="box-sizing: border-box; color: #6f42c1;">commit</span>(<span class="pl-s" style="box-sizing: border-box; color: #032f62;"><span class="pl-pds" style="box-sizing: border-box;">"</span>setUser<span class="pl-pds" style="box-sizing: border-box;">"</span></span>, isLogged)
<span class="pl-en" style="box-sizing: border-box; color: #6f42c1;">next</span>()
} <span class="pl-k" style="box-sizing: border-box; color: #d73a49;">else</span> {
<span class="pl-c" style="box-sizing: border-box; color: #6a737d;"><span class="pl-c" style="box-sizing: border-box;">//</span> User is not logged in, redirecting to App ID</span>
<span class="pl-c1" style="box-sizing: border-box; color: #005cc5;">window</span>.<span class="pl-c1" style="box-sizing: border-box; color: #005cc5;">location</span>.<span class="pl-c1" style="box-sizing: border-box; color: #005cc5;">href</span><span class="pl-k" style="box-sizing: border-box; color: #d73a49;">=</span><span class="pl-s" style="box-sizing: border-box; color: #032f62;"><span class="pl-pds" style="box-sizing: border-box;">`</span>http://localhost:3000/auth/login?redirect=<span class="pl-s1" style="box-sizing: border-box; color: #24292e;"><span class="pl-pse" style="box-sizing: border-box;">${</span><span class="pl-smi" style="box-sizing: border-box;">to</span>.<span class="pl-smi" style="box-sizing: border-box;">fullPath</span><span class="pl-pse" style="box-sizing: border-box;">}</span></span><span class="pl-pds" style="box-sizing: border-box;">`</span></span>
}
}).<span class="pl-c1" style="box-sizing: border-box; color: #005cc5;">catch</span>(<span class="pl-smi" style="box-sizing: border-box;">e</span> <span class="pl-k" style="box-sizing: border-box; color: #d73a49;">=></span> {
<span class="pl-c" style="box-sizing: border-box; color: #6a737d;"><span class="pl-c" style="box-sizing: border-box;">//</span> TODO: do something sensible here so the user sees their login has failed</span>
<span class="pl-en" style="box-sizing: border-box; color: #6f42c1;">console</span>.<span class="pl-c1" style="box-sizing: border-box; color: #005cc5;">log</span>(<span class="pl-s" style="box-sizing: border-box; color: #032f62;"><span class="pl-pds" style="box-sizing: border-box;">"</span>Testing user login failed - D'oh!<span class="pl-pds" style="box-sizing: border-box;">"</span></span>)
})
} <span class="pl-k" style="box-sizing: border-box; color: #d73a49;">else</span> {
<span class="pl-c" style="box-sizing: border-box; color: #6a737d;"><span class="pl-c" style="box-sizing: border-box;">//</span> User already logged in</span>
<span class="pl-en" style="box-sizing: border-box; color: #6f42c1;">next</span>()
}
}</pre>
<br />
The requireAuth function does the following in plain English:<br />
<br />
<ol>
<li>Using the VueJS client side cache, test if the user is already logged in</li>
<li>If they are not. then ask the server if the user is already logged in</li>
<ol>
<li>If they are not, then redirect them to the server login page</li>
<li>If they are, then cache the information and load the next piece of middleware</li>
</ol>
<li>If they are, then simply load the next piece of middleware</li>
</ol>
<br />
<br />
Each route you want to protect with the above function must have a <i>beforeEnter: requireAuth</i> parameter specified on the route. When this is done, VueJS will call the requireAuth function before the component specified by the route is loaded.<br />
<i><br /></i>
<pre style="background-color: #f6f8fa; border-radius: 3px; box-sizing: border-box; color: #24292e; font-family: SFMono-Regular, Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 13.6px; line-height: 1.45; overflow-wrap: normal; overflow: auto; padding: 16px; word-break: normal;">{
path<span class="pl-k" style="box-sizing: border-box; color: #d73a49;">:</span> <span class="pl-s" style="box-sizing: border-box; color: #032f62;"><span class="pl-pds" style="box-sizing: border-box;">'</span>/protected<span class="pl-pds" style="box-sizing: border-box;">'</span></span>,
name<span class="pl-k" style="box-sizing: border-box; color: #d73a49;">:</span> <span class="pl-s" style="box-sizing: border-box; color: #032f62;"><span class="pl-pds" style="box-sizing: border-box;">'</span>protected<span class="pl-pds" style="box-sizing: border-box;">'</span></span>,
beforeEnter<span class="pl-k" style="box-sizing: border-box; color: #d73a49;">:</span> requireAuth,
component<span class="pl-k" style="box-sizing: border-box; color: #d73a49;">:</span> Protected
}</pre>
<i><br /></i>
<i>Note: there are methods by which you don't have do call window.location.href to redirect the user to the login page (which does seem like a bit of a nasty hack. However, these methods require the modification of the webpack configuration and so were kept out of scope of this example for the purposes of being simple.</i><br />
<i><br /></i>Graham Whitehttp://www.blogger.com/profile/03878311939940449093noreply@blogger.com0tag:blogger.com,1999:blog-2027699993235411172.post-63282895042247205592018-06-04T13:07:00.000+01:002018-06-07T21:05:15.374+01:00South Downs Way WalkI've just finished a pretty extraordinary journey, both physically and mentally, here's the story...<br />
<br />
<b>The Short Version - 100 Miles, 4 Days, 2 Charities</b><br />
<b><br /></b>
This bit of the blog post is a summary for the <acronym title="Too Long; Didn't Read">TL;DR</acronym> brigade...<br />
<ul>
<li>Starting in Eastbourne on 31st May</li>
<li>More or less 4 marathons in 4 days</li>
<li>Finishing in Winchester on 3rd June</li>
<li>Raising funds for:</li>
<ul>
<li>The National Eczema Society</li>
<li>Parkinson's UK</li>
</ul>
<li>You can still donate (please do):</li>
<ul>
<li><a href="https://uk.virginmoneygiving.com/team/DadsbeingLads">https://uk.virginmoneygiving.com/team/DadsbeingLads</a></li>
</ul>
<li>We raised over £4500 (more than £5500 including gift aid)</li>
</ul>
<div>
<br /></div>
<div>
I have made all the pictures available on Flickr in my <a href="https://www.flickr.com/photos/graham_alton/albums/72157669748029898">South Downs Way Walk Album</a>.</div>
<br />
<br />
<b>The Longer Version</b><br />
<b><br /></b>
My best mate decided he wanted to challenge himself as a consequence of coming to terms with his 40th birthday. He called a few of us to the pub a few months back. We settled on the idea of walking the South Downs Way in 4 days for 2 charities. I was nuts enough to go along with this idea and I'm writing the morning after successfully finishing the entire route with him.<br />
<br />
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCc4MxlW9mdVsx3oP_m_F_wkQMQtEDYs28b_WucKF4qBfkCCN0AuYqvXbSyJ5cjKxz0bMo_Uy1kQ9IzqqokGJT0HS0V9CVu4rySs5Zx03LjmL5waVgfmMzRXPOckKF83HLRJ9dqmtcVl4/s1600/IMG_20180530_190851.jpg" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img alt="All done and in the restaurant at the finish" border="0" data-original-height="1200" data-original-width="1600" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCc4MxlW9mdVsx3oP_m_F_wkQMQtEDYs28b_WucKF4qBfkCCN0AuYqvXbSyJ5cjKxz0bMo_Uy1kQ9IzqqokGJT0HS0V9CVu4rySs5Zx03LjmL5waVgfmMzRXPOckKF83HLRJ9dqmtcVl4/s320/IMG_20180530_190851.jpg" title="All done and in the restaurant at the finish" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">In the car on the way to get started...</td></tr>
</tbody></table>
<div>
The people you need to know about in this story are:</div>
<div>
<ul>
<li>Matt Wettone - team leader</li>
<li>Me (obviously)</li>
<li>Andy McGrath - team super hero</li>
<li>Pete and Phil - team members</li>
<li>Stephen Warwick - honorary team member</li>
<li>Tim - Matt's dad, team logistics</li>
<li>Linda - Matt's mum, team chef</li>
</ul>
</div>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgl-FgxAq2Q66LTv_2gs5QnAUU6Z0x7Vf9yq1GH0WE1RJtSLR-GoHmElq19ReshQxEQDseHBMC_zlhdQ7qP_VPGRhehyphenhyphenQXV-HXXsgq0th9uPSOF4Q-4P6lN6NeZaFKWl00MIHCuRjtXCLw/s1600/IMG_20180603_180319.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img alt="All done and in the restaurant at the finish" border="0" data-original-height="1200" data-original-width="1600" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgl-FgxAq2Q66LTv_2gs5QnAUU6Z0x7Vf9yq1GH0WE1RJtSLR-GoHmElq19ReshQxEQDseHBMC_zlhdQ7qP_VPGRhehyphenhyphenQXV-HXXsgq0th9uPSOF4Q-4P6lN6NeZaFKWl00MIHCuRjtXCLw/s320/IMG_20180603_180319.jpg" title="All done and in the restaurant at the finish" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">...all done and in the restaurant at the finish</td></tr>
</tbody></table>
<div>
<div>
<br />
The reason for doing this has already been much better explained by Matt than I'll manage to come up with so if you're interested in that then head over to <a href="https://uk.virginmoneygiving.com/team/DadsbeingLads">our donation page</a> or I've saved a copy of his text at the bottom of this post. My personal reasons are fairly simple in as much as I'd find it hard to turn Matt down, doing something for charity is always worthwhile and challenging yourself every now and then has to be worth something as well.</div>
<div>
<br /></div>
<div>
It turns out that it certainly was a challenge both physically and mentally. I'll try to be brief below with a summary of each day...</div>
<div>
<br /></div>
<div>
<b>Day 1 - Eastbourne to Housedene Farm</b></div>
<div>
<b><br /></b></div>
<div>
Vital statistics: 27.4 miles in 8 hours 26 minutes moving time (3.25 MPH, moving average), about 58,000 steps and 3968 feet of elevation gain.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiUH8Cs-4XkfKtWtu9spWXFQuVnlMTva3CZA6i8f_zvCdVCTh8L7dpg1BRo7BXma4_-Zd5n2ArVtoOM_pCuF_1fbX4jG8I_niqC5cz9uPgyQoQevEB1wi3xH3JPKHFEYyQLvxL6I_G2G0/s1600/Strava+Day+1.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1200" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiUH8Cs-4XkfKtWtu9spWXFQuVnlMTva3CZA6i8f_zvCdVCTh8L7dpg1BRo7BXma4_-Zd5n2ArVtoOM_pCuF_1fbX4jG8I_niqC5cz9uPgyQoQevEB1wi3xH3JPKHFEYyQLvxL6I_G2G0/s320/Strava+Day+1.jpeg" width="320" /></a></div>
<div>
<br /></div>
<div>
We planned Day 1 to be 24 miles long but ended up doing 27.4 miles. This was due to starting further back than the documented start of the South Downs Way, we started at Eastbourne Pier, another 1.5 miles along the coast. Also, the distance charts for the Eastern half of the walk seem to be about 10% out in terms of accuracy so we picked up another couple of miles we weren't expecting.</div>
<div>
<br /></div>
<div>
Matt, Andy and I left Eastbourne in heavy rain. I think we were all excited and apprehensive but keen to get started. After the first couple of miles, we climbed up onto the Seven Sisters and for the next 10 miles or so found ourselves repeatedly going up and down each of the 7 cliffs. That was really hard work, especially in poor weather, and set the tone for the rest of the day as being a really tough day.</div>
<div>
<br /></div>
<div>
We pretty much dodged a bullet with the weather though, the rain cleared up by around 11am and it became overcast and warm for the remainder of the day, perfect walking weather. The rest of the country seemingly got drowned in thundery showers that day so we were really lucky.</div>
<div>
<br /></div>
<div>
We finished the day in good spirits but with Andy starting to struggle a bit with a knee problem and having picked up a blister along the route somewhere.</div>
<div>
<b><br /></b></div>
<div>
<b>Day 2 - Housedene Farm Camp Site to Amberley</b></div>
<div>
<b><br /></b></div>
<div>
Vital statistics: 29.7 miles in 9 hours 5 minutes moving time (3.23 MPH, moving average), about 62,000 steps and 3186 feet of elevation gain.</div>
<div>
<b><br /></b></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRCvwnAitLHiz5ZwCi-JMsEgsFSCvC2dDEnfN1FWf7yVQDzgpHwjRCl0cVeVKXHJJD9Hoi-sjxKBz8GYT1t-DrQHqL_FicLML8b_BV82cz0enMccC7rkUnmn9NzQwg7Qw2Z_rPtcT9hJY/s1600/Strava+Day+2.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1200" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRCvwnAitLHiz5ZwCi-JMsEgsFSCvC2dDEnfN1FWf7yVQDzgpHwjRCl0cVeVKXHJJD9Hoi-sjxKBz8GYT1t-DrQHqL_FicLML8b_BV82cz0enMccC7rkUnmn9NzQwg7Qw2Z_rPtcT9hJY/s320/Strava+Day+2.jpeg" width="320" /></a></div>
<div>
<b><br /></b></div>
<div>
<br /></div>
<div>
This route was also longer than the planned 26.5 miles we had in mind for day 2. We picked up the trail where we left off the previous evening at Housedene Farm and walked to Amberley. Pete joined us, meeting at the start point in the morning and intending to walk the next 2 days.</div>
<div>
<br /></div>
<div>
Andy put in a heroic effort just to be ready for the start. From the previous day, all of us thought there was a real danger he may have to pull out for at least day 2, but somehow he managed to be ready and start walking with us again.</div>
<div>
<br /></div>
<div>
The weather was decent enough for walking in as much as it wasn't sunny and the temperature was probably mid teens. However, we basically spent the entire day walking through cloud. The most we saw all day was dew drops forming in our hair from all the moisture in the air. The dampness did make it a little tougher but we found the biggest drawback of this weather was the lack of reward for climbing some enormous hills. For example, we walked the length of the south rim of Devil's Dyke and none of us have the foggiest (pun intended) idea what it looks like. Visibility was between 20 and 100 yards all day!</div>
<div>
<br /></div>
<div>
At about 18 miles Pete wasn't able to continue, having aggravated an old knee injury. We decided it was best for him to leave the trail and get picked up early so he headed to a nearby road for rescue. At that point, Andy took the tactical decision to accompany Pete on the journey home to give himself more time and a better chance of recovery to finish the route, leaving just Matt and I. This was definitely one of the low points for all of us in the team that day.</div>
<div>
<br /></div>
<div>
Matt and I soldiered on through the cloud for another 11-12 miles after that. We were due to be picked up at the agreed point but due to a traffic accident and resulting traffic chaos, Tim was unable to meet us until 40 minutes or so after our agreed meet time. Matt and I decided to add some more miles to make day 3 a bit shorter and easier.</div>
<div>
<br /></div>
<div>
<b><br /></b></div>
<div>
<b>Day 3 - Amberley to Queen Elizabeth Country Park</b></div>
<div>
<b><br /></b></div>
<div>
Vital statistics: 25.2 miles in 8 hours 3 minutes moving time (3.13 MPH, moving average), about 54,000 steps and 3287 feet of elevation gain.</div>
<div>
<b><br /></b></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhD1dt9Fj1gy9R7SN-WMPm6ln2gMayDSXcNxWRPb1I-jdcn4ocCnobJJMKnckZxzF3BHMMi_oDVtXFLd-z-ddTSpMgitKxtx5vb9Y4fh5ipy58Oe0JakU7Owngcu1_mhlCtY3ss-KHbwaQ/s1600/Strava+Day+3.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1200" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhD1dt9Fj1gy9R7SN-WMPm6ln2gMayDSXcNxWRPb1I-jdcn4ocCnobJJMKnckZxzF3BHMMi_oDVtXFLd-z-ddTSpMgitKxtx5vb9Y4fh5ipy58Oe0JakU7Owngcu1_mhlCtY3ss-KHbwaQ/s320/Strava+Day+3.jpeg" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div>
Day 3 was a huge mental struggle for me. We had lost Pete the day before, Andy was with us again and struggling through. But the main problem was having eaten fish and chips for dinner the night before and not slept a wink resulting from the indigestion that followed, I was both extremely tired and feeling rather nauseous as well. I kept going, putting faith in my physical ability (physically I felt fine), force fed myself as many calories as I could (I really didn't want to eat) and by around 2pm was starting to feel a little better.</div>
<div>
<br /></div>
<div>
There were a huge number of highlights on Day 3 that really helped:</div>
<div>
<br /></div>
<div>
<ul>
<li>We were joined in a fairly last minute addition to the plan by Stephen Warwick. It was lovely to have someone new in the team with fresh legs and a different dynamic. Stephen's used to lengthy exercise having walked some trails in the Himalayas and also ridden from Lands End to John O'Groats. He really helped me get my head in the right place to soldier on with some good team talks and deliberately poor maths. "We're half way" he said at 11 miles. "No we're not, go back and re-sit your GCSE" I replied knowing full well that we'd be the wrong side of 25 miles by the time we'd finished the day.</li>
<li>The weather was much, much better. We could see. It was warm, not hot. That was lovely.</li>
<li>We'd previously walked from Buriton to Didling during training, about the last third of Day 3. So there was a point when we reached the part of the trail we knew. That was a huge moment for all of us. We stopped there and celebrated with a banana each (we know how to live). Matt and I had now walked to the point where we knew we'd walked the entire length of the remaining trail into Winchester during training and most of that done in a day. We started to believe this might actually be possible.</li>
<li>Amy, Matt's sister, joined us at Harting Down and walked the last 8 miles or so with us. That was another huge boost to us - thank you, Amy!</li>
<li>Linda also joined us for the last 2 miles into Queen Elizabeth Country Park. Since she's suffering with Parkinson's, I thought that it was particularly poignant for her to join us. I'm really glad she did. </li>
<li>Donations were still coming in, we'd had a particularly good donation day on Day 2, and for those people who decided to wait until we started walking - many thanks - you helped keep us going and our spirits up.</li>
</ul>
</div>
<div>
The last few miles were really tough for Andy. Carrying his injury, he hobbled along to the finish, doubtful about whether he could complete Day 4. Testament to Andy though, he sat down in a disabled parking space in the car park, causing much hilarity. Other than in quite a lot of pain, I'm not sure exactly how he was feeling, but I imagine very proud of getting this far but also worried about the potential disappointment of not being able to finish the whole thing on Day 4.</div>
<div>
<b><br /></b></div>
<div>
<b><br /></b></div>
<div>
<b>Day 4 - Queen Elizabeth Country Park to Winchester</b></div>
<div>
<b><br /></b></div>
<div>
Vital statistics: 24.1 miles in 7 hours 12 minutes moving time (3.35 MPH, moving average), about 51,000 steps and 1972 feet of elevation gain.</div>
<div>
<b><br /></b></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghO4DPeQB3PoyXClI6VlgGJaoEG-qytt2QAcq4yLfkvTrqUhjP4zhB_djsIlj3CeHx_b5-LfxPWYBxGkuFFlHwcOeBwVS0COq46yLNzUcdQn369QWVvCpACxU9Gdy9-Qtb94h_mT1oFJA/s1600/Strava+Day+4.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1200" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghO4DPeQB3PoyXClI6VlgGJaoEG-qytt2QAcq4yLfkvTrqUhjP4zhB_djsIlj3CeHx_b5-LfxPWYBxGkuFFlHwcOeBwVS0COq46yLNzUcdQn369QWVvCpACxU9Gdy9-Qtb94h_mT1oFJA/s320/Strava+Day+4.jpeg" width="320" /></a></div>
<div>
<b><br /></b></div>
<div>
The start of day 4 was met with mixed feelings. We had all stayed at home the previous night, our first night home for the previous 3 nights. Seeing family and sleeping in your own bed was great. However, Andy was unable to recover from the previous day in time and we had a message saying that he wasn't going to be able to join us for the final day. That must have been a very hard decision to take but you'd never know it, having been delivered with the sense of humour and good grace Andy had shown throughout the walk. We'd miss him but we did have Phil joining me and Matt with his fresh legs for the final day.</div>
<div>
<br /></div>
<div>
Matt and I were buoyed by the fact we'd walked the entire length of this day during training and done so in a single day. That feeling of confidence and the fact we knew where we were going and exactly what lay ahead at each stage of the walk certainly helped. It made things a lot easier when we were getting tired during the day. It's probably due to a mixture of factors but we walked a little faster on day 4 too.</div>
<div>
<br /></div>
<div>
Andy parked in Winchester and walked backwards along our route to meet us and walk into town the last few miles. Still struggling, that must have been a hard walk for him too but it was great to cross the line with the main team of 3 of us and Phil who joined for the final day.</div>
<div>
<br /></div>
<div>
We arrived in Winchester a bit earlier than any of us might have expected. But with due warning, friends and family were dotted throughout the last couple of miles to meet and greet us. That felt amazing, picking up more people as we got closer to the end point. We were clearly going to make it, feeling extremely tired, but unstoppable at the same time.</div>
<div>
<br /></div>
<div>
We went for food and drink. Left the building to be driven, a long way home but a shorter distance than we'd walked each day, that felt weird.</div>
<div>
<br /></div>
<div>
We're done. This is now history. But please <a href="https://uk.virginmoneygiving.com/Team/DadsbeingLads">consider a donation</a>, if you haven't already.</div>
<div>
<b><br /></b></div>
<div>
<div>
<br /></div>
<div>
<b>Matt's Original Text</b></div>
<div>
<br /></div>
<div>
Taken from <a href="https://uk.virginmoneygiving.com/Team/DadsbeingLads">https://uk.virginmoneygiving.com/Team/DadsbeingLads</a></div>
<div>
<blockquote>
"<i>Thank you so much for visiting my page. My name is Matt and this year I will be turning the grand age of 40. I was inspired to take on a challenge to mark the occasion and hopefully do some good while I'm at it. </i></blockquote>
<blockquote>
<i>On 31st May I will be walking the South Downs Way. This is a walk that is 100 miles long and I will be attempting to cover it in 4 days. This means covering something close to a marathon each day. To help me do this I have put together a team of close friends. They will be joining me for either all (Graham & Andy) or part (Phil and Pete) of the walk. </i></blockquote>
<blockquote>
<i>Together we are raising money for The National Eczema Society and Parkinsons UK. Here's why... </i></blockquote>
<blockquote>
<i>I was diagnosed with atopic eczema aged just 3 months and I still struggle with the disease to this day. With the help of my parents, my family, close friends, some incredible doctors and some equally astounding nurses, my skin is in a far better condition that it ever was as a child. In July of 2017 my wife and I welcomed our second child into the world. Sadly he too has been suffering with eczema.</i> </blockquote>
<blockquote>
<i>The work that the National Eczema Society do is vitally important in the development of new treatments, drugs and support for sufferers of this condition. I am passionate to find something that not only helps my life but helps the generations to come (including my son). </i></blockquote>
<blockquote>
<i>In September 2017 my Mum was diagnosed with Parkinson's. Prior to the diagnosis as a family we had seen her deteriorating. She was walking much slower than normal, she dragged her feet, her right arm developed a tremor, her speech was much quieter and she wasn't herself. </i></blockquote>
<blockquote>
<i>My sister got married in early September and while helping to setup the day before Mum tripped on a kerb and broke her arm. Having recognised she wasn’t herself, Mum had been having various tests. A cardiologist she’d been sent to contacted the GP to say he thought Mum should be referred to a neurologist because he thought she had Parkinson’s disease. It is very likely that not picking her feet up (due to Parkinson's) caused her to trip and fall. </i></blockquote>
<blockquote>
<i>Since then she has been given a medication, seen a Parkinsons nurse and a physiotherapist. This has meant a significant improvement and she is now standing much taller (quite a significant given how 'tall' she is), she is speaking more freely, she is interacting with all her grandchildren with a vibrancy that was missing.</i> </blockquote>
<blockquote>
<i>The work that Parkinsons UK do is vital for people with this disease. They provide invaluable support and research that could not be possible without the support of donors.</i> </blockquote>
<blockquote>
<i>I would be so grateful if you would like to sponsor my team and I as we embark on this challenge and help raise some money for some fabulous charities. </i></blockquote>
<blockquote>
<i>Don’t forget to gift aid your donation so we can get even more from the Taxman.</i>"</blockquote>
<br />
Last, but very much not least, a great debt of thanks to everyone who has supported us. Those of you donating your hard-earned cash to our two fantastic causes, thank you. To our wives and families who we've abandoned to fulfil our own personal challenge, you're tired too from holding the fort while we've been gone, thank you. Finally, particular thanks to Linda and Tim for the logistical support, you were a part of the team as well and we wouldn't have completed the journey without you.<br />
<br /></div>
</div>
</div>
Graham Whitehttp://www.blogger.com/profile/03878311939940449093noreply@blogger.com1tag:blogger.com,1999:blog-2027699993235411172.post-82104460247785654552017-11-02T08:49:00.001+00:002017-11-02T08:49:50.681+00:00Kids Sponsored Walk with Dads<div style="font-family: Calibri, Helvetica, sans-serif, EmojiFont, "Apple Color Emoji", "Segoe UI Emoji", NotoColorEmoji, "Segoe UI Symbol", "Android Emoji", EmojiSymbols; font-size: 16px;">
On Saturday 11th November, my 3 year old is taking on a 3 mile sponsored walk. We're going from Bushy Leaze woods in the next village of Beech to the <a href="http://www.bushyleaze.co.uk/">Bushy Leaze</a> children's centre in Alton. Basically, a walk across the town in which we live. It doesn't sound far but it's a long way for little legs with some steep climbs over rough terrain too.</div>
<div style="font-family: Calibri, Helvetica, sans-serif, EmojiFont, "Apple Color Emoji", "Segoe UI Emoji", NotoColorEmoji, "Segoe UI Symbol", "Android Emoji", EmojiSymbols; font-size: 16px;">
<br /></div>
<div style="font-family: Calibri, Helvetica, sans-serif, EmojiFont, "Apple Color Emoji", "Segoe UI Emoji", NotoColorEmoji, "Segoe UI Symbol", "Android Emoji", EmojiSymbols; font-size: 16px;">
The idea is to raise funds for the centre and in particular to continue running the dad's group. The group used to get government funding through the sure start scheme but all this funding was cut last year along with a lot of other funding the centre was able to get. We're going to our bit to make sure the group can continue to run for future generations. One of our friends has helped set the centre up as a charity so they can continue as much of their outreach work and things like the breast feeding clinics can continue to run too.</div>
<div style="font-family: Calibri, Helvetica, sans-serif, EmojiFont, "Apple Color Emoji", "Segoe UI Emoji", NotoColorEmoji, "Segoe UI Symbol", "Android Emoji", EmojiSymbols; font-size: 16px;">
<br /></div>
<div style="font-family: Calibri, Helvetica, sans-serif, EmojiFont, "Apple Color Emoji", "Segoe UI Emoji", NotoColorEmoji, "Segoe UI Symbol", "Android Emoji", EmojiSymbols; font-size: 16px;">
You can read a little more and sponsor us at the following web page <a class="OWAAutoLink" href="https://mydonate.bt.com/events/walkwithdad/450291">https://mydonate.bt.com/events/walkwithdad/450291</a></div>
<div style="font-family: Calibri, Helvetica, sans-serif, EmojiFont, "Apple Color Emoji", "Segoe UI Emoji", NotoColorEmoji, "Segoe UI Symbol", "Android Emoji", EmojiSymbols; font-size: 16px;">
<br /></div>
<div style="font-family: Calibri, Helvetica, sans-serif, EmojiFont, "Apple Color Emoji", "Segoe UI Emoji", NotoColorEmoji, "Segoe UI Symbol", "Android Emoji", EmojiSymbols; font-size: 16px;">
Please feel free to share the story and donation link as you see fit.</div>
<div style="font-family: Calibri, Helvetica, sans-serif, EmojiFont, "Apple Color Emoji", "Segoe UI Emoji", NotoColorEmoji, "Segoe UI Symbol", "Android Emoji", EmojiSymbols; font-size: 16px;">
<br /></div>
<div style="font-family: Calibri, Helvetica, sans-serif, EmojiFont, "Apple Color Emoji", "Segoe UI Emoji", NotoColorEmoji, "Segoe UI Symbol", "Android Emoji", EmojiSymbols; font-size: 16px;">
Thanks!</div>
Graham Whitehttp://www.blogger.com/profile/03878311939940449093noreply@blogger.com0tag:blogger.com,1999:blog-2027699993235411172.post-20450571305696285622017-07-26T21:02:00.001+01:002017-07-26T21:03:59.740+01:00Moving to giffgaffMuch like moving bank account, it's not very often I move mobile network. I tend to favour staying with the same provider unless they provide me with a good reason to leave. My current network, <a href="https://talkmobile.co.uk/">TalkMobile</a>, have just done so by completely shutting down their PAYG service and so are only able to offer me a contract (that I don't want) or a rubbish deal to move to Vodafone (they're a Vodafone MVNO).<br />
<br />
I thought I'd write a similar post about my experience moving to the <a href="https://www.giffgaff.com/">giffgaff</a> network today to the one I wrote about <a href="http://gibbalog.blogspot.co.uk/2012/04/moving-to-talkmobile.html">Moving to TalkMobile</a> back in 2012. You'll see from that link that joining TalkMobile was extremely painful. However, I'm happy to report I found the network very solid and reliable with what I can only presume is good coverage (there's always black spots, right?) on the Vodafone network. Getting them to do anything was always painful as there's little option for self-service so it's more or less always a call to their support staff. The staff are very polite and extremely helpful but the processes and presumably the systems they have to use seem somewhat antiquated today.<br />
<br />
So in comparison to my previous blog post about moving to TalkMobile, moving to giffgaff went a bit like this:<br />
<br />
<b>Day 1 (yesterday)</b><br />
<br />
<ol>
<li>Register a giffgaff SIM a friend gave me and create a new giffgaff account all in one simple guided wizard on the giffgaff web site</li>
<li>Request a PAC from TalkMobile</li>
<li>Go through the number transfer process via another simple wizard on the giffgaff web site</li>
</ol>
<b>Day 2 (today)</b><br />
<br />
<ol>
<li>Observe a short outage in mobile service as my number was transferred just after lunch</li>
<li>Happy customer</li>
</ol>
<br />
So now I'm looking forward to years of good service from giffgaff until they provide me with a good reason to leave some time in the future.<br />
<br />
By the way, if you want to <a href="https://www.giffgaff.com/orders/affiliate/grahamwhiteuk">grab a giffgaff SIM</a> then feel free to register via my referral link as we'll both get a free £5 credit if you do.<br />
<br />Graham Whitehttp://www.blogger.com/profile/03878311939940449093noreply@blogger.com0tag:blogger.com,1999:blog-2027699993235411172.post-8672038954843793972017-04-23T19:42:00.001+01:002017-04-23T19:42:23.699+01:00New Thinkpad P50<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzF0xxwcB5eRthW5aGMte7_-0rBGcwIyd1YtWtw5BfMqTs8DNe3zrcyxCjF69fiYEIgHngvcZXECOZKrLskANzJEe8F8XXDg0UtZ4sANVM65ZrZfFzkvJ8oBcC5IBTG3uwkR45SvmKff4/s1600/thinkpad-P50.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="227" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzF0xxwcB5eRthW5aGMte7_-0rBGcwIyd1YtWtw5BfMqTs8DNe3zrcyxCjF69fiYEIgHngvcZXECOZKrLskANzJEe8F8XXDg0UtZ4sANVM65ZrZfFzkvJ8oBcC5IBTG3uwkR45SvmKff4/s320/thinkpad-P50.png" width="320" /></a></div>
It's been a while, but true to our 4 year hardware refresh cycle, I've just received my latest laptop - a Lenovo P50. I've been installing it with Fedora 25 since Friday and configuring and copying data over this weekend ready to swap laptops first thing this week. I'm looking forward to trying out the new machine although I'm not quite sure why as the specs are barely different from the machine I was given 4 years ago. It's certainly the best indication yet I've personally experienced of Moore's Law coming to a complete halt as well as many of the other specifications not improving a huge amount either. The two most noticeable differences are likely to be the more powerful graphics chip and the inclusion of an SSD. That said, there is twice as much RAM in this machine and I had upgraded my previous machine with an SSD as well so that particular upgrade isn't going to be noticeable for me at least.<br />
<br />
My previous machine was a <a href="http://gibbalog.blogspot.co.uk/2013/03/new-thinkpad-w530.html">W530</a> and the one I had before that was a <a href="http://gibbalog.blogspot.co.uk/2008/06/new-thinkpad-t61p.html">T61p</a> (with a T41p before that) and so I'm well used to this particular line of Thinkpad laptops.<br />
<br />
Here's the specifications of the machine I've got, as ever there are variants of the P50 so if you have one or are thinking of getting one the specifications could be a little different but will be broadly similar to this:<br />
<br />
<ul>
<li>Intel(R) Core(TM) i7-6820HQ CPU @ 2.70GHz (5433.79 bogomips in Linux)</li>
<li style="border: none; margin: 0px 0px 0.25em; padding: 0px;">32GB DDR4 2133MHz</li>
<li style="border: none; margin: 0px 0px 0.25em; padding: 0px;">Samsung MZNLN512 (PM871) 512GB SSD</li>
<li style="box-sizing: border-box;">15.6" 1920 x 1080 IPS (non-touch)</li>
<li style="box-sizing: border-box;">6 Cell Battery</li>
<li style="box-sizing: border-box;">Wireless A/C</li>
<li style="box-sizing: border-box;">NVIDIA Quadro M1000M 4 GB</li>
<li style="border: none; margin: 0px 0px 0.25em; padding: 0px;">Front Facing Web Cam, Mini Display Port, HDMI Out, Headphone, 4x USB3, Smart Card Reader, GBit Ethernet, Thunderbold, Fingerprint Reader</li>
</ul>
So looking at those and comparing in more detail to what I had before it seems my gut feeling was pretty good. The CPU benchmarks are more-or-less exactly the same and certainly within tolerances of error as well as other performance increases that will effect the benchmarks such as the memory clock speed. Here's the comparison between the W530 CPU and the P50 CPU:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj5Au5oIOsYJK3hDhbj4j8Dy5HKbCpFJzFrLjlFZs9Akrdj_aK7aSPzcxRStZwt3qa96kVWWsSsuilu20hyphenhyphenEEzUUOrsAaSdjVvMASV2pzZN1W59TCHyXYPFe_Ozo6dPWf1HdeuAoiMFeFE/s1600/Screenshot+at+2017-04-21+20-32-02.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="92" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj5Au5oIOsYJK3hDhbj4j8Dy5HKbCpFJzFrLjlFZs9Akrdj_aK7aSPzcxRStZwt3qa96kVWWsSsuilu20hyphenhyphenEEzUUOrsAaSdjVvMASV2pzZN1W59TCHyXYPFe_Ozo6dPWf1HdeuAoiMFeFE/s320/Screenshot+at+2017-04-21+20-32-02.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<br />
The same can't be said of the GPU benchmarks though so it looks like GPUs are continuing to gain in power even when CPU speed increases have run out of steam:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEho3Sl7IQWf3qG7BDFwkV0x-ero5LAVvCTo9E3_cDcWDTT3cvtJm_eRf-fvij0GdFO9UVtA7WwegotdvPPYHY3yDhUPQPTO6rs03D7F5PJh4zi_0U8syukiV5sMiVSRgsStRzqTBmB36sw/s1600/Screenshot+at+2017-04-21+20-33-42.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="92" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEho3Sl7IQWf3qG7BDFwkV0x-ero5LAVvCTo9E3_cDcWDTT3cvtJm_eRf-fvij0GdFO9UVtA7WwegotdvPPYHY3yDhUPQPTO6rs03D7F5PJh4zi_0U8syukiV5sMiVSRgsStRzqTBmB36sw/s320/Screenshot+at+2017-04-21+20-33-42.png" width="320" /></a></div>
<div>
<br /></div>
<div>
The other noticeable difference I hadn't spotted before is the battery size. That's very apparent when you pick the machine up as it's actually a little bit thinner (probably also due to the lack of DVD/combo drive) as well as not as deep i.e. it doesn't have the big battery sticking out of the back that has been common place on this line of Thinkpad machines over the past decade or so. I'm guessing (without having done any research on the matter) that this is probably due to improvements in battery technology so I'd think Lenovo have probably moved over to Li-ion or Li-po batteries.</div>
<div>
<br /></div>
<div>
In terms of running and using the machine, it does seem very nice so far as one might expect. It's running Fedora 25 very nicely and hasn't caused me any issues at all during setup. I'm not really expecting any either as most if not all of the hardware seems pretty well support by Linux these days. I think, in fact, Lenovo even offer to supply this machine pre-installed with Linux if you want. That said, there looks to be one possible sticking point in terms of hardware support at the moment but this is very minor. That is, the build-in fingerprint reader doesn't seem to have a driver available on Linux yet. I did some very brief research into this yesterday and it's not clear why vendor support is lacking for the device at the moment although I did find at least one effort that has gone a fairly long way towards reverse engineering it and starting to write a driver so I would guess within the next year we'll see some sort of support for the fingerprint reader too.</div>
<div>
<br /></div>
<div>
All in all then it's a good machine even though it's not a huge upgrade over my 4 year old laptop!</div>
Graham Whitehttp://www.blogger.com/profile/03878311939940449093noreply@blogger.com0tag:blogger.com,1999:blog-2027699993235411172.post-87084411417039720662016-12-23T11:29:00.000+00:002016-12-23T11:29:27.377+00:00Becomming a Fedora Package Maintainer<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1pAxz2w4-FqbI78_65iHC9SP1DYgGiUlNSg-RqYJtFrZDf-FQGl45Eh8RJhBj5QmJa66JxZvh54mf3wVmQHCaIuDRaMEVnZziZqX0fviJoVR-ljp5FRurPu2I6LdJiBgKHlfZz9Vdhas/s1600/fedora.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1pAxz2w4-FqbI78_65iHC9SP1DYgGiUlNSg-RqYJtFrZDf-FQGl45Eh8RJhBj5QmJa66JxZvh54mf3wVmQHCaIuDRaMEVnZziZqX0fviJoVR-ljp5FRurPu2I6LdJiBgKHlfZz9Vdhas/s1600/fedora.png" /></a></div>
Those of you that know me well will know I like Linux. Don't get me wrong, there's a lot wrong with it and the community can be a pretty harsh place where more or less everyone has an opinion they think is the right one. I don't get a lot of chance to contribute for various reasons but earlier this year I was (finally) accepted to be a package maintainer for the Fedora project.<br />
<br />
Since I like Linux I do tend to use it on the desktop both at home and at work. I do more or less everything with Linux and Open Source software including photo editing with <a href="https://www.gimp.org/">GIMP</a>. It bugged me that Fedora ship a library called <a href="http://lensfun.sourceforge.net/">lensfun</a> which is a library of lens correction data but the only piece of software using it within Fedora was <a href="https://www.digikam.org/">Digikam</a>. Preferring GIMP I decided to set about packaging and supporting <a href="https://seebk.github.io/GIMP-Lensfun/">gimp-lensfun</a> for Fedora.<br />
<br />
Becoming a Fedora Package Maintainer is a well documented process as there are <a href="https://fedoraproject.org/wiki/Join_the_package_collection_maintainers">joining instructions</a> and <a href="https://fedoraproject.org/wiki/Package_Review_Process">package review guidelines</a> for the <a href="https://fedoraproject.org/wiki/Packaging:Guidelines">packaging guidelines</a>. Whilst well documented, there's a heck of a lot of stuff you have to read through and comply with before you can submit your first package review request. This is further complicated by not yet having any reputation within the Fedora community and so you have to build this up in other ways before your package will be recognised and one of the senior community members agrees to sponsor you as a package maintainer.<br />
<br />
I eventually raised <a href="https://bugzilla.redhat.com/show_bug.cgi?id=951496">my first package review request</a> for gimp-lensfun in April 2013. Over a period of a few weeks people throw rocks at what you've done according to the various guidelines that you either didn't see or forgot about. This is actually really good and helpful as it ensures quality and consistency between all the new packages being accepted into Fedora.<br />
<br />
What I wasn't prepared for was the length of the wait. I know this isn't an earth shattering change to Fedora but it took me over 2 years to get noticed enough for my package to be accepted and for me to be sponsored as a Fedora packager. I think I'd probably still be waiting now but I bugged a few people on IRC to point out my review request had been sitting there for so long.<br />
<br />
Finally! My first package was released into the wild for Fedora 21 and 22 and I've been given the chance to give just a little back to the community.Graham Whitehttp://www.blogger.com/profile/03878311939940449093noreply@blogger.com0tag:blogger.com,1999:blog-2027699993235411172.post-12664799162217221392015-11-19T12:26:00.000+00:002015-11-19T12:26:07.167+00:00Compiling the 8192eu driver for the Raspberry PiI recently had the need to Wi-Fi enable a Raspberry Pi and so bought a D-Link DWA-131 Wireless USB Adapter. I knew from <a href="http://elinux.org/RPi_USB_Wi-Fi_Adapters">something I'd read</a> that it was a bit of a gamble in terms of whether it would be supported by the Pi under Raspian. It turns out there are currently <a href="http://www.linux-hardware-guide.com/2013-11-16-d-link-dwa-131-n300-usb-wifi-adapter">3 revs of this adapter</a> with different chipsets in each. The one I got was the latest E1 version identified with the USB Device ID 2001:3319 that requires the realtek 8192eu driver.<br />
<br />
Here's how to get it working under the September 2015 Raspian Jessie running Kernel 4.1.7+ for which I found <a href="https://discourse.osmc.tv/t/tutorial-compiling-a-working-kernel-driver-for-rtl8192eu/5252">some similar instructions</a> a helpful starter:<br />
<br />
1. Get up to date and ready for compilation<br />
<span style="font-family: "Courier New",Courier,monospace;"><br /></span>
<span style="font-family: "Courier New",Courier,monospace;">sudo apt-get update</span><br />
<span style="font-family: "Courier New",Courier,monospace;">sudo apt-get upgrade</span><br />
<span style="font-family: "Courier New",Courier,monospace;">sudo apt-get install build-essential git</span><br />
<br />
<br />
2. Grab the Driver Source<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">git clone <a href="https://github.com/romcyncynatus/rtl8192eu.git" rel="nofollow">https://github.com/romcyncynatus/rtl8192eu.git</a></span><br />
<br />
or from<br />
<br />
<a href="http://support.dlink.com.au/download/download.aspx?product=DWA-131">http://support.dlink.com.au/download/download.aspx?product=DWA-131</a><br />
<br />
<br />
3. Patch the driver source for Kernel 4.x<br />
<br />
cd rtl8192eu<br />
Apply the following patch to rtw_android.c <br />
<br />
<span style="font-size: xx-small;"><span style="font-family: "Courier New",Courier,monospace;">diff --git a/os_dep/linux/rtw_android.c b/os_dep/linux/rtw_android.c<br />index 40ddf07..f7c496e 100755<br />--- a/os_dep/linux/rtw_android.c<br />+++ b/os_dep/linux/rtw_android.c<br />@@ -342,7 +342,11 @@ int rtw_android_cmdstr_to_num(char *cmdstr)<br /> {<br /> int cmd_num;<br /> for(cmd_num=0 ; cmd_num<ANDROID_WIFI_CMD_MAX; cmd_num++)<br />+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,0,0))<br />+ if(0 == strncasecmp(cmdstr , android_wifi_cmd_str[cmd_num], strlen(android_wifi_cmd_str[cmd_num])) )<br />+#else<br /> if(0 == strnicmp(cmdstr , android_wifi_cmd_str[cmd_num], strlen(android_wifi_cmd_str[cmd_num])) )<br />+#endif<br /> break;<br /><br /> return cmd_num;</span></span><br />
<br />
<br />
4. Grab the rpi-source tool (to download the Pi kernel source)<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">wget https://raw.githubusercontent.com/notro/rpi-source/master/rpi-source </span><br />
<span style="font-family: "Courier New",Courier,monospace;">chmod +x rpi-source</span><span style="font-family: "Courier New",Courier,monospace;"> </span><br />
<span style="font-family: "Courier New",Courier,monospace;">sudo mv rpi-source /usr/bin/</span><br />
<span style="font-family: "Courier New",Courier,monospace;">sudo rpi-source -q --tag-update</span><br />
<br />
<br />
5. Install the Pi kernel <br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">sudo rpi-source --skip-gcc</span><br />
<br />
<br />
6. Build and install the driver<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">make ARCH=arm</span><br />
<span style="font-family: "Courier New",Courier,monospace;">sudo make ARCH=arm install</span><br />
<span style="font-family: "Courier New",Courier,monospace;">sudo bash -c 'echo "options 8192eu rtw_power_mgnt=0 rtw_enusbss=0" > /etc/modprobe.d/8192eu.conf'</span><br />
<span style="font-family: "Courier New",Courier,monospace;">modprobe 8192eu</span><br />
<br />
<strong><a href="https://github.com/romcyncynatus/rtl8192eu.git" rel="nofollow"><span class="badge badge-notification clicks" title="100 clicks"></span></a></strong>Graham Whitehttp://www.blogger.com/profile/03878311939940449093noreply@blogger.com8tag:blogger.com,1999:blog-2027699993235411172.post-70668662778834920212014-11-14T08:29:00.000+00:002014-11-14T08:29:25.962+00:00Tackling Cancer with Machine LearningFor a recent Hack Day at work I spent some time working with one of my colleagues, Adrian Lee, on a little side project to see if we could detect cancer cells in a biopsy image. We've only spent a couple of days on this so far but already the results are looking very promising with each of us working on a distinctly different part of the overall idea.<br />
<br />
We held an open day in our department at work last month and I gave a lightening talk on the subject which you can see <a href="https://www.youtube.com/watch?v=n4pCty6LbuA">on YouTube</a>:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/n4pCty6LbuA?feature=player_embedded' frameborder='0'></iframe></div>
<br />
There were a whole load of other talks given on the day that can be seen in the <a href="https://www-304.ibm.com/connections/blogs/et/entry/emerging_technology_centre_innovation_day">summary blog post</a> over on the <a href="http://ibm.com/blogs/et">ETS (Emerging Technology Services) site</a>.<br />
<br />
<br />
<br />Graham Whitehttp://www.blogger.com/profile/03878311939940449093noreply@blogger.com0tag:blogger.com,1999:blog-2027699993235411172.post-76257999908388749162014-01-22T06:30:00.001+00:002020-08-14T07:38:20.304+01:00Snooker Cue Maintenance<div class="separator" style="clear: both; text-align: center;">
<a href="http://www.peradon.co.uk/peradon-cues-extensions/34-jointed-snooker-cues/ascot-(1223).aspx" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="128" src="http://www.peradon.co.uk/media/128282/1223-on%20angle_butt_thumb_431.jpg" width="200" /></a></div>
A slight departure from my usual sort of posts but these are "my notes" so what the heck.<br />
<br />
Last Christmas I treated myself (or strictly speaking was treated to) a new snooker cue. I've always dabbled with snooker, not particularly good, but I can do enough to get by. My old cue (18th birthday present) was getting a bit tired. I decided to go with a really nice English make, <a href="http://www.peradon.co.uk/">Peradon</a>, from Liverpool. They are reasonably priced but the real treat is the quality of the craftsmanship and since I'm quite keen on making things from wood I really appreciate that side of the cue as much as anything else - it's clearly one that's far above the level to which I actually play the game. I eventually settled on the <a href="https://web.archive.org/web/20151016161244/http://www.peradon.co.uk/peradon-cues-extensions/34-jointed-snooker-cues/ascot-(1223).aspx">Ascot ¾ cue</a>.<br />
<br />
With such a nice piece of wood I was surprised to see a complete lack of advice on how to care for and maintain it. I wrote to Peradon for some help and what follows is their advice, and hence the reason for keeping it on my blog so I'll stand a chance of finding it again in the future...<br />
<br />
The method is quite simple:<br />
<br />
<ol>
<li>Rub down with a very fine steel wool (I use Liberon 0000) and wipe away any residue</li>
<li>Apply raw linseed oil (I use Liberon Raw Linseed Oil) with a lint free cloth and leave for 20-30 minutes</li>
<li>Buff the cue with a lint free cloth</li>
<li>Repeat if necessary (you can also heat or dilute the linseed oil for multiple coats)</li>
</ol>
It seems to work very well. Peradon recommended I do this every couple of weeks which seems to be to be rather on the excessive side so I'll probably opt for "every now and then" and since this is the first time I've done it, it looks to be an annual event although I may do it more often now I've got all the gear.Graham Whitehttp://www.blogger.com/profile/03878311939940449093noreply@blogger.com0tag:blogger.com,1999:blog-2027699993235411172.post-72181141512204925122013-08-20T22:13:00.000+01:002013-08-20T22:15:06.495+01:00Nexus 4 Red Light of Death<div class="separator" style="clear: both; text-align: center;">
<a href="http://www.google.com/nexus/images/n4-product-hero.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="200" src="http://www.google.com/nexus/images/n4-product-hero.png" width="136" /></a></div>
I've written a few times in the past about various poor or laughable customer experiences I've had when dealing with technology and the companies making or retailing them. Things usually work out well in the end of course as we're well protected as consumers here in the UK. However, when my <a href="http://www.google.co.uk/nexus/4/">Nexus 4</a> went wrong late on Saturday night I thought I was in for another world of pain, I couldn't have been more wrong.<br />
<br />
The short version of this post is that my phone died late on Saturday night. On Sunday morning I raised a support call. By Tuesday morning I had a brand new phone in my hand, delivered to my door, all under warranty. I need not have worried it seems, Google appear to have customer support really very well sorted out. I only wish the vast array of companies out there who are terrible to deal with would learn the lessons of having satisfied customers even when things go wrong.<br />
<br />
The slightly longer version of the story is that my phone completely ran out of charge on Saturday and when I went to plug it in for an over night full charge before going to bed, I noticed the LED was solid red. I've never seen this before but left it for a few hours and tried turning it on, nothing. I left it on over night and it still wouldn't turn on the next morning. I tried a few other things, like a separate wall outlet and another charger and cable but still all I got was a solid red light and no ability to boot the phone.<br />
<br />
I phoned Google at 10am on a Sunday in the hope that they ran a call center on Sundays or that I would be connected to an international person who would be able to help. I think that's probably what happened as it was an all-American experience from start to finish. Benjamin answered the phone, asked me some questions and got me to do a couple of things with the phone, it was still dead. He was first class, easy to understand and took ownership of the issue straight away, I can still email him directly about the problem now.<br />
<br />
After Google support (Ben) realised the phone was dead, there was no quibble, no problem, no hoops to jump through. He told me that he'd send the issue through to the warranty department, they would send me an email with how to order a new phone and when I receive it I should send back the old one in the same packaging (standard practice for the tech industry). We parted company, and I'm thinking this is all a bit too easy and something will go wrong later.<br />
<br />
A couple of hours later, I get an email from Google warranty. It has a link to click which allows you to order a new phone at no cost (the link is only live for 24 hours). I set about ordering the phone, it was Sunday night by this time.<br />
<br />
8:30am Tuesday morning and Parcel Force knock at the door and deliver my new phone. Inside the package is a return envelope, exactly as described by Ben at Google and exactly what the warranty email said would happen. I printed the RMA note attached to the email, packaged everything up and it's ready to go back to Google - we're still less than 5 days from the start of the issue at this point.<br />
<br />
Quite simply, brilliant. I thought I should say so (<a href="https://twitter.com/graham_alton/status/369724167090110464">or more so</a>).<br />
<br />
So would I buy a new Google hardware product again? You bet I would. Software updates come regularly, I'm always at the latest Android level (unlike the Transformer Prime tablet we have in the house which is stuck on 4.1 because Asus dropped support after little more than a year), I don't suffer from the Apple single vendor lock-in issue, and now to top it all off it seems the warranty support is first class.Graham Whitehttp://www.blogger.com/profile/03878311939940449093noreply@blogger.com4tag:blogger.com,1999:blog-2027699993235411172.post-84016990174847212642013-08-17T22:03:00.001+01:002013-08-20T22:15:55.626+01:00Android Clients for Twitter<div class="separator" style="clear: both; text-align: center;">
<a href="http://livewithasmile.com/wp-content/uploads/2013/05/TweetDeck-Old-Logo.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="200" src="http://livewithasmile.com/wp-content/uploads/2013/05/TweetDeck-Old-Logo.png" width="200" /></a></div>
I've been a long time fan of <a href="http://www.tweetdeck.com/">Tweetdeck</a> as a piece of software for social management, certainly long before it was bought by Twitter. I've used it everywhere via the Air Desktop app, on the web, the Chrome app and on Android too. That is, up until now. In their infinite wisdom Twitter appear to have realised maintaining two clients across a wide range of platforms doesn't make sense (begs the question why the bought it in the first place but I wont have that argument here) any longer and most versions of Tweetdeck are being phased out leaving only the web version or the heavily-based-on-the-web-version Chrome app. So for the fans, what's next? Which Twitter client should I be using on my mobile device now? I've been assessing a bunch of them for quite a while now and I know I'm not the only one facing this decision so here's what I've learned.<br />
<br />
First of all to put into perspective my thoughts on each client, here's a list of things I want or that I'm concerned with in an Android client:<br />
<br />
<ol>
<li>I should very easily be able to get to different content streams from my main Twitter stream, my mentions, searches, lists, to my direct messages. A column interface (similar to Tweetdeck I guess) is ideal for this with a swipe gesture to navigate between them.</li>
<li>It should support multiple Twitter accounts and switch easily between each account.</li>
<li>It should be slick, fast, nice to use and be configurable in terms of its look and feel, notifications and ideally offer per column filters.</li>
<li>It should ideally support push notifications and Twitter streaming. When notifications are pressed in the notifications bar the client should open directly to the Tweet being notified.</li>
<li>It should not contain adverts. It doesn't matter if I have to pay for the app or pay to get rid of the adverts, paying (within reason) is fine.</li>
<li>It would preferably be free (as in open source) but I appreciate many of them are not and indeed to get the best Android clients at the moment it's less likely to be so.</li>
</ol>
<br />
So onward, to the apps...<br />
<br />
<b>Twitter (official client)</b><br />
I guess the main critique of a post such as this is to ask what's wrong with the official client. Well for me I find it takes ages to get to the content I read regularly. Twitter lists take 3 taps and a scroll-down to find (for each list) so the official client fails at point 1 in my requirements list. It doesn't do particularly well at points 2 or 3 either. However, it does have the beefed-up mentions column they're calling Interactions that also includes favourites and new followers which I really like so I'm likely to keep it installed just for this until some other clients catch up.<br />
<br />
<b>Scope</b><br />
Requires a special Scope account in order to login. Screenshots appear to indicate a lack of column support so I didn't even bother signing in and got rid of it straight away.<br />
<br />
<b>Slices</b><br />
An interesting take on reading Twitter and may once have provided lots of useful extra functionality on top of the basic Twitter. However, with the introduction of Twitter lists there seems less point to Slices ability to carve up your social content into chunks. The UI I found to be really rather confusing and difficult to navigate. I quickly got rid of it after some investigation into its features.<br />
<br />
<b>Carbon</b><br />
One of the slickest and nicest looking Twitter clients I think there is, this one really excels at want list number 3 with its fancy animations and cool look. However, in the end it's still a button based UI that takes far too many taps to get to each piece of content you want to read. That makes it slow and confusing to navigate so it's a sad farewell when uninstalling this one as it does implement swipe between columns but you can't configure your own columns to swipe through.<br />
<br />
<b>Tweet Lanes</b><br />
This one does everything I want more or less out of the box with zero setup. All I did for this app was sign in and a carousel swipe interface is loaded with all my tweets, mentions, lists, etc. and more can easily be added. This app also appeals due to its free and open source mentality so is good for want list number 6. However, it was left by the original developer (who no longer maintains it) somewhat feature incomplete with no notifications or sync although it does handle multiple accounts rather nicely. Other developers have hacked in a few of these missing features here and there but there's still no driving force behind the project any more. I wouldn't be expecting regular updates so the amount of life left in this app without someone taking up the reigns is probably quite short. If it wasn't for the fact it's in a state of limbo I could seriously like this one but in the end lack of attention to detail such as pressing a notification in the notification bar and it merely starting the app rather than dropping you to the right place are just annoying.<br />
<br />
<b>Seesmic</b><br />
A really popular client at one point, even if it's not now. However, I really didn't get Seesmic at all. It's a button based UI similar to the official Twitter client that takes lots of taps to get anywhere. Lets count how I read a Twitter list: Profile Button -> Lists -> List Name, that's 3 which is too many in my book. So it fails in the same way the official client fails at point 1 in my want list and doesn't do well at points 2 or 3 either. It also has ads that I could pay to get rid of but why pay when it doesn't work very well for me anyway?<br />
<br />
<b>UberSocial</b><br />
Not a bad column-based client that allows you to easily add the columns you want and arrange them in the order that suits. It's easy to switch between accounts too. The big problem with this client is that it's a battery-eater, I've no idea what it's doing but presumably polling quite a lot as when installed and in use on my phone it was one of the top reported apps in terms of battery usage where none of the other clients are anywhere to be seen. If you want decent battery life then don't bother with this one.<br />
<br />
<b>TweetCaster</b><br />
A not particularly easy on the eye button based app which, like other similar apps that limit the columns you're allowed and don't swipe between them, makes it rather awkward to traverse all the various parts of Twitter that a modern user might expect. I really don't see the advantage of TweetCaster over the standard Twitter app.<br />
<br />
<b><span style="font-size: large;">The Winners Are</span></b><br />
These three are all very good indeed and for me and my list, worth a shot. I've not yet completely made my mind up which way I'll be going but it will definitely be one of these.<br />
<br />
<b>Janetter</b><br />
With the default theme, this client can be a bit "oh my eyes" with its jet black text on bright white background. Not much imagination in the colouring and shading of the interface except the bright lime green. However, when switched to the dark theme it's much easier on the eye and you can start to look at the functionality a little more closely. It manages multiple accounts very well, returning you to the same account you left when you start the app but making it easy to move between the two accounts - perfect for when you have a major account and other minor accounts you don't read that much. The interface itself is the typical column/swipe style interface and the columns are easily configured, edited and arranged. It also has another feature that is becoming more important in the management of busy columns, the idea of muting certain keywords, hashtags, user accounts or apps. The free version has adverts built in but if this is the app I end up going for then it's a one-time £4.99 purchase to get rid of the ads and unlock a couple of other features.<br />
<br />
<b>HootSuite</b><br />
Really easy to use from the off and has a nice separation of accounts that allow you to read content from any particular account with ease. Accounts are separated so you can only scroll through the columns for a particular account that's active. However, switching between accounts feels a little awkward to me as you have to remember how to navigate back to the main start page which isn't done using the most obvious (and normal for Android) method of clicking the button in the title bar. Other than that, once you've got an account selected it's really quite nice to browse through all the different content and with no ads either, for free. If you want more than a certain number of accounts (I'm not sure how many) or you want to unlock some particular features (that I've not found the need for) then you need to pay a fairly staggering $9.99 per month to use the pro version of the app. That sum plus the features you get in the paid version clearly indicate HootSuite is aiming to make money from commercial users of Twitter where lots of different people might be maintaining lots of different accounts, a marketing department perhaps. Because of that the free version is really good, as I've said, but I do wonder if one of the other two of my favourite apps will win out with a slicker user experience overall.<br />
<br />
<b>Plume</b><br />
<div>
I'm really liking Plume at the moment, along with Janetter it's quite slick at the way it handles navigation and moving between accounts. However, it does have a couple of annoying "features" that can't be changed. The worst is that every time the app is started it shows a feed of information from all of your accounts configured in the app. Unlike most apps, Plume doesn't separate content from different accounts, they're all shown in the same columns and colour coded to match a particular account. That's great except that most of the time I want to read content from my main Twitter account and only occasionally do I want to dip into content from other accounts. Hence, at the moment every time I start the app I have to tap a couple of buttons to select my main account - how hard can that be to add as an option? Many users have asked for it and as yet it's not been added. The free version is supported by ads so you you need to shell out the small sum of £3.73 to get rid of them. Another similar feature to Janetter is that you can mute certain things from column content, either accounts, hashtags, keywords or apps. This highlights another annoying Plume buglet in that not everything you ask to be muted actually gets muted, or at least it seems mutes only apply to the main column and not to specific columns or all columns as you might expect. This is a really excellent Twitter client and if you can work around the few annoyances I've highlighted then it's a real winner. For me, time will tell whether they sort it out enough for me to be able to live with it on a daily basis.</div>
Graham Whitehttp://www.blogger.com/profile/03878311939940449093noreply@blogger.com2tag:blogger.com,1999:blog-2027699993235411172.post-29017232211021042562013-06-25T21:21:00.005+01:002013-06-25T21:21:48.570+01:00Machine Learning Course<div class="separator" style="clear: both; text-align: center;">
<a href="https://s3.amazonaws.com/coursera/topics/ml/small-icon.hover.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://s3.amazonaws.com/coursera/topics/ml/small-icon.hover.png" /></a></div>
Enough time has passed since I undertook the Stanford University <a href="http://gibbalog.blogspot.co.uk/2012/05/natural-language-processing-course.html">Natural Language Processing Course</a> for me to forget just how much hard work it was for me to start all over again. This year I decided to have a go at the <a href="https://www.coursera.org/">coursera</a> Machine Learning Course.<br />
<br />
Unlike the 12 week NLP course last year which estimated 10 hours a week and turned out to be more like 15-20 hours a week, this course was much more realistic in estimation at 10 weeks of 8 hours. I think I more or less hit the mark on that point spending about 1 day every week for the past 10 weeks studying machine learning - so around half the time required for the NLP course.<br />
<br />
The course was written and presented by <a href="http://ai.stanford.edu/~ang/">Andrew Ng</a> who seems to be rather prolific and somewhat of an academic star in his fields of machine learning and artificial intelligence. He is one of the co-founders of the coursera site which along with their main rival, <a href="https://www.udacity.com/">Udacity</a>, have brought about the popular rise of <a href="http://en.wikipedia.org/wiki/Massive_open_online_course">Massive Open Online Learning</a>.<br />
<br />
The Machine Learning Course followed the same format as the NLP course from last year which I can only assume is the standard coursera format, at least for technical courses anyway. Each week there were 1 or two main topic areas to study which were presented in a series of videos featuring Andrew talking through a set of slides on which he's able to hand write notes for demonstration purposes, just as if you're sitting in a real lecture hall at university. To check your understanding of the content of the videos there are questions which must be answered on each topic against which you're graded. The second main component each week is a programming exercise which for the Machine Learning Course must be completed in Octave - so yet another programming language to add to your list. Achieving a mark of 80% or above across all the questions and programming exercises results in a course pass. I appear to have done that with relative ease for this course.<br />
<br />
The 18 topics covered were:<br />
<br />
<ul>
<li>Introduction</li>
<li>Linear Regression with One Variable</li>
<li>Linear Algebra Review</li>
<li>Linear Regression with Multiple Variables</li>
<li>Octave Tutorial</li>
<li>Logistic Regression</li>
<li>Regularisation</li>
<li>Neural Networks Representation</li>
<li>Neural Networks Learning</li>
<li>Advice for Applying Machine Learning</li>
<li>Machine Learning System Design</li>
<li>Support Vector Machines</li>
<li>Clustering</li>
<li>Dimensionality Reduction</li>
<li>Anomaly Detection</li>
<li>Recommender Systems</li>
<li>Large Scale Machine Learning</li>
<li>Application Example Photo OCR</li>
</ul>
The course served as a good revision of some maths I haven't used in quite some time, lots of Linear Algebra for which you need a pretty good understanding and lots of calculus which you didn't really need to understand if all you care about is implementing the algorithms rather than working out how they're derived or proven. Being quite maths based, the course used matrices and vectorisation very heavily rather than using the loop structures that most of us would use as a go-to framework for writing complex algorithms. Again, this was some good revision as I've not programmed in this fashion for quite some time. You're definitely reminded of just how efficient you can make complex tasks on modern processors if you stand back from your algorithm for a bit and work out how best to utilise the hardware (via the appropriately optimised libraries) you have.<br />
<br />
The major thought behind the course seems to be to teach as many different algorithms as possible. There really is a great range. Starting of simply with linear algorithms and progressing right up to the current state-of-the-art Neural Networks and the ever fashionable map-reduce stuff.<br />
<br />
I didn't find the course terribly difficult, I'm no expert in any of the topics but have studied enough maths not to struggle with that side of things and don't struggle with programming either. I didn't need to use the forums or any of the other social elements offered during the course so I don't really have a feel for how others found the course. I can certainly imagine someone finding it a real struggle if they don't have a particularly deep background in either maths or programming.<br />
<br />
There was, as far as I can think right now, one (or maybe two depending on how you count) omission from the course. Most of the programming exercises were heavily frameworked for you in advance, you just have to fill in the gaps. This is great for learning the various different algorithms presented during the course but does leave a couple of areas at the end of the course you're not so confident with (aside from not really having a wide grasp of the Octave programming language). The omission of which I speak is that of storing and bootstrapping the models you've trained with the algorithm. All the exercises concentrated on training a model, storing it in memory, using it and as the program terminates then so your model disappears. It would have been great to have another module on the best ways to persist models between program runs, and how to continue training (bootstrap) a model that you have already persisted. I'll feed that thought back to Andrew when the opportunity arises over the next couple of weeks.<br />
<br />
The problem going forward wont so much be applying what has been offered here but working out what to apply it to. The range of problems that can be tackled with these techniques is mind-blowing, just look at the rise of analytics we're seeing in all areas of business and technology.<br />
<br />
Overall then, a really nice introduction into the world of machine learning. Recommended!<br />
<br />
<br />Graham Whitehttp://www.blogger.com/profile/03878311939940449093noreply@blogger.com0tag:blogger.com,1999:blog-2027699993235411172.post-33838026456159893402013-06-02T22:00:00.000+01:002013-06-02T22:38:25.523+01:00Making a Cajón<div class="separator" style="clear: both; text-align: left;">
When I asked my best mate what he wanted for his birthday this year he came back with something rather unexpected, he said "I'd really like a Cajón!". Having never heard of one before he continued to explain what it was and I <a href="http://en.wikipedia.org/wiki/Caj%C3%B3n">looked it up</a> a bit later too. It turned out that for the sort of thing he wanted, something with an electrical pick-up (to make it semi-acoustic) with an adjustable snare too, it was a bit out of budget. After a bit of research around various different makes and models I wondered how hard it could really be (it's just a wooden box after all) and offered to make one. Matt quickly warmed to the idea and so with his knowledge of what he wanted in the way of design and my woodworking experience we set about a joint project that we've just finished this weekend.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
To save the long blog post about exactly what we did, I'll simply refer you to a video (below). This is more or less exactly what we made, following <a href="http://www.woodworkingformeremortals.com/">Steve Ramsey's</a> design almost to the letter. There were a few things we had to make up that the video didn't explain very well and a couple of design adjustments (where we found the video to be incorrect - we weren't the only one's to notice <a href="http://www.woodworkingformeremortals.com/2011/08/make-your-own-cajon.html?showComment=1313855326306#c6672196717171016847">the problem</a>).</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<object class="BLOGGER-youtube-video" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" data-thumbnail-src="http://img.youtube.com/vi/EVZN_mdz7Ks/0.jpg" height="266" width="320"><param name="movie" value="http://youtube.googleapis.com/v/EVZN_mdz7Ks&source=uds" /><param name="bgcolor" value="#FFFFFF" /><param name="allowFullScreen" value="true" /><embed width="320" height="266" src="http://youtube.googleapis.com/v/EVZN_mdz7Ks&source=uds" type="application/x-shockwave-flash" allowfullscreen="true"></embed></object></div>
<br />
The main departure from Steve's design in the video was the inclusion of an electric pick-up. However, we didn't depart from Steve's advice and just followed his design for an electric pick-up using a piezo transducer and a 6mm jack socket soldered together as can be seen from about 4:30 in the <a href="http://www.youtube.com/watch?v=dvXNv4XXlIc">video for his stomp box</a>.
<br />
<br />
We took pictures all the way through which can be seen in chronological order in <a href="http://www.flickr.com/photos/graham_alton/sets/72157633298369565/">my Flickr set</a> or via the slideshow at the bottom of this post. We started off with a bunch of different stuff we needed to work up. Here's Matt with the cheesy-grinned first picture before we got started, posing with the various bits and pieces:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://www.flickr.com/photos/graham_alton/8670475041/in/set-72157633298369565" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://farm9.staticflickr.com/8385/8670475041_9e76b4f339_n.jpg" /></a></div>
<br />
More or less everything we used is there in the picture above:<br />
<br />
<ul>
<li>4' x 2' x ¾" birch faced ply sheet (for the top, bottom and sides)</li>
<li>3mm ply (for the front piece, called the tapa)</li>
<li>25mm dowel rod</li>
<li>piezo transducer and 6mm jack socket</li>
<li>4 speaker feet</li>
<li>Snare wire</li>
<li>2 knobs, m6 40mm long thread</li>
<li>Clear wax</li>
<li>Glue</li>
</ul>
<br />
On the first afternoon's work, the birch ply was cut to size and rebated to form a box shape, albeit not yet glued together:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://www.flickr.com/photos/graham_alton/8670474773/in/set-72157633298369565" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://farm9.staticflickr.com/8387/8670474773_de57bd3881_n.jpg" /></a></div>
<br />
This was actually the main part of the work we had to do. The next time we got together we modified <a href="http://www.flickr.com/photos/graham_alton/8680498844/in/set-72157633298369565">the back panel</a> so it had a large hole in it (to let the sound out) and a fitting for the jack socket to be screwed through. After that came the tricky business of fitting the adjustable snare dowel rod mechanism to the sides which can best be seen in <a href="http://www.flickr.com/photos/graham_alton/8757210454/in/set-72157633298369565">a couple</a> of <a href="http://www.flickr.com/photos/graham_alton/8757210424/in/set-72157633298369565">different pictures</a>. Once all that was done we were able to glue it all together and left it clamped up for a couple of days to dry, the result was a completed box:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://www.flickr.com/photos/graham_alton/8774732968/in/set-72157633298369565" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://farm6.staticflickr.com/5467/8774732968_2fdf703c74_n.jpg" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Finally, we cut the front to size and fitted that, waxed the whole thing then fitted the feet and jack socket. We gave it a few different tests. First was to sit on it (since that's how they're played) and it survived that, then Matt had his first play on it in my garage followed by heading in doors to hook it up to the stereo in order to test the semi-accoustic-ness off it. Everything worked well.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
We're both really pleased with it. It's really solidly constructed and feels like it should last a good many years use. All the tweaks to a basic Cajón design work really well including the adjustable snare and the electric pick-up. It looks really good too, we were really lucky to source such a nice looking piece of ply (thanks to my cousin's at <a href="http://www.ascot-timber.co.uk/">Ascot Timer Buildings</a>), finished it off with nicely rounded corners and a good quality clear wax. Of course, the really important bit is the sound and fortunately it performs on that front too (better than I'd expected). The base notes from the middle sound really deep and can be quite loud if you're really going for it and they graduate to a nice high pitch as you move towards playing at the sides. When turned on, the snare adds an extra dimension when hitting near the top too.</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://www.flickr.com/photos/graham_alton/8922695513/in/set-72157633298369565" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://farm8.staticflickr.com/7367/8922695513_d59f1a632d_n.jpg" /></a></div>
<br />
So, it's happy birthday to Matt (a wee bit late since we started making it just after his birthday). There have been loads of people interested in the project as we've bee going through so I'm sure he's going to be a busy boy showing it off all over the place now.<br />
<br />
I'll close out with the slideshow and another mention of thanks to <a href="https://twitter.com/MereMortalsWW">Steve Ramsey</a> for his excellent video tutorial.<br />
<br />
<center>
<object height="300" width="400"> <param name="flashvars" value="offsite=true&lang=en-us&page_show_url=%2Fphotos%2Fgraham_alton%2Fsets%2F72157633298369565%2Fshow%2Fwith%2F8670475041%2F&page_show_back_url=%2Fphotos%2Fgraham_alton%2Fsets%2F72157633298369565%2Fwith%2F8670475041%2F&set_id=72157633298369565&jump_to=8670475041"></param>
<param name="movie" value="http://www.flickr.com/apps/slideshow/show.swf?v=124984"></param>
<param name="allowFullScreen" value="true"></param>
<embed type="application/x-shockwave-flash" src="http://www.flickr.com/apps/slideshow/show.swf?v=124984" allowFullScreen="true" flashvars="offsite=true&lang=en-us&page_show_url=%2Fphotos%2Fgraham_alton%2Fsets%2F72157633298369565%2Fshow%2Fwith%2F8670475041%2F&page_show_back_url=%2Fphotos%2Fgraham_alton%2Fsets%2F72157633298369565%2Fwith%2F8670475041%2F&set_id=72157633298369565&jump_to=8670475041" width="400" height="300"></embed></object></center>
Graham Whitehttp://www.blogger.com/profile/03878311939940449093noreply@blogger.com0