<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wikidot="http://www.wikidot.com/rss-namespace">

	<channel>
		<title>Piotr Gabryjeluk blog</title>
		<link>http://piotrgabryjeluk.wikidot.com</link>
		<description>Blog, photos and developer notes of Piotr Gabryjeluk, one of Wikidot.com developers.</description>
				<copyright></copyright>
		<lastBuildDate>Thu, 21 May 2026 00:56:31 +0000</lastBuildDate>
		
					<item>
				<guid>http://piotrgabryjeluk.wikidot.com/blog:mac-m1-builds</guid>
				<title>Mac M1 Builds</title>
				<link>http://piotrgabryjeluk.wikidot.com/blog:mac-m1-builds</link>
				<description>

&lt;h1&gt;&lt;span&gt;Setup Mac&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=2462&amp;amp;amp;size=small&amp;amp;amp;timestamp=1779324991&quot; alt=&quot;Gabrys&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=2462)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;Gabrys&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Fri, 01 Jul 2022 05:57:55 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <h1><span>Setup Mac</span></h1> <ol> <li>Get an M1 mac (via scaleway)</li> <li>Connect via VNC over SSH</li> <li>Install Docker Desktop</li> </ol> <h1><span>Setup Docker Hub account</span></h1> <ol> <li>Log in to Docker Hub</li> <li>Generate access token. Copy to clipboard</li> </ol> <h1><span>Docker commands:</span></h1> <div class="code"> <pre><code># Build: $ docker buildx build --tag gabrys/elasticsearch:6.8 . # Log in to Docker Hub: $ security -v unlock-keychain ~/Library/Keychains/login.keychain-db $ docker login -u gabrys $ docker buildx create --use # Build and push: $ docker buildx build --platform linux/arm64/v8,linux/amd64 --push --tag gabrys/elasticsearch:6.8 .</code></pre></div> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/gabrys" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=2462&amp;amp;size=small&amp;amp;timestamp=1779324991" alt="Gabrys" style="background-image:url(http://www.wikidot.com/userkarma.php?u=2462)" /></a><a href="http://www.wikidot.com/user:info/gabrys" >Gabrys</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://piotrgabryjeluk.wikidot.com/blog:closing-svn2github</guid>
				<title>Closing svn2github</title>
				<link>http://piotrgabryjeluk.wikidot.com/blog:closing-svn2github</link>
				<description>

&lt;p&gt;Almost exactly one year ago, I was planning to spend some more time on &lt;a href=&quot;http://svn2github.com&quot;&gt;svn2github&lt;/a&gt;, (see &lt;a href=&quot;http://piotrgabryjeluk.wikidot.com/blog:svn2github-next-steps&quot;&gt;svn2github: Next Steps&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=2462&amp;amp;amp;size=small&amp;amp;amp;timestamp=1779324991&quot; alt=&quot;Gabrys&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=2462)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;Gabrys&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Sun, 13 Jan 2019 18:06:29 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>Almost exactly one year ago, I was planning to spend some more time on <a href="http://svn2github.com">svn2github</a>, (see <a href="http://piotrgabryjeluk.wikidot.com/blog:svn2github-next-steps">svn2github: Next Steps</a>).</p> <p>Unfortunately, I never delivered on that promise, and to put it as directly as I can, I need to <strong>close the project</strong> altogether. (Please continue reading if you're interested in doing a similar thing yourself!)</p> <h2><span>History</span></h2> <p>svn2github has been up since 2011/2012 (based on whois data). That's been 7 years already! What started a little side project, stayed exactly that. I kept it running, because I've seen people use it. I'm extremely happy I could help, but this time has come to an end.</p> <p>I created svn2github back in 2011 to help my team at Allegro deal with SVN dependencies to our Git project. We wanted to use Git for our PHP application and Git submodules for our dependencies, but at that point in time many mainstream projects were still using SVN. Then out of a weekend of quick Python coding, svn2github was born!</p> <p>7 years later and most programmers don't know what SVN is anymore :-). Most projects are either hosted in Git or Mercurial with big corporations backing them (Microsoft, Facebook). Also it looks like git submodules didn't catch on and language-specific dependency management is used instead (npm for JS, composer for PHP, etc). I don't think anyone will miss svn2github, but if you will, please leave me a comment, I will gladly share some information on how to build a service like svn2github. Let me remind you it was born in one weekend!</p> <h2><span>Stats</span></h2> <p>Through the 7 years of operation, its users mirrored about 1300+ SVN repositories to GitHub. My single server running the project was down a few times due to not scaling properly when mirroring HUGE repos (that I needed to disable at some point to continue operating). After removing the HUGE repos, the repos mirrored to GitHub currently take about 200GB.</p> <h2><span>Plan forward</span></h2> <p>13 January 2019: This note posted<br /> 20 January 2019: Disable automatically updating the repos (can still add more repos, but this will be a one-time import operation)<br /> 27 January 2019: Disable adding new repos</p> <p>I'm not going to remove repos from GitHub (unless someone requests it due to legal issues, etc).</p> <h2><span>Next steps</span></h2> <p>The biggest challenge running the project was making sure all of the 1,000+ repos are actually mirrored. If you have just one or two repos to look after, your job is much easier, in fact I created a little helper script to help you do just that. Please check the simplified &quot;just one repo&quot; host-yourself version of svn2github at this link: <a href="https://github.com/gabrys/svn2github">https://github.com/gabrys/svn2github</a></p> <h2><span>Thank you!</span></h2> <p>Thank you all for using the service. If you want to contact me, please leave me a direct message on Wikidot, or send me an email, or leave a comment.</p> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/gabrys" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=2462&amp;amp;size=small&amp;amp;timestamp=1779324991" alt="Gabrys" style="background-image:url(http://www.wikidot.com/userkarma.php?u=2462)" /></a><a href="http://www.wikidot.com/user:info/gabrys" >Gabrys</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://piotrgabryjeluk.wikidot.com/blog:svn2github-next-steps</guid>
				<title>svn2github: Next Steps</title>
				<link>http://piotrgabryjeluk.wikidot.com/blog:svn2github-next-steps</link>
				<description>

&lt;p&gt;I&#039;d like to invest a bit of time in &lt;a href=&quot;http://svn2github.com/&quot;&gt;http://svn2github.com/&lt;/a&gt; . I&#039;d like to do the following things:&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=2462&amp;amp;amp;size=small&amp;amp;amp;timestamp=1779324991&quot; alt=&quot;Gabrys&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=2462)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;Gabrys&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Wed, 10 Jan 2018 04:24:53 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>I'd like to invest a bit of time in <a href="http://svn2github.com/">http://svn2github.com/</a> . I'd like to do the following things:</p> <ul> <li>Add more transparency in the &quot;add&quot; queue and process &#8212; i.e. you should be able to see more than just &quot;Queued&quot; when you add a repo to be mirrored.</li> <li>Add some end-to-end tests. Should be easy to do, given how limited the functionality is</li> <li>Add a status page: showing results of the tests above, number of repos cloned, average mirror latency, last sync time, etc</li> <li>Add Monaro mining on the add page. Mine some money for me while waiting to get your repo cloned (I'd rather do this than ads)</li> <li>Change the syncing mechanism: currently it's mostly random, i.e. your repo might be updated every few hours or days depending on your luck. I'd like to weigh how often a repo is updated given how it is (sync smaller/faster repos more often) and whether it generally succeeds or not (if a repo doesn't sync once, increase the interval for it, so other repos can be at benefit).</li> </ul> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/gabrys" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=2462&amp;amp;size=small&amp;amp;timestamp=1779324991" alt="Gabrys" style="background-image:url(http://www.wikidot.com/userkarma.php?u=2462)" /></a><a href="http://www.wikidot.com/user:info/gabrys" >Gabrys</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://piotrgabryjeluk.wikidot.com/blog:centos-chroot</guid>
				<title>Centos Chroot</title>
				<link>http://piotrgabryjeluk.wikidot.com/blog:centos-chroot</link>
				<description>

&lt;p&gt;Let&#039;s say you want a chroot with CentOS with an older version of the system to test something.&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=2462&amp;amp;amp;size=small&amp;amp;amp;timestamp=1779324991&quot; alt=&quot;Gabrys&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=2462)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;Gabrys&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Tue, 12 Dec 2017 19:49:28 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>Let's say you want a chroot with CentOS with an older version of the system to test something.</p> <h1><span>Get the minimal root fs</span></h1> <ol> <li>Check out Docker images for CentOS: <a href="https://hub.docker.com/_/centos/">https://hub.docker.com/_/centos/</a></li> <li>Follow the Dockerfile link for the version you're interested in, say 6.6: <a href="https://github.com/CentOS/sig-cloud-instance-images/blob/8911843d9a6cc71aadd81e491f94618aded94f30/docker/Dockerfile">https://github.com/CentOS/sig-cloud-instance-images/blob/8911843d9a6cc71aadd81e491f94618aded94f30/docker/Dockerfile</a></li> <li>Go one level up in GitHub and locate the centos-*.tar.xz file, it's the archive with the mininal rootfs for CentOS: <a href="https://github.com/CentOS/sig-cloud-instance-images/blob/8911843d9a6cc71aadd81e491f94618aded94f30/docker/centos-6.6-20150304_1234-docker.tar.xz">https://github.com/CentOS/sig-cloud-instance-images/blob/8911843d9a6cc71aadd81e491f94618aded94f30/docker/centos-6.6-20150304_1234-docker.tar.xz</a></li> <li>Click the download link</li> </ol> <h1><span>Prepare a directory, unpack the root fs</span></h1> <div class="code"> <pre><code>sudo mkdir -p /mnt/centos-chroot/ # You may need to uncompress the XZ file, but my tar could deal with it, so try yourself: sudo tar -xf /path/to/centos-6.6-20150304_1234-docker.tar.xz # Mount some pseudo filesystems: cd /mnt/centos-chroot/ sudo mount --bind /sys sys sudo mount --bind /dev dev sudo mount -t proc proc proc</code></pre></div> <h1><span>Enter your precious chroot:</span></h1> <div class="code"> <pre><code>sudo chroot /mnt/centos-chroot/ /bin/bash . /etc/environment</code></pre></div> <p>Done!</p> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/gabrys" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=2462&amp;amp;size=small&amp;amp;timestamp=1779324991" alt="Gabrys" style="background-image:url(http://www.wikidot.com/userkarma.php?u=2462)" /></a><a href="http://www.wikidot.com/user:info/gabrys" >Gabrys</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://piotrgabryjeluk.wikidot.com/blog:getting-used-to-mac</guid>
				<title>Getting Used To Mac (or not really)</title>
				<link>http://piotrgabryjeluk.wikidot.com/blog:getting-used-to-mac</link>
				<description>

&lt;p&gt;Starting October 3rd I&#039;ve been using a Mac. This has been very challenging and here are a few reasons why (and how to fix it).&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=2462&amp;amp;amp;size=small&amp;amp;amp;timestamp=1779324991&quot; alt=&quot;Gabrys&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=2462)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;Gabrys&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Wed, 11 Oct 2017 19:32:45 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>Starting October 3rd I've been using a Mac. This has been very challenging and here are a few reasons why (and how to fix it).</p> <div class="content-separator" style="display: none:"></div> <h1><span>Touch Bar</span></h1> <p>The keyboard is equipped with the amazing piece of technology called Touch Bar. What is it? It's a replacement for the top row of the keys on the keyboard. What's wrong with this?</p> <p>*Firstly*, the buttons on it are displayed. You need to touch them, not press. This means a lot of accidental actions done.</p> <p>*Secondly*, the buttons displayed change depending on the application running. This means you need to LOOK at the keys before you can &quot;press&quot; them. Not sure about you guys, but I think looking at the keyboard is LAME.</p> <p>*Thirdly*, when running some programs the things displayed on the bar change with every key press. This is very annoying. Example: iTerm.</p> <p>How to solve: unfortunately you cannot disable Touch Bar, but you can configure it to only show the functional keys. You take away the customizability of it for the applications so the buttons shown are always the same.</p> <p>Unfortunately this still means you press a lot of those keys accidentally, so to solve the other part of the problem: use an external keyboard.</p> <h1><span>Keyboard continued</span></h1> <p>Touch bar is just one thing that's wrong with the keyboard, there are more things.</p> <p>This is highly subjective, but the keyboard is very unpleasant to type on. It feels very plasticky.</p> <p>There are no &quot;Home&quot; and &quot;End&quot; buttons on the integrated keyboard. Even if your external keyboard has the Home and End buttons (and other useful stuff like Page Up/Down), which is better do, those work in a very weird way: Home takes you to the beginning of the document, End to the end, rather than to the first and last character of the line. There's a bit of trickery you can do to &quot;fix&quot; that thankfully, but the default behavior is just broken.</p> <p>I treat my work and my health seriously. My work involves typing on a keyboard and that can involve serious injuries. That's why it's important to use ergonomic keyboards. Those keyboards tend to have PC layout rather than a Mac layout. What does it mean? The layout of the lowest row is like that: Ctrl, Win, Alt, Space, Alt, Menu, Ctrl. On Macs your layout is this: Ctrl, Option (alt), Command (win), space, Command (win), Option. On a PC the convention is the right Alt is for typing local characters, for example Alt+a = ą, while the left Alt is for shortcuts. On Macs both Options work the same way. The problem with this setup is you can't easily switch between keyboards, because you'll quickly start hitting Command+a instead of Option+a which selects everything in your text field. Super annoying, so what you need to do is to remap your internal keyboard to switch Command and Option keys. If you wanted to &quot;fix&quot; your external keyboard instead you're going to re-learn typing your local characters with your left Windows key, because there's no Windows key on the right side&#8230;</p> <p>As some of you may know, I type on a keyboard using the Dvorak layout. On Macs this mean I can only type in English&#8230; There's no Polish Dvorak&#8230; Unless you load a custom keymap, which binds ź to Option-x instead of Option-w which is just next to Z&#8230; Thankfully you don't use ź that much.</p> <h1><span>Mouse / Touchpad</span></h1> <p>There's a controversial setting for your mouse and touchpad named &quot;Natural&quot; scrolling, which is really &quot;reversed&quot; scrolling, i.e. it reverses how the scroll used to work on both touchpad and mouse. While I agree the &quot;Natural&quot; scrolling makes sense for touchpad, and I'd like to use that, that setting also reverses the scroll behavior for your mouse. ANNOYING! You need a separate program running in the background to allow you to control both settings separately. It's called &quot;Scroll reverser&quot;.</p> <h1><span>Playing with windows</span></h1> <p>A bunch of annoyances related to window positioning. There's a Command+Tab shortcut for switching applications and Control-Tab shortcut for switching tabs in a window. But how do you switch between windows of the same application? (Say you have a few browser windows). There's another keyboard shortcut for that. Don't worry. There's no setting to merge window and application switcher though.</p> <p>I expect the application to hide when I click on the application icon in the dock. What happens? Nothing. Great. But hey, there's Command+h shortcut for this. (Also annoying if you're used to using Ctrl-h shortcut and also started &quot;naturally&quot; using Command instead of Ctrl for some shortcuts).</p> <h1><span>Slowness</span></h1> <p>Macs take forever to (re)boot. Even with SSD, ultra high performance CPU and software carefully trimmed to the hardware (or the other way round). It takes very long to reboot your computer. Thankfully you don't need to do that daily, but once you want to do this, you're gonna have a lot of waiting.</p> <p>When I click my Terminal icon on an older Linux machine, my terminal window pops out and shows me my prompt sign immediately (I mean everything happens below 200ms from the click). On my Mac it may take 3 seconds from the window opening to showing the prompt. This depends on the system load, but it's definitely not as snappy as one would expect from a top-tier PRO computer.</p> <h1><span>Ports</span></h1> <p>Remember I needed to connect an external keyboard? It so happens it's a wireless keyboard with a very slim radio transmitter you put to your USB port and your laptop now has a very subtle bump. Well, that is, if your laptop has any USB-A ports. If you have a Mac, you'll need a 10-cm long adapter for your transmitter. Bravo! Obviously you also need an adapter if you want to connect your screen to a display, because the laptop doesn't have an HDMI port either.</p> <h1><span>Summary and some good things</span></h1> <p>Summing up, the machine needs a lots of customization to make it work sensibly. Switching from using Ctrl for most shortcuts to Command is not that bad and has one big up-side. In your terminal applications, you can use the same Command+c, Command+v for copy/paste as in the other applications and Ctrl+* for your regular in-command-line shortcuts (Ctrl+c, Ctrl+z, etc). There's no conflicts like in Linux (where the copy is done with Ctrl+Shift+c instead).</p> <p>Also because the laptop is powered with USB-C, I can use my laptop charger to charge my USB-C phone!</p> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/gabrys" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=2462&amp;amp;size=small&amp;amp;timestamp=1779324991" alt="Gabrys" style="background-image:url(http://www.wikidot.com/userkarma.php?u=2462)" /></a><a href="http://www.wikidot.com/user:info/gabrys" >Gabrys</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://piotrgabryjeluk.wikidot.com/blog:server-commander</guid>
				<title>Server Commander</title>
				<link>http://piotrgabryjeluk.wikidot.com/blog:server-commander</link>
				<description>

&lt;p&gt;Here&#039;s a problem I&#039;d like was already solved:&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=2462&amp;amp;amp;size=small&amp;amp;amp;timestamp=1779324991&quot; alt=&quot;Gabrys&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=2462)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;Gabrys&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Wed, 12 Jul 2017 04:46:37 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>Here's a problem I'd like was already solved:</p> <p>Be able to manage and run &quot;tasks&quot; on a Linux server. More specifically:</p> <ul> <li>There should be a WEB interface where: <ul> <li>I could define commands or tasks that the server is capable of doing</li> <li>I could schedule tasks to run at specific times (like cron)</li> </ul> </li> <li>The tasks/commands should be (optionally) parametrized</li> <li>The tasks/commands should be (optionally) stored in GitHub and/or a database</li> <li>The task runs should not overlap with each other (i.e. when the previous run is still in progress don't start the new one) &#8212; configurable</li> <li>The task configuration should include: <ul> <li>the command to run</li> <li>task timeout &#8212; the task should be killed after the specified time</li> <li>environment variables to set for the task</li> <li>max CPU/memory/disk to use (optional)</li> <li>number of times to retry on failure</li> <li>what to do on success and failure &#8212; e-mail, webhook and trigger another task</li> <li>directory to run the command in: I can specify one, or a temporary one is created for each run and cleared after the run</li> <li>user to run the command as: I can specify one, or a temporary user is created for each run and cleared after the run</li> </ul> </li> <li>The task run view should include <ul> <li>colored command output</li> <li>command exit code: OK/FAIL</li> <li>resources used by the task (optional)</li> <li>time the task took, time the task started and ended</li> <li>environment variables</li> <li>link to next/previous run and a button to re-run</li> </ul> </li> <li>The code should be free and open and extremely easy to install</li> <li>There should be an error log in the UI to track all the jobs failures</li> <li>Misconfigured tasks should not take the machine down &#8212; there should be some level of monitoring &#8212; don't start new jobs when load is high or disk is almost full, etc</li> <li>One should be able to have a nice dashboard with selected tasks for easy launching</li> </ul> <p>What I describe here is to some extent already covered by some of the following:</p> <ul> <li>Jenkins <a href="https://jenkins.io/">https://jenkins.io/</a></li> <li>Travis-CI <a href="https://travis-ci.com/">https://travis-ci.com/</a></li> <li>Rundeck <a href="http://rundeck.org/">http://rundeck.org/</a></li> <li>Minicron <a href="https://github.com/jamesrwhite/minicron/">https://github.com/jamesrwhite/minicron/</a></li> </ul> <p>Here's what's wrong with them:</p> <ul> <li>Jenkins' UI is to complicated for simple tasks, also it feel very heavy</li> <li>in Travis-CI you specify the tasks in your code, not in Travis, also it's not software you run locally</li> <li>My experience with Rundeck is it doesn't work out of the box, I could debug it, but I didn't want to, also UI is a bit too complex</li> <li>Minicron is way too simple and (currently) only allows you to run jobs through ssh (not locally)</li> </ul> <p>To reiterate I'd like:</p> <ul> <li>A web UI for cron, that's also</li> <li>a bit like Jenkins in a way you can see the output of each of the command runs</li> <li>and have ability to sandbox the processes it runs</li> <li>looks nice and is easy to install and doesn't require maintenance</li> </ul> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/gabrys" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=2462&amp;amp;size=small&amp;amp;timestamp=1779324991" alt="Gabrys" style="background-image:url(http://www.wikidot.com/userkarma.php?u=2462)" /></a><a href="http://www.wikidot.com/user:info/gabrys" >Gabrys</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://piotrgabryjeluk.wikidot.com/blog:how-to-disable-kinetic-scrolling-on-linux</guid>
				<title>How To Disable Kinetic Scrolling On Linux</title>
				<link>http://piotrgabryjeluk.wikidot.com/blog:how-to-disable-kinetic-scrolling-on-linux</link>
				<description>

&lt;p&gt;I spent more time than I wished searching for how to disable kinetic scrolling on Linux. Here&#039;s the spell:&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=2462&amp;amp;amp;size=small&amp;amp;amp;timestamp=1779324991&quot; alt=&quot;Gabrys&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=2462)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;Gabrys&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Tue, 14 Feb 2017 04:44:11 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>I spent more time than I wished searching for how to disable kinetic scrolling on Linux. Here's the spell:</p> <div class="code"> <pre><code>$ synclient CoastingSpeed=0</code></pre></div> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/gabrys" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=2462&amp;amp;size=small&amp;amp;timestamp=1779324991" alt="Gabrys" style="background-image:url(http://www.wikidot.com/userkarma.php?u=2462)" /></a><a href="http://www.wikidot.com/user:info/gabrys" >Gabrys</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://piotrgabryjeluk.wikidot.com/blog:roku-remapping-useless-channels</guid>
				<title>Roku Remapping Useless Channels</title>
				<link>http://piotrgabryjeluk.wikidot.com/blog:roku-remapping-useless-channels</link>
				<description>

&lt;p&gt;Does your Roku remote have a useless Rdio button? Rdio has closed, but you cannot remap your remote buttons. Or can you?&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=2462&amp;amp;amp;size=small&amp;amp;amp;timestamp=1779324991&quot; alt=&quot;Gabrys&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=2462)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;Gabrys&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Sun, 23 Oct 2016 03:44:56 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>Does your Roku remote have a useless Rdio button? Rdio has closed, but you cannot remap your remote buttons. Or can you?</p> <div class="image-container floatright"><a href="http://piotrgabryjeluk.wdfiles.com/local--files/blog:roku-remapping-useless-channels/IMG_20161022_204713.jpg"><img src="http://piotrgabryjeluk.wdfiles.com/local--resized-images/blog:roku-remapping-useless-channels/IMG_20161022_204713.jpg/small.jpg" alt="IMG_20161022_204713.jpg" class="image" /></a></div> <p>You cannot really remap the keys, but what you can do is check what channel is currently displayed on the TV and launch another one instead. Unfortunately, there's no pub/sub mechanism, so you need to poll.</p> <p>Here's te whole code:</p> <div class="code"> <pre><code>#!/bin/bash PLAYSTATION=tvinput.hdmi3 ROKU_MEDIA_PLAYER=2213 YOUTUBE=837 while sleep 1; do curApp=&quot;`curl -s http://roku:8060/query/active-app | grep -o '&gt;.*&lt;/app&gt;'`&quot; case &quot;$curApp&quot; in *VUDU*) curl -X POST http://roku:8060/launch/$ROKU_MEDIA_PLAYER ;; *Netflix*) curl -X POST http://roku:8060/launch/$YOUTUBE ;; *Rdio*) curl -X POST http://roku:8060/launch/$PLAYSTATION ;; esac done</code></pre></div> <p>As you can see starting VUDU channel opens the Roku Media Player, starting Netflix opens YouTube, and RIP Rdio is remapped to to HDMI3, which is the HDMI port I used for my PlayStation.</p> <p>To find out what IDs different channels have, just call:</p> <div class="code"> <pre><code>curl http://roku:8060/query/apps</code></pre></div> <p>(Note I'm using <a href="http://roku:8060/">http://roku:8060/</a> in this script, that's because I run a local DNS server in my local network and my Roku TV has a fixed IP that &quot;roku&quot; name resolves to.)</p> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/gabrys" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=2462&amp;amp;size=small&amp;amp;timestamp=1779324991" alt="Gabrys" style="background-image:url(http://www.wikidot.com/userkarma.php?u=2462)" /></a><a href="http://www.wikidot.com/user:info/gabrys" >Gabrys</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://piotrgabryjeluk.wikidot.com/blog:monitoring-freezer-temperature</guid>
				<title>Monitoring Freezer Temperature</title>
				<link>http://piotrgabryjeluk.wikidot.com/blog:monitoring-freezer-temperature</link>
				<description>

&lt;p&gt;For some time we&#039;ve had suspicions the freezer in our apartment doesn&#039;t work correctly. Recently my wife reached to it to get some ice cubes but found water in the form instead. That clearly meant the temperature was over the freezing point and stayed there for some time. She put a thermometer on the fridge, put the sensor into the freezer and started watching the readings. The temperature reached around -20°C and stayed there, fluctuating between -15°C and -20°C.&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=2462&amp;amp;amp;size=small&amp;amp;amp;timestamp=1779324991&quot; alt=&quot;Gabrys&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=2462)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;Gabrys&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Sun, 25 Sep 2016 22:11:15 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>For some time we've had suspicions the freezer in our apartment doesn't work correctly. Recently my wife reached to it to get some ice cubes but found water in the form instead. That clearly meant the temperature was over the freezing point and stayed there for some time. She put a thermometer on the fridge, put the sensor into the freezer and started watching the readings. The temperature reached around -20°C and stayed there, fluctuating between -15°C and -20°C.</p> <h1><span>The webcam reader</span></h1> <p>I decided, it's time to record the temperature, so I brought the laptop, adjusted the screen angle, set the brightness to max and took a shot from the webcam to see if the thermometer is in the view of the camera:</p> <div class="code"> <pre><code>mplayer tv:// -vo png -frames 3</code></pre></div> <p>This takes 3 frames from the webcam and saves them as PNG files: 00000001.png, 00000002.png, and 00000003.png. If you wonder why I need 3 frames, the first one is always under- or overexposed and out of focus, the second is usually OK and the third is almost always good (as for a webcam), so long story short, I'm giving some time to the camera to auto-adjust its settings.</p> <p>Here's a script that does just a bit more than that:</p> <div class="code"> <pre><code>#!/bin/bash set -e export DISPLAY=:0 curdate=`date +%x-%X | sed 's/[\.:]//g'` outpng=/home/quake/git/thermonitor/out/&quot;$curdate&quot;.png tmppng=/home/quake/git/thermonitor/tmp/00000005.png mkdir -p /home/quake/git/thermonitor/out/ /home/quake/git/thermonitor/tmp cd /home/quake/git/thermonitor/tmp # White background ristretto ../white.png &amp; # Wake screen xte &quot;mousemove 100 100&quot; sleep 0.2 xte &quot;mousemove 99 99&quot; # Dump screen mplayer tv:// -vo png -frames 5 -noconsolecontrols cp &quot;$tmppng&quot; &quot;$outpng&quot; echo &quot;$outpng&quot; kill $!</code></pre></div> <p>It's very hacky, but here are the big parts:</p> <ul> <li><tt>set -e</tt> makes the script stop if any of the commands in it fail</li> <li><tt>export DISPLAY=:0</tt> selects the default X display, so I can run the command from an SSH shell</li> <li>Then we have some hard-coded paths to <tt>tmp</tt> and <tt>out</tt> directories</li> <li><tt>ristretto ./white.png &amp;</tt> starts a image-viewer and shows a <tt>white.png</tt> file which is a big all-white file. This makes the screen display enough white, so the LCD thermometer is properly lit</li> <li>I use <tt>xte</tt> to move the mouse around: this blocks the automatic screen dimming, so the screen continues to be 100% bright</li> <li>Then we have the <tt>mplayer</tt> command from before, just changed to 5 frames (just to be sure) and <tt>-noconsolecontrols</tt>. <tt>mplayer</tt> kind of hangs when you start it without a proper terminal on stdin, unless you pass this option</li> <li>Then I copy the 5th frame to the output file, which has the current date and the time in its path</li> <li>Finally I close the ristretto process I opened before</li> </ul> <p>I run this command in a while loop like that:</p> <div class="code"> <pre><code>while sleep 28 ; do ./dup.sh ; done</code></pre></div> <p><tt>./dup.sh</tt> takes around 2 seconds, so I have about 2 photos a minute.</p> <p>I put that to a screen session.</p> <p>Now in the <tt>out</tt> directory I serve the files using Python HTTP server:</p> <div class="code"> <pre><code>python -m SimpleHTTPServer</code></pre></div> <p>This starts an HTTP server on port 8000 and serves all the files and creates an index of them when requesting /.</p> <h1><span>The processing</span></h1> <p>How easier to copy the HTTP-exposed files than using a plain-old <tt>wget</tt> command?</p> <div class="code"> <pre><code>wget -r http://dell:8000/</code></pre></div> <p>This creates directory <tt>dell:8000</tt> and downloads all the PNG files to it.</p> <p>Once you have that directory you may later want to update it with only the newer files:</p> <div class="code"> <pre><code>rm dell\:8000/index.html wget -nc -r http://dell:8000/</code></pre></div> <p>The <tt>-nc</tt> switch makes <tt>wget</tt> ignore files that are already there. We explicitly remove the <tt>index.html</tt> so it downloads a new list (that includes newer files).</p> <p>I wanted to make a program that gets a photo of the 7-segment display and reads it producing a number that along with the date could be used to graph the temperature over time.</p> <p>First, let's use ImageMagick to:</p> <ul> <li>crop the picture to only the interesting part: the OUT reading</li> <li>shear the picture to make the LCD segments vertical and horizontal, not skewed</li> <li>bump contrast/gamma to remove the noise</li> <li>auto-adjust the visual properties of the picture so it's more consistent across different times (like night vs day)</li> <li>make it black and white &#8212; turned out it works best if I only use the Green channel, R and B turned out more noisy than G.</li> <li>resize to as small size as needed &#8212; for easier and faster processing</li> </ul> <p>Here's the actual command:</p> <div class="code"> <pre><code>convert $file_in -gamma 1.5 -auto-level -brightness-contrast 35x80 -shear -14x0 -crop 260x70+320+227 -channel Green -separate -resize 40x20 $file_out</code></pre></div> <p>Input image:</p> <img src="http://piotrgabryjeluk.wdfiles.com/local--files/blog:monitoring-freezer-temperature/input.png" alt="input.png" class="image" /> <p>Output image:</p> <img src="http://piotrgabryjeluk.wdfiles.com/local--files/blog:monitoring-freezer-temperature/output.png" alt="output.png" class="image" /> <p>Zoomed in:</p> <img src="http://piotrgabryjeluk.wdfiles.com/local--files/blog:monitoring-freezer-temperature/output-scaled.png" alt="output-scaled.png" class="image" /> <p>You can see the bottom segment is not really visible, but that's OK, all the digits can be properly read without that segment being visible, so we'll only consider the 6 segments that we can easily read.</p> <p>Now comes the meat, the Python program reading the file and returning the temperature:</p> <div class="code"> <div class="hl-main"> <pre><span class="hl-comment">#!/usr/bin/env python</span><span class="hl-code"> </span><span class="hl-comment">#encoding: utf-8</span><span class="hl-code"> </span><span class="hl-reserved">from</span><span class="hl-code"> </span><span class="hl-identifier">PIL</span><span class="hl-code"> </span><span class="hl-reserved">import</span><span class="hl-code"> </span><span class="hl-identifier">Image</span><span class="hl-code"> </span><span class="hl-comment"># Points that hold each segment:</span><span class="hl-code"> </span><span class="hl-comment"># d1 is the first digit</span><span class="hl-code"> </span><span class="hl-identifier">d1_sA</span><span class="hl-code"> = </span><span class="hl-brackets">[(</span><span class="hl-number">12</span><span class="hl-code">,</span><span class="hl-number">1</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">13</span><span class="hl-code">,</span><span class="hl-number">1</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">14</span><span class="hl-code">,</span><span class="hl-number">1</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">15</span><span class="hl-code">,</span><span class="hl-number">1</span><span class="hl-brackets">)]</span><span class="hl-code"> </span><span class="hl-identifier">d1_sB</span><span class="hl-code"> = </span><span class="hl-brackets">[(</span><span class="hl-number">18</span><span class="hl-code">,</span><span class="hl-number">2</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">18</span><span class="hl-code">,</span><span class="hl-number">3</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">18</span><span class="hl-code">,</span><span class="hl-number">4</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">18</span><span class="hl-code">,</span><span class="hl-number">5</span><span class="hl-brackets">)]</span><span class="hl-code"> </span><span class="hl-identifier">d1_sC</span><span class="hl-code"> = </span><span class="hl-brackets">[(</span><span class="hl-number">18</span><span class="hl-code">,</span><span class="hl-number">8</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">18</span><span class="hl-code">,</span><span class="hl-number">9</span><span class="hl-brackets">)]</span><span class="hl-code"> </span><span class="hl-identifier">d1_sE</span><span class="hl-code"> = </span><span class="hl-brackets">[(</span><span class="hl-number">11</span><span class="hl-code">,</span><span class="hl-number">8</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">12</span><span class="hl-code">,</span><span class="hl-number">9</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">11</span><span class="hl-code">,</span><span class="hl-number">9</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">12</span><span class="hl-code">,</span><span class="hl-number">8</span><span class="hl-brackets">)]</span><span class="hl-code"> </span><span class="hl-comment"># Don't need this, as we only ever have 1 and 2 in the first place</span><span class="hl-code"> </span><span class="hl-identifier">d1_sF</span><span class="hl-code"> = </span><span class="hl-brackets">[]</span><span class="hl-code"> </span><span class="hl-identifier">d1_sG</span><span class="hl-code"> = </span><span class="hl-brackets">[(</span><span class="hl-number">13</span><span class="hl-code">,</span><span class="hl-number">7</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">14</span><span class="hl-code">,</span><span class="hl-number">7</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">15</span><span class="hl-code">,</span><span class="hl-number">7</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">16</span><span class="hl-code">,</span><span class="hl-number">7</span><span class="hl-brackets">)]</span><span class="hl-code"> </span><span class="hl-comment"># d2 is the second digit</span><span class="hl-code"> </span><span class="hl-identifier">d2_sA</span><span class="hl-code"> = </span><span class="hl-brackets">[(</span><span class="hl-number">24</span><span class="hl-code">,</span><span class="hl-number">1</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">25</span><span class="hl-code">,</span><span class="hl-number">1</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">26</span><span class="hl-code">,</span><span class="hl-number">1</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">27</span><span class="hl-code">,</span><span class="hl-number">1</span><span class="hl-brackets">)]</span><span class="hl-code"> </span><span class="hl-identifier">d2_sB</span><span class="hl-code"> = </span><span class="hl-brackets">[(</span><span class="hl-number">29</span><span class="hl-code">,</span><span class="hl-number">2</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">29</span><span class="hl-code">,</span><span class="hl-number">3</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">29</span><span class="hl-code">,</span><span class="hl-number">4</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">29</span><span class="hl-code">,</span><span class="hl-number">5</span><span class="hl-brackets">)]</span><span class="hl-code"> </span><span class="hl-identifier">d2_sC</span><span class="hl-code"> = </span><span class="hl-brackets">[(</span><span class="hl-number">29</span><span class="hl-code">,</span><span class="hl-number">8</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">29</span><span class="hl-code">,</span><span class="hl-number">9</span><span class="hl-brackets">)]</span><span class="hl-code"> </span><span class="hl-identifier">d2_sE</span><span class="hl-code"> = </span><span class="hl-brackets">[(</span><span class="hl-number">22</span><span class="hl-code">,</span><span class="hl-number">8</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">22</span><span class="hl-code">,</span><span class="hl-number">9</span><span class="hl-brackets">)]</span><span class="hl-code"> </span><span class="hl-identifier">d2_sF</span><span class="hl-code"> = </span><span class="hl-brackets">[(</span><span class="hl-number">22</span><span class="hl-code">,</span><span class="hl-number">2</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">22</span><span class="hl-code">,</span><span class="hl-number">3</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">22</span><span class="hl-code">,</span><span class="hl-number">4</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">22</span><span class="hl-code">,</span><span class="hl-number">5</span><span class="hl-brackets">)]</span><span class="hl-code"> </span><span class="hl-identifier">d2_sG</span><span class="hl-code"> = </span><span class="hl-brackets">[(</span><span class="hl-number">24</span><span class="hl-code">,</span><span class="hl-number">6</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">25</span><span class="hl-code">,</span><span class="hl-number">6</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">26</span><span class="hl-code">,</span><span class="hl-number">6</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">24</span><span class="hl-code">,</span><span class="hl-number">7</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">25</span><span class="hl-code">,</span><span class="hl-number">7</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">26</span><span class="hl-code">,</span><span class="hl-number">7</span><span class="hl-brackets">)]</span><span class="hl-code"> </span><span class="hl-comment"># d3 is the small digit (first after the decimal point)</span><span class="hl-code"> </span><span class="hl-identifier">d3_sA</span><span class="hl-code"> = </span><span class="hl-brackets">[(</span><span class="hl-number">35</span><span class="hl-code">,</span><span class="hl-number">4</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">36</span><span class="hl-code">,</span><span class="hl-number">4</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">37</span><span class="hl-code">,</span><span class="hl-number">4</span><span class="hl-brackets">)]</span><span class="hl-code"> </span><span class="hl-identifier">d3_sB</span><span class="hl-code"> = </span><span class="hl-brackets">[(</span><span class="hl-number">38</span><span class="hl-code">,</span><span class="hl-number">5</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">38</span><span class="hl-code">,</span><span class="hl-number">6</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">38</span><span class="hl-code">,</span><span class="hl-number">7</span><span class="hl-brackets">)]</span><span class="hl-code"> </span><span class="hl-identifier">d3_sC</span><span class="hl-code"> = </span><span class="hl-brackets">[(</span><span class="hl-number">38</span><span class="hl-code">,</span><span class="hl-number">9</span><span class="hl-brackets">)]</span><span class="hl-code"> </span><span class="hl-identifier">d3_sE</span><span class="hl-code"> = </span><span class="hl-brackets">[(</span><span class="hl-number">34</span><span class="hl-code">,</span><span class="hl-number">9</span><span class="hl-brackets">)]</span><span class="hl-code"> </span><span class="hl-identifier">d3_sF</span><span class="hl-code"> = </span><span class="hl-brackets">[(</span><span class="hl-number">34</span><span class="hl-code">,</span><span class="hl-number">5</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">34</span><span class="hl-code">,</span><span class="hl-number">6</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">34</span><span class="hl-code">,</span><span class="hl-number">7</span><span class="hl-brackets">)]</span><span class="hl-code"> </span><span class="hl-identifier">d3_sG</span><span class="hl-code"> = </span><span class="hl-brackets">[(</span><span class="hl-number">35</span><span class="hl-code">,</span><span class="hl-number">8</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">36</span><span class="hl-code">,</span><span class="hl-number">8</span><span class="hl-brackets">)]</span><span class="hl-code"> </span><span class="hl-comment"># Now the tricky part, for each segment I define a threshold below which I consider it &quot;lit&quot;</span><span class="hl-code"> </span><span class="hl-comment"># 0 means completely black, 255 is white.</span><span class="hl-code"> </span><span class="hl-comment"># Because of uneven lighting, for each segment (and digit, but we ignore that) the value is different.</span><span class="hl-code"> </span><span class="hl-identifier">tA</span><span class="hl-code"> = </span><span class="hl-number">200</span><span class="hl-code"> </span><span class="hl-identifier">tB</span><span class="hl-code"> = </span><span class="hl-number">170</span><span class="hl-code"> </span><span class="hl-identifier">tC</span><span class="hl-code"> = </span><span class="hl-number">120</span><span class="hl-code"> </span><span class="hl-identifier">tE</span><span class="hl-code"> = </span><span class="hl-number">115</span><span class="hl-code"> </span><span class="hl-identifier">tF</span><span class="hl-code"> = </span><span class="hl-number">140</span><span class="hl-code"> </span><span class="hl-identifier">tG</span><span class="hl-code"> = </span><span class="hl-number">170</span><span class="hl-code"> </span><span class="hl-comment"># A threshold for the &quot;-&quot; sign</span><span class="hl-code"> </span><span class="hl-identifier">tSIGN</span><span class="hl-code"> = </span><span class="hl-number">200</span><span class="hl-code"> </span><span class="hl-comment"># All of those were obviously updated on the go to match the files</span><span class="hl-code"> </span><span class="hl-comment"># A nice debugging function that prints which segments the code considers lit</span><span class="hl-code"> </span><span class="hl-comment"># Also if you wondered what A, B, C, E, F, G meant, here's the schematic:</span><span class="hl-code"> </span><span class="hl-reserved">def</span><span class="hl-code"> </span><span class="hl-identifier">print_digit</span><span class="hl-brackets">(</span><span class="hl-identifier">segs</span><span class="hl-brackets">)</span><span class="hl-code">: </span><span class="hl-comment"># Only print this if there's a second argument to the script passed</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-builtin">len</span><span class="hl-brackets">(</span><span class="hl-identifier">sys</span><span class="hl-code">.</span><span class="hl-identifier">argv</span><span class="hl-brackets">)</span><span class="hl-code"> == </span><span class="hl-number">2</span><span class="hl-code">: </span><span class="hl-reserved">return</span><span class="hl-code"> </span><span class="hl-reserved">print</span><span class="hl-code"> </span><span class="hl-quotes">'''</span><span class="hl-string"> {A}{A} {A}{A} {F} {B} {F} {B} {F} {B} {G}{G} {G}{G} {E} {C} {E} {C} {E} {C} </span><span class="hl-quotes">'''</span><span class="hl-code">.</span><span class="hl-identifier">format</span><span class="hl-brackets">(</span><span class="hl-code"> </span><span class="hl-identifier">A</span><span class="hl-code">=</span><span class="hl-quotes">'</span><span class="hl-string">###</span><span class="hl-quotes">'</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-quotes">'</span><span class="hl-string">A</span><span class="hl-quotes">'</span><span class="hl-code"> </span><span class="hl-reserved">in</span><span class="hl-code"> </span><span class="hl-identifier">segs</span><span class="hl-code"> </span><span class="hl-reserved">else</span><span class="hl-code"> </span><span class="hl-quotes">'</span><span class="hl-string"> </span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-identifier">B</span><span class="hl-code">=</span><span class="hl-quotes">'</span><span class="hl-string">###</span><span class="hl-quotes">'</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-quotes">'</span><span class="hl-string">B</span><span class="hl-quotes">'</span><span class="hl-code"> </span><span class="hl-reserved">in</span><span class="hl-code"> </span><span class="hl-identifier">segs</span><span class="hl-code"> </span><span class="hl-reserved">else</span><span class="hl-code"> </span><span class="hl-quotes">'</span><span class="hl-string"> </span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-identifier">C</span><span class="hl-code">=</span><span class="hl-quotes">'</span><span class="hl-string">###</span><span class="hl-quotes">'</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-quotes">'</span><span class="hl-string">C</span><span class="hl-quotes">'</span><span class="hl-code"> </span><span class="hl-reserved">in</span><span class="hl-code"> </span><span class="hl-identifier">segs</span><span class="hl-code"> </span><span class="hl-reserved">else</span><span class="hl-code"> </span><span class="hl-quotes">'</span><span class="hl-string"> </span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-identifier">E</span><span class="hl-code">=</span><span class="hl-quotes">'</span><span class="hl-string">###</span><span class="hl-quotes">'</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-quotes">'</span><span class="hl-string">E</span><span class="hl-quotes">'</span><span class="hl-code"> </span><span class="hl-reserved">in</span><span class="hl-code"> </span><span class="hl-identifier">segs</span><span class="hl-code"> </span><span class="hl-reserved">else</span><span class="hl-code"> </span><span class="hl-quotes">'</span><span class="hl-string"> </span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-identifier">F</span><span class="hl-code">=</span><span class="hl-quotes">'</span><span class="hl-string">###</span><span class="hl-quotes">'</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-quotes">'</span><span class="hl-string">F</span><span class="hl-quotes">'</span><span class="hl-code"> </span><span class="hl-reserved">in</span><span class="hl-code"> </span><span class="hl-identifier">segs</span><span class="hl-code"> </span><span class="hl-reserved">else</span><span class="hl-code"> </span><span class="hl-quotes">'</span><span class="hl-string"> </span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-identifier">G</span><span class="hl-code">=</span><span class="hl-quotes">'</span><span class="hl-string">###</span><span class="hl-quotes">'</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-quotes">'</span><span class="hl-string">G</span><span class="hl-quotes">'</span><span class="hl-code"> </span><span class="hl-reserved">in</span><span class="hl-code"> </span><span class="hl-identifier">segs</span><span class="hl-code"> </span><span class="hl-reserved">else</span><span class="hl-code"> </span><span class="hl-quotes">'</span><span class="hl-string"> </span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-comment"># This doesn't do anything spectacular, just passes the coordinates for each of the segments and the average value of the first 9 pixels of the image: (0,0) - (3,3)</span><span class="hl-code"> </span><span class="hl-reserved">def</span><span class="hl-code"> </span><span class="hl-identifier">read_digit</span><span class="hl-brackets">(</span><span class="hl-identifier">im</span><span class="hl-code">, </span><span class="hl-identifier">pointsA</span><span class="hl-code">, </span><span class="hl-identifier">pointsB</span><span class="hl-code">, </span><span class="hl-identifier">pointsC</span><span class="hl-code">, </span><span class="hl-identifier">pointsE</span><span class="hl-code">, </span><span class="hl-identifier">pointsF</span><span class="hl-code">, </span><span class="hl-identifier">pointsG</span><span class="hl-code">, </span><span class="hl-identifier">avg9px</span><span class="hl-brackets">)</span><span class="hl-code">: </span><span class="hl-identifier">segs</span><span class="hl-code"> = </span><span class="hl-quotes">''</span><span class="hl-code"> </span><span class="hl-identifier">segs</span><span class="hl-code"> += </span><span class="hl-quotes">'</span><span class="hl-string">A</span><span class="hl-quotes">'</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-identifier">read_segment</span><span class="hl-brackets">(</span><span class="hl-identifier">im</span><span class="hl-code">, </span><span class="hl-identifier">pointsA</span><span class="hl-code">, </span><span class="hl-identifier">tA</span><span class="hl-code">-</span><span class="hl-identifier">avg9px</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-reserved">else</span><span class="hl-code"> </span><span class="hl-quotes">''</span><span class="hl-code"> </span><span class="hl-identifier">segs</span><span class="hl-code"> += </span><span class="hl-quotes">'</span><span class="hl-string">B</span><span class="hl-quotes">'</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-identifier">read_segment</span><span class="hl-brackets">(</span><span class="hl-identifier">im</span><span class="hl-code">, </span><span class="hl-identifier">pointsB</span><span class="hl-code">, </span><span class="hl-identifier">tB</span><span class="hl-code">-</span><span class="hl-identifier">avg9px</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-reserved">else</span><span class="hl-code"> </span><span class="hl-quotes">''</span><span class="hl-code"> </span><span class="hl-identifier">segs</span><span class="hl-code"> += </span><span class="hl-quotes">'</span><span class="hl-string">C</span><span class="hl-quotes">'</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-identifier">read_segment</span><span class="hl-brackets">(</span><span class="hl-identifier">im</span><span class="hl-code">, </span><span class="hl-identifier">pointsC</span><span class="hl-code">, </span><span class="hl-identifier">tC</span><span class="hl-code">-</span><span class="hl-identifier">avg9px</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-reserved">else</span><span class="hl-code"> </span><span class="hl-quotes">''</span><span class="hl-code"> </span><span class="hl-identifier">segs</span><span class="hl-code"> += </span><span class="hl-quotes">'</span><span class="hl-string">E</span><span class="hl-quotes">'</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-identifier">read_segment</span><span class="hl-brackets">(</span><span class="hl-identifier">im</span><span class="hl-code">, </span><span class="hl-identifier">pointsE</span><span class="hl-code">, </span><span class="hl-identifier">tE</span><span class="hl-code">-</span><span class="hl-identifier">avg9px</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-reserved">else</span><span class="hl-code"> </span><span class="hl-quotes">''</span><span class="hl-code"> </span><span class="hl-identifier">segs</span><span class="hl-code"> += </span><span class="hl-quotes">'</span><span class="hl-string">F</span><span class="hl-quotes">'</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-identifier">read_segment</span><span class="hl-brackets">(</span><span class="hl-identifier">im</span><span class="hl-code">, </span><span class="hl-identifier">pointsF</span><span class="hl-code">, </span><span class="hl-identifier">tF</span><span class="hl-code">-</span><span class="hl-identifier">avg9px</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-reserved">else</span><span class="hl-code"> </span><span class="hl-quotes">''</span><span class="hl-code"> </span><span class="hl-identifier">segs</span><span class="hl-code"> += </span><span class="hl-quotes">'</span><span class="hl-string">G</span><span class="hl-quotes">'</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-identifier">read_segment</span><span class="hl-brackets">(</span><span class="hl-identifier">im</span><span class="hl-code">, </span><span class="hl-identifier">pointsG</span><span class="hl-code">, </span><span class="hl-identifier">tG</span><span class="hl-code">-</span><span class="hl-identifier">avg9px</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-reserved">else</span><span class="hl-code"> </span><span class="hl-quotes">''</span><span class="hl-code"> </span><span class="hl-identifier">print_digit</span><span class="hl-brackets">(</span><span class="hl-identifier">segs</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-comment"># A list of all digits and their representation on the 7-segment display:</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-identifier">segs</span><span class="hl-code"> == </span><span class="hl-quotes">'</span><span class="hl-string">ABCEF</span><span class="hl-quotes">'</span><span class="hl-code">: </span><span class="hl-reserved">return</span><span class="hl-code"> </span><span class="hl-number">0</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-identifier">segs</span><span class="hl-code"> == </span><span class="hl-quotes">'</span><span class="hl-string">BC</span><span class="hl-quotes">'</span><span class="hl-code">: </span><span class="hl-reserved">return</span><span class="hl-code"> </span><span class="hl-number">1</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-identifier">segs</span><span class="hl-code"> == </span><span class="hl-quotes">'</span><span class="hl-string">ABEG</span><span class="hl-quotes">'</span><span class="hl-code">: </span><span class="hl-reserved">return</span><span class="hl-code"> </span><span class="hl-number">2</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-identifier">segs</span><span class="hl-code"> == </span><span class="hl-quotes">'</span><span class="hl-string">ABCG</span><span class="hl-quotes">'</span><span class="hl-code">: </span><span class="hl-reserved">return</span><span class="hl-code"> </span><span class="hl-number">3</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-identifier">segs</span><span class="hl-code"> == </span><span class="hl-quotes">'</span><span class="hl-string">BCFG</span><span class="hl-quotes">'</span><span class="hl-code">: </span><span class="hl-reserved">return</span><span class="hl-code"> </span><span class="hl-number">4</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-identifier">segs</span><span class="hl-code"> == </span><span class="hl-quotes">'</span><span class="hl-string">ACFG</span><span class="hl-quotes">'</span><span class="hl-code">: </span><span class="hl-reserved">return</span><span class="hl-code"> </span><span class="hl-number">5</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-identifier">segs</span><span class="hl-code"> == </span><span class="hl-quotes">'</span><span class="hl-string">ACEFG</span><span class="hl-quotes">'</span><span class="hl-code">: </span><span class="hl-reserved">return</span><span class="hl-code"> </span><span class="hl-number">6</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-identifier">segs</span><span class="hl-code"> == </span><span class="hl-quotes">'</span><span class="hl-string">ABC</span><span class="hl-quotes">'</span><span class="hl-code">: </span><span class="hl-reserved">return</span><span class="hl-code"> </span><span class="hl-number">7</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-identifier">segs</span><span class="hl-code"> == </span><span class="hl-quotes">'</span><span class="hl-string">ABCEFG</span><span class="hl-quotes">'</span><span class="hl-code">: </span><span class="hl-reserved">return</span><span class="hl-code"> </span><span class="hl-number">8</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-identifier">segs</span><span class="hl-code"> == </span><span class="hl-quotes">'</span><span class="hl-string">ABCFG</span><span class="hl-quotes">'</span><span class="hl-code">: </span><span class="hl-reserved">return</span><span class="hl-code"> </span><span class="hl-number">9</span><span class="hl-code"> </span><span class="hl-comment"># A special case for the first digit, it doesn't display &quot;0&quot;, just doesn't display any segments</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-identifier">segs</span><span class="hl-code"> == </span><span class="hl-quotes">''</span><span class="hl-code">: </span><span class="hl-reserved">return</span><span class="hl-code"> </span><span class="hl-number">0</span><span class="hl-code"> </span><span class="hl-comment"># The function that takes the PIL image object, gets a list of (x,y) coordinates</span><span class="hl-code"> </span><span class="hl-comment"># and checks if the average value of them is smaller than the threshold passed: segment &quot;on&quot;</span><span class="hl-code"> </span><span class="hl-comment"># For 0 points passed it returns False: segment &quot;off&quot;</span><span class="hl-code"> </span><span class="hl-reserved">def</span><span class="hl-code"> </span><span class="hl-identifier">read_segment</span><span class="hl-brackets">(</span><span class="hl-identifier">im</span><span class="hl-code">, </span><span class="hl-identifier">points</span><span class="hl-code">, </span><span class="hl-identifier">threshold</span><span class="hl-code">=</span><span class="hl-number">128</span><span class="hl-brackets">)</span><span class="hl-code">: </span><span class="hl-identifier">val</span><span class="hl-code"> = </span><span class="hl-number">0</span><span class="hl-code"> </span><span class="hl-reserved">for</span><span class="hl-code"> </span><span class="hl-identifier">point</span><span class="hl-code"> </span><span class="hl-reserved">in</span><span class="hl-code"> </span><span class="hl-identifier">points</span><span class="hl-code">: </span><span class="hl-identifier">val</span><span class="hl-code"> += </span><span class="hl-identifier">im</span><span class="hl-code">.</span><span class="hl-identifier">getpixel</span><span class="hl-brackets">(</span><span class="hl-identifier">point</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-reserved">return</span><span class="hl-code"> </span><span class="hl-identifier">val</span><span class="hl-code"> &lt; </span><span class="hl-identifier">threshold</span><span class="hl-code"> * </span><span class="hl-builtin">len</span><span class="hl-brackets">(</span><span class="hl-identifier">points</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-comment"># Nothing interesting in here, just for printing the date from the file name</span><span class="hl-code"> </span><span class="hl-reserved">def</span><span class="hl-code"> </span><span class="hl-identifier">get_date</span><span class="hl-brackets">(</span><span class="hl-identifier">file_name</span><span class="hl-brackets">)</span><span class="hl-code">: </span><span class="hl-identifier">time_str</span><span class="hl-code"> = </span><span class="hl-identifier">file_name</span><span class="hl-code">.</span><span class="hl-identifier">split</span><span class="hl-brackets">(</span><span class="hl-quotes">'</span><span class="hl-string">-</span><span class="hl-quotes">'</span><span class="hl-brackets">)[</span><span class="hl-code">-</span><span class="hl-number">1</span><span class="hl-brackets">]</span><span class="hl-code">.</span><span class="hl-identifier">replace</span><span class="hl-brackets">(</span><span class="hl-quotes">'</span><span class="hl-string">.png</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">''</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-identifier">d1</span><span class="hl-code">, </span><span class="hl-identifier">d2</span><span class="hl-code">, </span><span class="hl-identifier">m1</span><span class="hl-code">, </span><span class="hl-identifier">m2</span><span class="hl-code">, </span><span class="hl-identifier">y1</span><span class="hl-code">, </span><span class="hl-identifier">y2</span><span class="hl-code">, </span><span class="hl-identifier">y3</span><span class="hl-code">, </span><span class="hl-identifier">y4</span><span class="hl-code"> = </span><span class="hl-identifier">file_name</span><span class="hl-code">.</span><span class="hl-identifier">split</span><span class="hl-brackets">(</span><span class="hl-quotes">'</span><span class="hl-string">/</span><span class="hl-quotes">'</span><span class="hl-brackets">)[</span><span class="hl-code">-</span><span class="hl-number">1</span><span class="hl-brackets">]</span><span class="hl-code">.</span><span class="hl-identifier">split</span><span class="hl-brackets">(</span><span class="hl-quotes">'</span><span class="hl-string">-</span><span class="hl-quotes">'</span><span class="hl-brackets">)[</span><span class="hl-number">0</span><span class="hl-brackets">]</span><span class="hl-code"> </span><span class="hl-reserved">return</span><span class="hl-code"> </span><span class="hl-quotes">'</span><span class="hl-string">{}{}/{}{}/{}{}{}{} </span><span class="hl-quotes">'</span><span class="hl-code">.</span><span class="hl-identifier">format</span><span class="hl-brackets">(</span><span class="hl-identifier">m1</span><span class="hl-code">, </span><span class="hl-identifier">m2</span><span class="hl-code">, </span><span class="hl-identifier">d1</span><span class="hl-code">, </span><span class="hl-identifier">d2</span><span class="hl-code">, </span><span class="hl-identifier">y1</span><span class="hl-code">, </span><span class="hl-identifier">y2</span><span class="hl-code">, </span><span class="hl-identifier">y3</span><span class="hl-code">, </span><span class="hl-identifier">y4</span><span class="hl-brackets">)</span><span class="hl-code"> + </span><span class="hl-quotes">'</span><span class="hl-string">{}{}:{}{}:{}{}</span><span class="hl-quotes">'</span><span class="hl-code">.</span><span class="hl-identifier">format</span><span class="hl-brackets">(</span><span class="hl-code">*</span><span class="hl-builtin">list</span><span class="hl-brackets">(</span><span class="hl-identifier">time_str</span><span class="hl-brackets">))</span><span class="hl-code"> </span><span class="hl-comment"># A bunch of imports in the middle of the file</span><span class="hl-code"> </span><span class="hl-comment"># Don't do that at home ;-)</span><span class="hl-code"> </span><span class="hl-reserved">import</span><span class="hl-code"> </span><span class="hl-identifier">sys</span><span class="hl-code"> </span><span class="hl-reserved">import</span><span class="hl-code"> </span><span class="hl-identifier">subprocess</span><span class="hl-code"> </span><span class="hl-comment"># This will be for example: pngs/dell\:8000/24092016-101055.png</span><span class="hl-code"> </span><span class="hl-identifier">file_in</span><span class="hl-code"> = </span><span class="hl-identifier">sys</span><span class="hl-code">.</span><span class="hl-identifier">argv</span><span class="hl-brackets">[</span><span class="hl-number">1</span><span class="hl-brackets">]</span><span class="hl-code"> </span><span class="hl-comment"># And this: processed-pngs/dell\:8000/24092016-101055.png</span><span class="hl-code"> </span><span class="hl-identifier">file_out</span><span class="hl-code"> = </span><span class="hl-quotes">'</span><span class="hl-string">processed-</span><span class="hl-quotes">'</span><span class="hl-code"> + </span><span class="hl-identifier">file_in</span><span class="hl-code"> </span><span class="hl-comment"># Calling the ImageMagick as discussed in the article</span><span class="hl-code"> </span><span class="hl-identifier">subprocess</span><span class="hl-code">.</span><span class="hl-identifier">check_call</span><span class="hl-brackets">([</span><span class="hl-quotes">'</span><span class="hl-string">convert</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-identifier">file_in</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">-gamma</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">1.5</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">-auto-level</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">-brightness-contrast</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">35x80</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">-shear</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">-14x0</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">-crop</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">260x70+320+227</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">-channel</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">Green</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">-separate</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">-resize</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">40x20</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-identifier">file_out</span><span class="hl-brackets">])</span><span class="hl-code"> </span><span class="hl-comment"># Reading what it created</span><span class="hl-code"> </span><span class="hl-identifier">im</span><span class="hl-code">=</span><span class="hl-identifier">Image</span><span class="hl-code">.</span><span class="hl-builtin">open</span><span class="hl-brackets">(</span><span class="hl-identifier">file_out</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-comment"># Now a thing I added at some point later.</span><span class="hl-code"> </span><span class="hl-comment"># Because of different lighting throughout the day and because the ImageMagick command</span><span class="hl-code"> </span><span class="hl-comment"># above was not good compensating for it (in spite of auto-level and high contrast)</span><span class="hl-code"> </span><span class="hl-comment"># some of the images were darker than the others. In most images (the ideal scenario for the code)</span><span class="hl-code"> </span><span class="hl-comment"># the first 9 pixels of the image (0,0) to (3,3) were just white (or very close), but in those darker</span><span class="hl-code"> </span><span class="hl-comment"># images the whole image was darker and I used the first 9 pixels to detect how much darker</span><span class="hl-code"> </span><span class="hl-identifier">first9px</span><span class="hl-code"> = </span><span class="hl-identifier">im</span><span class="hl-code">.</span><span class="hl-identifier">getpixel</span><span class="hl-brackets">((</span><span class="hl-number">0</span><span class="hl-code">,</span><span class="hl-number">0</span><span class="hl-brackets">))</span><span class="hl-code"> + </span><span class="hl-identifier">im</span><span class="hl-code">.</span><span class="hl-identifier">getpixel</span><span class="hl-brackets">((</span><span class="hl-number">0</span><span class="hl-code">,</span><span class="hl-number">1</span><span class="hl-brackets">))</span><span class="hl-code"> + </span><span class="hl-identifier">im</span><span class="hl-code">.</span><span class="hl-identifier">getpixel</span><span class="hl-brackets">((</span><span class="hl-number">0</span><span class="hl-code">,</span><span class="hl-number">2</span><span class="hl-brackets">))</span><span class="hl-code"> \ + </span><span class="hl-identifier">im</span><span class="hl-code">.</span><span class="hl-identifier">getpixel</span><span class="hl-brackets">((</span><span class="hl-number">1</span><span class="hl-code">,</span><span class="hl-number">0</span><span class="hl-brackets">))</span><span class="hl-code"> + </span><span class="hl-identifier">im</span><span class="hl-code">.</span><span class="hl-identifier">getpixel</span><span class="hl-brackets">((</span><span class="hl-number">1</span><span class="hl-code">,</span><span class="hl-number">1</span><span class="hl-brackets">))</span><span class="hl-code"> + </span><span class="hl-identifier">im</span><span class="hl-code">.</span><span class="hl-identifier">getpixel</span><span class="hl-brackets">((</span><span class="hl-number">1</span><span class="hl-code">,</span><span class="hl-number">2</span><span class="hl-brackets">))</span><span class="hl-code"> \ + </span><span class="hl-identifier">im</span><span class="hl-code">.</span><span class="hl-identifier">getpixel</span><span class="hl-brackets">((</span><span class="hl-number">2</span><span class="hl-code">,</span><span class="hl-number">0</span><span class="hl-brackets">))</span><span class="hl-code"> + </span><span class="hl-identifier">im</span><span class="hl-code">.</span><span class="hl-identifier">getpixel</span><span class="hl-brackets">((</span><span class="hl-number">2</span><span class="hl-code">,</span><span class="hl-number">1</span><span class="hl-brackets">))</span><span class="hl-code"> + </span><span class="hl-identifier">im</span><span class="hl-code">.</span><span class="hl-identifier">getpixel</span><span class="hl-brackets">((</span><span class="hl-number">2</span><span class="hl-code">,</span><span class="hl-number">2</span><span class="hl-brackets">))</span><span class="hl-code"> </span><span class="hl-comment"># This is the compensation, for most of the images it's 0 or very few, but for darker images, it's more</span><span class="hl-code"> </span><span class="hl-identifier">avg9px</span><span class="hl-code"> = </span><span class="hl-number">255</span><span class="hl-code">-</span><span class="hl-identifier">first9px</span><span class="hl-code">/</span><span class="hl-number">9</span><span class="hl-code"> </span><span class="hl-identifier">num</span><span class="hl-code"> = </span><span class="hl-quotes">'</span><span class="hl-string">{}{}{}.{}</span><span class="hl-quotes">'</span><span class="hl-code">.</span><span class="hl-identifier">format</span><span class="hl-brackets">(</span><span class="hl-code"> </span><span class="hl-quotes">'</span><span class="hl-string">-</span><span class="hl-quotes">'</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-identifier">read_segment</span><span class="hl-brackets">(</span><span class="hl-identifier">im</span><span class="hl-code">, </span><span class="hl-brackets">[(</span><span class="hl-number">2</span><span class="hl-code">,</span><span class="hl-number">6</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">3</span><span class="hl-code">,</span><span class="hl-number">6</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">(</span><span class="hl-number">4</span><span class="hl-code">,</span><span class="hl-number">6</span><span class="hl-brackets">)]</span><span class="hl-code">, </span><span class="hl-identifier">tSIGN</span><span class="hl-code">-</span><span class="hl-identifier">avg9px</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-reserved">else</span><span class="hl-code"> </span><span class="hl-quotes">'</span><span class="hl-string">+</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-identifier">read_digit</span><span class="hl-brackets">(</span><span class="hl-identifier">im</span><span class="hl-code">, </span><span class="hl-identifier">d1_sA</span><span class="hl-code">, </span><span class="hl-identifier">d1_sB</span><span class="hl-code">, </span><span class="hl-identifier">d1_sC</span><span class="hl-code">, </span><span class="hl-identifier">d1_sE</span><span class="hl-code">, </span><span class="hl-identifier">d1_sF</span><span class="hl-code">, </span><span class="hl-identifier">d1_sG</span><span class="hl-code">, </span><span class="hl-identifier">avg9px</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-identifier">read_digit</span><span class="hl-brackets">(</span><span class="hl-identifier">im</span><span class="hl-code">, </span><span class="hl-identifier">d2_sA</span><span class="hl-code">, </span><span class="hl-identifier">d2_sB</span><span class="hl-code">, </span><span class="hl-identifier">d2_sC</span><span class="hl-code">, </span><span class="hl-identifier">d2_sE</span><span class="hl-code">, </span><span class="hl-identifier">d2_sF</span><span class="hl-code">, </span><span class="hl-identifier">d2_sG</span><span class="hl-code">, </span><span class="hl-identifier">avg9px</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-identifier">read_digit</span><span class="hl-brackets">(</span><span class="hl-identifier">im</span><span class="hl-code">, </span><span class="hl-identifier">d3_sA</span><span class="hl-code">, </span><span class="hl-identifier">d3_sB</span><span class="hl-code">, </span><span class="hl-identifier">d3_sC</span><span class="hl-code">, </span><span class="hl-identifier">d3_sE</span><span class="hl-code">, </span><span class="hl-identifier">d3_sF</span><span class="hl-code">, </span><span class="hl-identifier">d3_sG</span><span class="hl-code">, </span><span class="hl-identifier">avg9px</span><span class="hl-brackets">)</span><span class="hl-code">, </span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-quotes">'</span><span class="hl-string">None</span><span class="hl-quotes">'</span><span class="hl-code"> </span><span class="hl-reserved">not</span><span class="hl-code"> </span><span class="hl-reserved">in</span><span class="hl-code"> </span><span class="hl-identifier">num</span><span class="hl-code">: </span><span class="hl-reserved">print</span><span class="hl-code"> </span><span class="hl-identifier">get_date</span><span class="hl-brackets">(</span><span class="hl-identifier">file_in</span><span class="hl-brackets">)</span><span class="hl-code"> + </span><span class="hl-quotes">'</span><span class="hl-special">\t</span><span class="hl-quotes">'</span><span class="hl-code"> + </span><span class="hl-identifier">num</span><span class="hl-code"> </span><span class="hl-comment"># If there's a second argument to the script passed, show the original image for comparison</span><span class="hl-code"> </span><span class="hl-reserved">if</span><span class="hl-code"> </span><span class="hl-builtin">len</span><span class="hl-brackets">(</span><span class="hl-identifier">sys</span><span class="hl-code">.</span><span class="hl-identifier">argv</span><span class="hl-brackets">)</span><span class="hl-code"> &gt; </span><span class="hl-number">2</span><span class="hl-code">: </span><span class="hl-identifier">Image</span><span class="hl-code">.</span><span class="hl-builtin">open</span><span class="hl-brackets">(</span><span class="hl-identifier">file_in</span><span class="hl-brackets">)</span><span class="hl-code">.</span><span class="hl-identifier">show</span><span class="hl-brackets">()</span></pre></div> </div> <p>Even though this script is so simple, after tweaking the thresholds, most of the files were recognized correctly, those that weren't had one or more non-recognized digits, so they were easy to filter out. For over 1-day worth of images, only 2 or 3 minutes had a missing reading.</p> <p>I loaded the data to LibreOffice and generated this pretty graph:</p> <img src="http://piotrgabryjeluk.wdfiles.com/local--files/blog:monitoring-freezer-temperature/graph.jpg" style="width: 100%" alt="graph.jpg" class="image" /> <h1><span>Timelapse video</span></h1> <p>Another approach visualizing the data was to create a video.</p> <p>The plan:</p> <ul> <li>Annotate the images with the recorded time</li> <li>Compose the video from single frames, putting 60 frames per a second of the resulting video</li> </ul> <p>60 frames a second with roughly 2 frames captured a minutes means a day of recording is compressed to:</p> <div class="code"> <pre><code>2 frames a minute * 60 minutes an hour * 24 hours a day = 2880 frames 2880 frames / 60 frames a second = 48 seconds</code></pre></div> <p>This makes is &quot;viewable&quot;. 60 FPS (versus 30 FPS at higher speed) means you can pause at any time and read the crisp time and temperature.</p> <p>Here's the annotate part:</p> <div class="code"> <div class="hl-main"> <pre><span class="hl-comment">#!/usr/bin/env python</span><span class="hl-code"> </span><span class="hl-reserved">import</span><span class="hl-code"> </span><span class="hl-identifier">sys</span><span class="hl-code"> </span><span class="hl-reserved">import</span><span class="hl-code"> </span><span class="hl-identifier">subprocess</span><span class="hl-code"> </span><span class="hl-identifier">path_in</span><span class="hl-code"> = </span><span class="hl-identifier">sys</span><span class="hl-code">.</span><span class="hl-identifier">argv</span><span class="hl-brackets">[</span><span class="hl-number">1</span><span class="hl-brackets">]</span><span class="hl-code"> </span><span class="hl-identifier">path_out</span><span class="hl-code"> = </span><span class="hl-identifier">sys</span><span class="hl-code">.</span><span class="hl-identifier">argv</span><span class="hl-brackets">[</span><span class="hl-number">2</span><span class="hl-brackets">]</span><span class="hl-code"> </span><span class="hl-identifier">date</span><span class="hl-code">, </span><span class="hl-identifier">time</span><span class="hl-code"> = </span><span class="hl-identifier">path_in</span><span class="hl-code">.</span><span class="hl-identifier">replace</span><span class="hl-brackets">(</span><span class="hl-quotes">'</span><span class="hl-string">.png</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">''</span><span class="hl-brackets">)</span><span class="hl-code">.</span><span class="hl-identifier">split</span><span class="hl-brackets">(</span><span class="hl-quotes">'</span><span class="hl-string">/</span><span class="hl-quotes">'</span><span class="hl-brackets">)[</span><span class="hl-code">-</span><span class="hl-number">1</span><span class="hl-brackets">]</span><span class="hl-code">.</span><span class="hl-identifier">split</span><span class="hl-brackets">(</span><span class="hl-quotes">'</span><span class="hl-string">-</span><span class="hl-quotes">'</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-identifier">D1</span><span class="hl-code">, </span><span class="hl-identifier">D2</span><span class="hl-code">, </span><span class="hl-identifier">M1</span><span class="hl-code">, </span><span class="hl-identifier">M2</span><span class="hl-code">, </span><span class="hl-identifier">Y1</span><span class="hl-code">, </span><span class="hl-identifier">Y2</span><span class="hl-code">, </span><span class="hl-identifier">Y3</span><span class="hl-code">, </span><span class="hl-identifier">Y4</span><span class="hl-code"> = </span><span class="hl-identifier">date</span><span class="hl-code"> </span><span class="hl-identifier">h1</span><span class="hl-code">, </span><span class="hl-identifier">h2</span><span class="hl-code">, </span><span class="hl-identifier">m1</span><span class="hl-code">, </span><span class="hl-identifier">m2</span><span class="hl-code">, </span><span class="hl-identifier">s1</span><span class="hl-code">, </span><span class="hl-identifier">s2</span><span class="hl-code"> = </span><span class="hl-identifier">time</span><span class="hl-code"> </span><span class="hl-identifier">label</span><span class="hl-code"> = </span><span class="hl-quotes">'</span><span class="hl-string">{}{}/{}{}/{}{}{}{} {}{}:{}{}:{}{}</span><span class="hl-special">\\</span><span class="hl-string">n</span><span class="hl-quotes">'</span><span class="hl-code">.</span><span class="hl-identifier">format</span><span class="hl-brackets">(</span><span class="hl-identifier">M1</span><span class="hl-code">, </span><span class="hl-identifier">M2</span><span class="hl-code">, </span><span class="hl-identifier">D1</span><span class="hl-code">, </span><span class="hl-identifier">D2</span><span class="hl-code">, </span><span class="hl-identifier">Y1</span><span class="hl-code">, </span><span class="hl-identifier">Y2</span><span class="hl-code">, </span><span class="hl-identifier">Y3</span><span class="hl-code">, </span><span class="hl-identifier">Y4</span><span class="hl-code">, </span><span class="hl-identifier">h1</span><span class="hl-code">, </span><span class="hl-identifier">h2</span><span class="hl-code">, </span><span class="hl-identifier">m1</span><span class="hl-code">, </span><span class="hl-identifier">m2</span><span class="hl-code">, </span><span class="hl-identifier">s1</span><span class="hl-code">, </span><span class="hl-identifier">s2</span><span class="hl-brackets">)</span><span class="hl-code"> </span><span class="hl-identifier">subprocess</span><span class="hl-code">.</span><span class="hl-identifier">check_call</span><span class="hl-brackets">([</span><span class="hl-code"> </span><span class="hl-quotes">'</span><span class="hl-string">convert</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-identifier">path_in</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">-gravity</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">south</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">-pointsize</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">45</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">-font</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">FreeMono</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">-annotate</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">0</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-identifier">label</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">-fill</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-quotes">'</span><span class="hl-string">black</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-identifier">path_out</span><span class="hl-code"> </span><span class="hl-brackets">])</span></pre></div> </div> <p>Here's the result:</p> <img src="http://piotrgabryjeluk.wdfiles.com/local--files/blog:monitoring-freezer-temperature/annotated.png" alt="annotated.png" class="image" /> <p>Running this in a loop, 16 images at a time:</p> <div class="code"> <pre><code>#!/bin/bash i=0 for file_in in dell*/*.png; do file_out=&quot;`printf &quot;labeled/%06d.png&quot; $i`&quot; echo ./add-labels.py &quot;$file_in&quot; &quot;$file_out&quot; i=$((i+1)) done | parallel -j 16</code></pre></div> <p>In addition to annotatig the image it also names them as 000001.png, 000002.png etc, which makes it easy for <tt>avconv</tt> to convert them to a video:</p> <div class="code"> <pre><code>avconv -fflags +genpts -r 60 -i labeled/%06d.png -r 60 temperature.mkv</code></pre></div> <p>And here's the video:</p> <p><iframe width="640" height="480" src="https://www.youtube.com/embed/DL9_sbdHlhU" frameborder="0" allowfullscreen="allowfullscreen"></iframe></p> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/gabrys" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=2462&amp;amp;size=small&amp;amp;timestamp=1779324991" alt="Gabrys" style="background-image:url(http://www.wikidot.com/userkarma.php?u=2462)" /></a><a href="http://www.wikidot.com/user:info/gabrys" >Gabrys</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://piotrgabryjeluk.wikidot.com/blog:pushing-a-http-stream-to-roku</guid>
				<title>Pushing a HTTP Stream To Roku</title>
				<link>http://piotrgabryjeluk.wikidot.com/blog:pushing-a-http-stream-to-roku</link>
				<description>

&lt;p&gt;After a bit of traffic capturing, I managed to find out how to make Roku play an HTTP stream by URL.&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=2462&amp;amp;amp;size=small&amp;amp;amp;timestamp=1779324991&quot; alt=&quot;Gabrys&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=2462)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;Gabrys&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Sun, 18 Sep 2016 23:11:43 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>After a bit of traffic capturing, I managed to find out how to make Roku play an HTTP stream by URL.</p> <p>It seems a Roku device (Roku TV in my case) hosts an HTTP server which is exposed on port 8060.</p> <p>There's a series of MDNS requests to determine the available player in the network, but we can skip that since I assume you know the IP address of your Roku. After the device (a phone in my case) identified the target player, it sends an HTTP request:</p> <div class="code"> <pre><code>GET http://your-roku-address:8060/query/device-info</code></pre></div> <p>You get a nice XML document in return that lists some properties like this:</p> <div class="code"> <pre><code>&lt;device-info&gt; &lt;udn&gt;...&lt;/udn&gt; &lt;serial-number&gt;...&lt;/serial-number&gt; &lt;device-id&gt;...&lt;/device-id&gt; &lt;advertising-id&gt;...&lt;/advertising-id&gt; &lt;vendor-name&gt;Hisense&lt;/vendor-name&gt; &lt;model-name&gt;Hisense 40H4&lt;/model-name&gt; &lt;model-number&gt;5203X&lt;/model-number&gt; &lt;model-region&gt;US&lt;/model-region&gt; &lt;screen-size&gt;40&lt;/screen-size&gt; &lt;wifi-mac&gt;...&lt;/wifi-mac&gt; &lt;network-type&gt;wifi&lt;/network-type&gt; &lt;user-device-name/&gt; &lt;software-version&gt;7.2.0&lt;/software-version&gt; &lt;software-build&gt;4143&lt;/software-build&gt; &lt;secure-device&gt;true&lt;/secure-device&gt; &lt;language&gt;en&lt;/language&gt; &lt;country&gt;US&lt;/country&gt; &lt;locale&gt;en_US&lt;/locale&gt; &lt;time-zone&gt;US/Pacific&lt;/time-zone&gt; &lt;time-zone-offset&gt;-420&lt;/time-zone-offset&gt; &lt;power-mode&gt;PowerOn&lt;/power-mode&gt; &lt;supports-suspend&gt;true&lt;/supports-suspend&gt; &lt;developer-enabled&gt;true&lt;/developer-enabled&gt; &lt;keyed-developer-id/&gt; &lt;search-enabled&gt;true&lt;/search-enabled&gt; &lt;voice-search-enabled&gt;true&lt;/voice-search-enabled&gt; &lt;notifications-enabled&gt;true&lt;/notifications-enabled&gt; &lt;notifications-first-use&gt;false&lt;/notifications-first-use&gt; &lt;headphones-connected&gt;true&lt;/headphones-connected&gt; &lt;expert-pq-enabled&gt;0.5&lt;/expert-pq-enabled&gt; &lt;/device-info&gt;</code></pre></div> <p>You can see for example my device is Hisense 40H4 and it's a secure device.</p> <p>This is interesting, but this doesn't cause anything to play.</p> <p>Here's the part that gets Roku to play something:</p> <div class="code"> <pre><code>POST http://your-roku-address:8060/input/15985?t=v&amp;u=http%3A%2F%2F192.168.1.108%3A8000%2Fstream.m3u8&amp;k=(null)&amp;videoName=192.168.1.108%3A8000%2Fstream.m3u8&amp;videoFormat=hls</code></pre></div> <p>That's it, you pass the m3u8 URI as u param (need to URL encode it first) and Roku starts playing it. Note the HTTP method used in POST, but the payload is empty.</p> <p>I'm not sure what's the meaning of 15985 in the URL, maybe it's the ID of the PlayOnRoku video source.</p> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/gabrys" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=2462&amp;amp;size=small&amp;amp;timestamp=1779324991" alt="Gabrys" style="background-image:url(http://www.wikidot.com/userkarma.php?u=2462)" /></a><a href="http://www.wikidot.com/user:info/gabrys" >Gabrys</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://piotrgabryjeluk.wikidot.com/blog:my-computer-setup-hardware</guid>
				<title>My Computer Setup: Hardware</title>
				<link>http://piotrgabryjeluk.wikidot.com/blog:my-computer-setup-hardware</link>
				<description>

&lt;p&gt;I believe you should use the tools that suit you. As a software developer, my computer is my toolbox. And I wanted to share what it is.&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=2462&amp;amp;amp;size=small&amp;amp;amp;timestamp=1779324991&quot; alt=&quot;Gabrys&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=2462)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;Gabrys&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Wed, 22 Jun 2016 01:40:51 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>I believe you should use the tools that suit you. As a software developer, my computer is my toolbox. And I wanted to share what it is.</p> <p>While writing this post I realized how much I want not only to list my setup but also explain what are the reasons for each element of it.</p> <p>This makes it not suitable for one post. That's why it's going to be a few separate blog posts on each of the parts.</p> <p>Today we start with&#8230;</p> <h1><span>Hardware</span></h1> <p>My current computer is a one supplied by my company &#8212; Wikia. It's Dell Latitude E6430s. Previously I also used an older version of Dell Latitude, both are very similar-looking and built around the same platform.</p> <div class="image-container aligncenter"><a href="http://piotrgabryjeluk.wdfiles.com/local--files/blog:my-computer-setup-hardware/dell-latitude-e6420_g.jpg"><img src="http://piotrgabryjeluk.wdfiles.com/local--resized-images/blog:my-computer-setup-hardware/dell-latitude-e6420_g.jpg/medium.jpg" alt="dell-latitude-e6420_g.jpg" class="image" /></a></div> <p>(My previous laptop)</p> <div class="image-container aligncenter"><a href="http://piotrgabryjeluk.wdfiles.com/local--files/blog:my-computer-setup-hardware/dell_e6430sHH.jpg"><img src="http://piotrgabryjeluk.wdfiles.com/local--resized-images/blog:my-computer-setup-hardware/dell_e6430sHH.jpg/medium.jpg" alt="dell_e6430sHH.jpg" class="image" /></a></div> <p>(My current one)</p> <h2><span>Intel-based</span></h2> <p>The computer is based on Intel hardware: Intel CPU, Intel Ethernet and Wi-Fi cards, Intel graphics. The hardware is very nicely supported by Linux, which will be covered in the next post.</p> <h2><span>Docking station</span></h2> <p>I'm a big fan of docking stations: you just put your laptop on it and you don't need to play with any cables whatsoever. The laptop gets power from it and you can connect a few devices through it all by placing the laptop in the correct spot.</p> <h2><span>Screens</span></h2> <p>I used to have two external screens, but now I only have one &#8212; a bigger one, though. The main difference between my old and new laptop from my standpoint was the number of simultaneously supported screens. Previously the graphic adapter could only support 2, the new model supports 3.</p> <p>With the old model, it was very tricky to script the computer in a way that would switch from displaying the contents just on the laptop to displaying it on two external screens. You needed to do that in stages: first, activate one external screen, then disable the laptop screen, and finally activate the other screen. I did finally craft the script that worked, that it required some time.</p> <p>With the new model, the regular tools for screen management (based on XRandr) works flawlessly whether you want to use internal, internal + 1 external, 2 external or internal + 2 external screens and whatever the transitions you want, it'll just work.</p> <h2><span>Keyboard</span></h2> <p>When I joined Wikia, my first project was rewriting the ad engine. That required a lot of coding and my hands started to be in pain. I asked for an ergonomic keyboard and got one. The keyboard I used was a Microsoft Natural 4000. I'm not an expert on keyboards, but I must say my pain was gone and I never wanted to type on a non-ergonomic keyboard again.</p> <div class="image-container aligncenter"><a href="http://piotrgabryjeluk.wdfiles.com/local--files/blog:my-computer-setup-hardware/ms-natural-4000-keyboard.jpg"><img src="http://piotrgabryjeluk.wdfiles.com/local--resized-images/blog:my-computer-setup-hardware/ms-natural-4000-keyboard.jpg/medium.jpg" alt="ms-natural-4000-keyboard.jpg" class="image" /></a></div> <p>When I moved to the States, my keyboard was left in Poland, so I asked for another ergonomic keyboard and got a Microsoft keyboard again. This time, it was a different model: Microsoft L5V-00001. The keyboard took some time to get used to, but as before my hands don't hurt.</p> <div class="image-container aligncenter"><a href="http://piotrgabryjeluk.wdfiles.com/local--files/blog:my-computer-setup-hardware/Microsoft-L5V-00001.jpg"><img src="http://piotrgabryjeluk.wdfiles.com/local--resized-images/blog:my-computer-setup-hardware/Microsoft-L5V-00001.jpg/medium.jpg" alt="Microsoft-L5V-00001.jpg" class="image" /></a></div> <p>I want to say one thing here: I don't think ergonomic keyboard (or mouse for that matter) makes you type faster &#8212; your body can adjust to using almost any sensible tool at comparable speeds &#8212; but it does help you type without pain. As I spend a good part of the day typing, this is important.</p> <h2><span>Mouse</span></h2> <p>As for the mouse, almost anything goes, I used wired, Bluetooth and proprietary-wireless-USB mouses. Also the laptop touchpads. Dells are equipped with track point devices. I don't like using them. I like the fact you get a dedicated middle button with it, I use it way more often that most of the people.</p> <p>One thing that I absolutely need my mouse-like device to give me is a sane scroll and the middle button I mentioned before. My Bluetooth mouse has the scroll broken &#8212; when scrolling down, it sometimes scrolls up &#8212; and this is very very annoying for me.</p> <p>Summing up: I don't use the mouse that often, mostly to scroll content, so give me anything that allows me to scroll, and I'm happy.</p> <h2><span>Extras</span></h2> <p>The laptop has a removable big capacity battery, SD card reader, USB3, and eSATA. It features an extension bay which by default is occupied by a DVD-writer. I have a 500GB placed in there with the original Windows installation moved to it, so I can both boot to it and start it in VirtualBox.</p> <p>The very annoying part of the laptop is the HDMI output, which is realized through a mini-HDMI port. The port is not very solid and after using it just a few times it stopped working (mechanically, it was later replaced by Dell support). You also need the adapter which you normally don't carry on you.</p> <h2><span>Seating arrangement</span></h2> <p>Again, because I spent a good part of the day working on a computer it is important for me to seat in a position that my body can handle. There are some resources online to help you arrange your seat, your desk, your keyboard and your screen in a way that is optimal, so I'm not going to go through that, but here's what I needed to do:</p> <ul> <li>As the desks in the office don't offer height alignment I ordered a monitor stand and I'm having my keyboard sit on top of it. This makes up for the fact my desk is too low for me. I keep my mouse on it too. There's no place for my num pad, but that's OK.</li> <li>With my keyboard already risen, you can expect my screen needs to be placed high as well. Even with quite wide height-alignment range of the screen, it's not enough, I placed the screen on a bunch of Amazon boxes.</li> <li>What works one day, doesn't work on the other. Every few days I adjust the screen and the seat to be higher or lower just a tad, just to change the position a little bit and to not cause any Repetitive Strain Injuries (well, not really, but I guess you know what I mean).</li> </ul> <div class="image-container aligncenter"><a href="http://piotrgabryjeluk.wdfiles.com/local--files/blog:my-computer-setup-hardware/monitor-stand.jpg"><img src="http://piotrgabryjeluk.wdfiles.com/local--resized-images/blog:my-computer-setup-hardware/monitor-stand.jpg/medium.jpg" alt="monitor-stand.jpg" class="image" /></a></div> <h2><span>Home setup</span></h2> <p>Whenever I'm not at work and I use my laptop, I use it completely bare: no external screen, no ergonomic keyboard, no optimized seating position, usually no AC cord. The battery, when fully charged, allows for anywhere between 3 and 6 hours of work/play and that's more than enough I need to use my computer outside the office.</p> <h1><span>Next time</span></h1> <p>The next posts will be dedicated to the operating system.</p> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/gabrys" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=2462&amp;amp;size=small&amp;amp;timestamp=1779324991" alt="Gabrys" style="background-image:url(http://www.wikidot.com/userkarma.php?u=2462)" /></a><a href="http://www.wikidot.com/user:info/gabrys" >Gabrys</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://piotrgabryjeluk.wikidot.com/blog:goodbye-pieter</guid>
				<title>Goodbye Pieter</title>
				<link>http://piotrgabryjeluk.wikidot.com/blog:goodbye-pieter</link>
				<description>

&lt;p&gt;Pieter Hintjens says goodbye: &lt;a href=&quot;http://hintjens.com/blog:115&quot;&gt;http://hintjens.com/blog:115&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=2462&amp;amp;amp;size=small&amp;amp;amp;timestamp=1779324991&quot; alt=&quot;Gabrys&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=2462)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;Gabrys&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Fri, 22 Apr 2016 18:44:48 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>Pieter Hintjens says goodbye: <a href="http://hintjens.com/blog:115">http://hintjens.com/blog:115</a></p> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/gabrys" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=2462&amp;amp;size=small&amp;amp;timestamp=1779324991" alt="Gabrys" style="background-image:url(http://www.wikidot.com/userkarma.php?u=2462)" /></a><a href="http://www.wikidot.com/user:info/gabrys" >Gabrys</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://piotrgabryjeluk.wikidot.com/blog:glupia-nawigacja-w-mazdzie-6</guid>
				<title>Głupia Nawigacja w Mazdzie 6</title>
				<link>http://piotrgabryjeluk.wikidot.com/blog:glupia-nawigacja-w-mazdzie-6</link>
				<description>

&lt;p&gt;Gdy kupowaliśmy naszą Mazdę, pracownik dilera nie mógł przestać zachwalać systemu &amp;quot;infotainmentu&amp;quot;, który Mazda posiada. W mojej ocenie system jest w porządku, ale szału nie robi.&lt;/p&gt;
&lt;p&gt;Ogólnie moja opinia na temat samochodów i ich ekranów multimedialnych, jest taka, że dla wszystkich byłoby dużo lepiej, gdyby producenci samochodów przestali się tym w ogóle zajmować, tylko dali jakąś dobrą integrację z tabletem, który można byłoby sobie wsadzić w odpowiedni slot w samochodzie.&lt;/p&gt;
&lt;p&gt;Ale do rzeczy. Dlaczego system w aucie, który kupiliśmy jest według mnie taki słaby?&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=2462&amp;amp;amp;size=small&amp;amp;amp;timestamp=1779324991&quot; alt=&quot;Gabrys&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=2462)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;Gabrys&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Sat, 13 Feb 2016 21:14:30 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>Gdy kupowaliśmy naszą Mazdę, pracownik dilera nie mógł przestać zachwalać systemu &quot;infotainmentu&quot;, który Mazda posiada. W mojej ocenie system jest w porządku, ale szału nie robi.</p> <p>Ogólnie moja opinia na temat samochodów i ich ekranów multimedialnych, jest taka, że dla wszystkich byłoby dużo lepiej, gdyby producenci samochodów przestali się tym w ogóle zajmować, tylko dali jakąś dobrą integrację z tabletem, który można byłoby sobie wsadzić w odpowiedni slot w samochodzie.</p> <p>Ale do rzeczy. Dlaczego system w aucie, który kupiliśmy jest według mnie taki słaby?</p> <div class="content-separator" style="display: none:"></div> <p>Po pierwsze <strong>sposób w jaki startuje</strong>. Nawigacja i reszta bajerów (radio, odtwarzacz MP3 itd) uruchamia się dopiero po &quot;przekręceniu kluczyka&quot;. Uruchomienie systemu trwa około minutę, więc nici z szybkiego ustawienia nawigacji czy wyboru stacji przed ruszeniem w podróż.</p> <p>System mógłby już zacząć się uruchamiać gdy otwieramy drzwi a nawet gdy kluczyk zbliża się do auta (mamy czujnik bliskości), wtedy długi czas uruchamiania systemu (o ile nie można go sensownie skrócić) nie byłby taki straszny, bo proces miałby miejsce zanim wsiądziemy do auta.</p> <p>Po drugie <strong>brak możliwości sterowania nawigacją w czasie jazdy</strong>. Gdy przekraczamy około 5 mil na godzinę nawigacja przechodzi w tryb ograniczonego sterowania: niemożliwe jest wpisywanie adresu czy nazwy pożądanego punktu, a jeśli nazwę już wpisaliśmy w czasie, gdy auto się toczyło: niemożliwe jest zatwierdzenie wpisanej nazwy.</p> <p>Są dostępne tylko niektóre opcje, wybrane chyba zupełnie losowo, bo o logice ciężko w tej sytuacji rozmawiać. Auto nie jest zainteresowane kto obsługuje nawigację. Niezależnie od tego, czy następny punkt podróży chce wpisać kierowca czy pasażer &quot;z powodów bezpieczeństwa&quot; jest to niemożliwe.</p> <p>W sytuacji gdy jedziemy autostradą i w wyniku zmiany planów (np. ktoś się źle poczuł i należy podjechać po drodze do apteki) należy zatrzymać auto (albo zwolnić do około 5 mph) i dopiero wtedy możliwe jest ustawienie następnego punktu podróży.</p> <p>Jeśli w Mazdzie nazywa się to bezpieczeństwem (zatrzymywanie auta na autostradzie), to jest po prostu głupia (tak jak i ich nawigacja).</p> <p>Po konsultacji na forum Mazdy6 w Polsce dowiedziałem się, że zabezpieczenie, o którym piszę wcale nie występuje w Polskich samochodach. Bardzo mnie to zdziwiło, bo jeżeli to kwestia bezpieczeństwa, to chyba powinno to działać tak samo we wszystkich krajach? Dla dociekliwych, to też nie kwestia regulacji prawnych w stanach, bo inne marki samochodów nie utrudniają w ten sposób życia swoim kierowcom.</p> <p>Jak zwykle w takich sytuacjach zwróciłem się do Mazdy z pytaniem jak to naprawić.</p> <p>Niestety nie mam zapisanego mojego pytania, ale dotyczyło ono dlaczego niemożliwe jest w aucie sterowanie nawigacją (nawet przez pasażera) w czasie jazdy. Oto odpowiedź:</p> <blockquote> <p>Dear Piotr Gabryjeluk,</p> <p>Good Morning</p> <p>Apologies that you are unhappy with our navigation system , to answer your question about operating the navigation while the vehicle is in motion , for safety precautions it could be a distraction to operate while in the vehicle is in motion. For the other issues with the navigation if it is not working as normal I suggest taking the vehicle into a local Mazda dealer to inspect your concern.</p> <p>Thank you for contacting Mazda Customer Experience Center.</p> <p>If you have any questions in the future, you can reach me directly using the number and extension below.</p> <p>Sincerely,</p> <p>William</p> <p>Representative, Customer Experience</p> </blockquote> <p>Nie można takiej odpowiedzi pozostawić bez odzewu, więc zadałem kolejne pytanie w nawiązaniu do tej odpowiedzi:</p> <blockquote> <p>Dear William,</p> <p>Could you please tell me how exactly operating the navigation system by a passenger is a distraction?</p> <p>Thank you very much,<br /> Piotr Gabryjeluk</p> </blockquote> <p>Po ośmiu dniach nie dostałem żadnej odpowiedzi, więc zapytałem:</p> <blockquote> <p>Hi there,</p> <p>Am I going to get the response from William?</p> <p>My issue is definitely NOT SOLVED!</p> <p>Thanks,<br /> Piotr Gabryjeluk</p> </blockquote> <p>Odpowiedź:</p> <blockquote> <p>Dear Piotr Gabryjeluk,</p> <p>Good Morning Apologies but it looks like I did supply the answer for you in regards why your not able to use the navigation while vehicle is in motion.</p> <p>Thank you for contacting Mazda Customer Experience Center.</p> <p>If you have any questions in the future, you can reach me directly using the number and extension below.</p> <p>Sincerely,<br /> William<br /> Representative, Customer Experience</p> </blockquote> <p>Moja odpowiedź:</p> <blockquote> <p>Dear William,</p> <p>You claimed that my navigation system cannot be operated by the passenger, because it is a security threat. I asked you why is that a security issue. You did not answer to that. Please answer that question.</p> <p>Thank you,<br /> Piotr Gabryjeluk</p> </blockquote> <p>Brak odpowiedzi. Nikt się nie przejmuje. Po przeszukaniu Internetu mam wrażenie, że nie tylko ja mam ten problem i wszyscy są jednakowo <strong>ignorowani przez Mazdę</strong>.</p> <p><strong>Jak to naprawić?</strong></p> <p>Skoro Mazda ma w dupie wygodę klientów, może jest jakiś sposób na naprawę problemu? Wygląda na to, że jest to możliwe. Na stronie forum Mazdy6: <a href="http://forum.mazda6club.com/car-electronics/351338-infotainment-hacks.html">http://forum.mazda6club.com/car-electronics/351338-infotainment-hacks.html</a> znalazłem informację o tym, że problem może być rozwiązany przez zalogowanie się przez ssh do samochodu i wyłączenie flagi.</p> <p>Tylko jak się zalogować? Okazuje się, że wystarczy podpiąć kartę Ethernetową do złącza USB w aucie, a auto pobierze adres IP przez DHCP, następne pod tym adresem na standardowym porcie SSH należy się zalogować na roota (hasło jci), przemontować system plików w tryb read-write <tt>mount -o rw,remount /</tt> a następnie wyedytować skrypt <tt>/jci/scripts/set_lvds_speed_restriction_config.sh</tt> wykomentowując linię zawierającą <tt>enable_speed_restriction</tt>.</p> <p><strong>Co z tego wynika?</strong></p> <p>Jeżeli to prawda (jeszcze tego nie sprawdzałem), to znaczy, że Mazda mając techniczną możliwość zdjęcia &quot;zabezpieczenia&quot; (które zresztą jest włączone tylko w niektórych krajach) odmawia tego klientom powołując się na kompletnie bezsensowne argumenty (że jest to podobno kwestia bezpieczeństwa). Dodatkowo obsługa klienta Mazdy nie odpowiada na pytania i ignoruje klientów.</p> <p>Jednocześnie, zgodnie z opiniami Mazdofili, wychodzi na to, że Mazda postawiła na sprawdzone rozwiązanie (wygląda na to, że pod &quot;maską&quot; systemu infotainmentu mamy dość standardowego Linuxa) co powinno się przełożyć na niezawodność systemu.</p> <p>Kwestię umożliwienia logowania na konto roota i trzyliterowe hasło zostawiam bez komentarza. Auto nie jest standardowo podłączone z Internetem i wymagany jest fizyczny dostęp do samochodu, żeby się dostać do systemu. Zakładam, że takie &quot;standardowe&quot; hasło i logowanie bezpośrednio na konto roota ułatwia pracę serwisantom, więc nie widzę w tym dużego zagrożenia.</p> <h2><span>Linki</span></h2> <ul> <li><a href="http://forum.mazda6club.com/car-electronics/351338-infotainment-hacks.html">http://forum.mazda6club.com/car-electronics/351338-infotainment-hacks.html</a></li> <li><a href="https://github.com/mazdahacks/tweaks">https://github.com/mazdahacks/tweaks</a></li> <li><a href="http://mazda3revolution.com/forums/2014-2016-mazda-3-skyactiv-audio-electronics/104730-index-infotainment-project.html">http://mazda3revolution.com/forums/2014-2016-mazda-3-skyactiv-audio-electronics/104730-index-infotainment-project.html</a></li> <li><a href="http://openmzdc.wikia.com/">http://openmzdc.wikia.com/</a></li> <li><a href="http://www.lukasz-skalski.com/portfolio/mazda-media-player/">http://www.lukasz-skalski.com/portfolio/mazda-media-player/</a> (klonowanie obrazu z Androida na wyświetlacz Mazdy)</li> </ul> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/gabrys" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=2462&amp;amp;size=small&amp;amp;timestamp=1779324991" alt="Gabrys" style="background-image:url(http://www.wikidot.com/userkarma.php?u=2462)" /></a><a href="http://www.wikidot.com/user:info/gabrys" >Gabrys</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://piotrgabryjeluk.wikidot.com/blog:converting-mp4-with-subs-for-roku</guid>
				<title>Converting MP4 with subtitles for Roku</title>
				<link>http://piotrgabryjeluk.wikidot.com/blog:converting-mp4-with-subs-for-roku</link>
				<description>

&lt;p&gt;I recently bought a HiSense Roku TV and it&#039;s awesome (I&#039;ve never had a Roku device before).&lt;/p&gt;
&lt;p&gt;The problem is that even though the TV has an USB port and Roku has a &amp;quot;Roku Media Player&amp;quot; channel that allows you plan video and audio files from the USB disk, not all formats are accepted.&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=2462&amp;amp;amp;size=small&amp;amp;amp;timestamp=1779324991&quot; alt=&quot;Gabrys&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=2462)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;Gabrys&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Wed, 28 Oct 2015 06:37:49 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>I recently bought a HiSense Roku TV and it's awesome (I've never had a Roku device before).</p> <p>The problem is that even though the TV has an USB port and Roku has a &quot;Roku Media Player&quot; channel that allows you plan video and audio files from the USB disk, not all formats are accepted.</p> <div class="content-separator" style="display: none:"></div> <p>Interestingly Roku has support for subtitles, but the support is quite limited. I found out that one of the options that work nicely is to have the subtitles embedded into the movie itself, given the movie uses Matroska container (.mkv files).</p> <p>On a side note, if the files are not encoded &quot;properly&quot; (Roku only supports a selection of video and audio codecs), you'll need to re-encode the video using ffmpeg or avconv, but how to do it is much simpler to Google than how to deal with the subtitles. In this post I'll only show you how to deal with the subtitles.</p> <p>So let's see what we have:</p> <div class="code"> <pre><code>quake@quake-laptop:~/movies$ ls movie.mp4 movie.txt</code></pre></div> <p>There's a MP4 file and subtitles in a separate file.</p> <div class="code"> <pre><code>quake@quake-laptop:~/movies$ avconv -i movie.mp4 -f microdvd -sub_charenc cp1250 -i movie.txt -c:v copy -c:a copy movie-with-subs.mkv</code></pre></div> <p>Let's look at this command part by part:</p> <ul> <li>avconv &#8212; the tool we're using</li> <li>-i movie.mp4 &#8212; the movie to convert</li> <li>-f microdvd &#8212; format for the subtitles (this part is actually optional)</li> <li>-sub_charenc cp1250 &#8212; the encoding of the subtitles (optional if UTF-8)</li> <li>-i movie.txt &#8212; the subtitles</li> <li>-c:v copy -c:a copy &#8212; copy the audio and video stream (rather than re-encode)</li> <li>movie-with-subs.mkv &#8212; the output file</li> </ul> <p>Which is very nice is this command will not do any re-coding, it will only repackage the movie from MPEG to Matroska container and convert the subtitles. This means there's no quality lost and it only takes a few seconds.</p> <p>As noted above if the file is not playable on Roku (or there's audio missing) you may actually need to transcode the file (omitting or modifying the -c:v copy -c:a copy line).</p> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/gabrys" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=2462&amp;amp;size=small&amp;amp;timestamp=1779324991" alt="Gabrys" style="background-image:url(http://www.wikidot.com/userkarma.php?u=2462)" /></a><a href="http://www.wikidot.com/user:info/gabrys" >Gabrys</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://piotrgabryjeluk.wikidot.com/blog:inea-mistrzowie</guid>
				<title>Inea Mistrzowie</title>
				<link>http://piotrgabryjeluk.wikidot.com/blog:inea-mistrzowie</link>
				<description>

&lt;p&gt;Jak pewnie wiecie, Lech, którego stadion sponsoruje &lt;a href=&quot;http://inea.pl/&quot;&gt;Inea&lt;/a&gt; zdobył tytuł mistrza Polski w piłkę kopaną.&lt;/p&gt;
&lt;p&gt;Ale Inea to nie tylko mistrzowie w piłkę, również mistrzowie czytania ze zrozumieniem.&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=2462&amp;amp;amp;size=small&amp;amp;amp;timestamp=1779324991&quot; alt=&quot;Gabrys&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=2462)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;Gabrys&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Mon, 08 Jun 2015 13:21:29 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>Jak pewnie wiecie, Lech, którego stadion sponsoruje <a href="http://inea.pl/">Inea</a> zdobył tytuł mistrza Polski w piłkę kopaną.</p> <p>Ale Inea to nie tylko mistrzowie w piłkę, również mistrzowie czytania ze zrozumieniem.</p> <div class="content-separator" style="display: none:"></div> <p>Oto moja komunikacja z nimi. Muszę przyznać, że byłem nieco wkurzony podniesieniem ceny Internetu i zwalanie tego na klientów (&quot;odpowiadając na zapotrzebowanie klientów na szybszy Internet podnieśliśmy jego prędkość do 100 Mbit/s, ale żeby zrównoważyć poniesione koszty podnieśliśmy też jego cenę o 5 złotych na miesiąc&quot;):</p> <blockquote> <p>Dzień dobry,</p> <p>Od kilku dni obserwujemy niepokojąco wolno działający Internet. Dzisiaj postawiłem przetestować prędkość korzystając z narzędzi typu speedtest.pl oraz <a href="http://speedtest.inea.pl/">http://speedtest.inea.pl/</a> i uzyskane wyniki oscylowały w granicach 20-50 Mbit/s. <strong>Testy przerowadziłem w odpowiednich warunkach (połączenie po kablu, nieobciążony komputer, brak innych korzystających z Internetu urządzeń).</strong> Ściąganie testowego 1GB pliku z serwerów Inea trwało ponad 3 minuty:</p> <p>user@debian:~$ curl <a href="http://speedtest.inea.pl/1GB.test">http://speedtest.inea.pl/1GB.test</a> &gt; /dev/null<br /> % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed<br /> 100&#160;1024M 100&#160;1024M 0&#160;0&#160;5610k 0&#160;0:03:06&#160;0:03:06 <span style="text-decoration: line-through;">:</span>:&#8212; 5573k</p> <p>Jak widać raportowana prędkość to 5.6*8 ~ 50 Mbit/s. Ściąganie testowego pliku 10&#160;MB z &quot;zewnątrz&quot; sieci Inea:</p> <p>user@debian:~$ curl <a href="http://lastlook.pl/~quake/test10mb.html">http://lastlook.pl/~quake/test10mb.html</a> &gt; /dev/null<br /> % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed<br /> 100&#160;9.9M 100&#160;9.9M 0&#160;0&#160;2262k 0&#160;0:00:04&#160;0:00:04 <span style="text-decoration: line-through;">:</span>:&#8212; 2262k</p> <p>Prędkość jeszcze gorsza: około 20 Mbit/s. Proszę o poprawienie przepustowości do zgodnej z umową (100 Mbit/s).</p> <p>Dziękuję, Piotr Gabryjeluk</p> </blockquote> <p>Odpowiedź Inei:</p> <blockquote> <p>Dotyczy: problemy techniczne<br /> Reklamacja została rozpatrzona przez: Dział Korespondencji i Reklamacji<br /> Podstawa prawna rozstrzygnięcia: § 25 ust. 1 Regulaminu Świadczenia Usług Telekomunikacyjnych<br /> Rozstrzygnięcie reklamacji: odmowa</p> <p>Szanowny Panie,<br /> działając w imieniu INEA S.A. (dalej „Dostawca usług”) z siedzibą w Poznaniu, ul. Klaudyny Potockiej 25, 60-211, adres do korespondencji: Wysogotowo, ul. Wierzbowa 84, 62-081 Przeźmierowo; niniejszym, na podstawie art. 106 ustawy z dnia 16 lipca 2004 roku – Prawo telekomunikacyjne (Dz. U. 2014 poz. 243 – „Ustawa”) w odpowiedzi na reklamację złożoną w dniu 19 marca 2015 roku chciałabym opisać wynik postępowania reklamacyjnego w przedstawionej sprawie.</p> <p>W odpowiedzi na Pana uwagi dotyczące problemów technicznych z działaniem usługi dostępu do sieci Internet uprzejmie informuję, że przeprowadzona diagnostyka nie wykazała występowania u Pana opisanych problemów z działaniem łącza. <strong>Opisane nieprawidłowości wskazują na nieprawidłową konfigurację Państwa sieci wi-fi.</strong> Jednocześnie w przypadku połączenia bezprzewodowego Regulamin Świadczenia Usług Telekomunikacyjnych § 12 ust. 3 określa, iż jakość oraz prędkość transmisji danych jest zależna od licznych czynników zewnętrznych niezależnych od Dostawcy Usług (maksymalna prędkość obsługiwana przez terminal abonencki, obciążenie sieci etc.). Ponadto, sygnał doprowadzony do Państwa lokalu jest prawidłowy, a opisane nieprawidłowości są charakterystyczne dla zewnętrznych zakłóceń sieci wi-fi. Modem oferowany przez Dostawcę usług oferuje możliwość właściwej konfiguracji Państwa sieci bezprzewodowej, tak, aby zminimalizować wpływ zakłóceń zewnętrznych na parametry działania sieci bezprzewodowej.</p> <p>Mając na uwadze powyższe okoliczności, nie odnajduje podstaw do uznania wniesionej reklamacji, którą tym samym należy uznać za niezasadną i udzielić odpowiedzi odmownej.</p> <p>Ufam, iż udzielona odpowiedź spotka się z Pana uznaniem, a nasza dalsza współpraca będzie przebiegała pomyślnie dla obu Stron.</p> <p>Z wyrazami szacunku</p> <p>Agnieszka Marczak<br /> Specjalista ds. Korespondencji</p> </blockquote> <p>Trochę się zdziwiłem, że piszą o konfiguracji wi-fi jeśli wyraźnie zaznaczyłem, że piszę o problemach na kablu, więc pociągnąłem temat:</p> <blockquote> <p>Dzień dobry,</p> <p>Dlaczego w odpowiedzi na moją reklamację, sugerują Państwo, że problem był związany z nieprawidłową konfiguracją sieci wi-fi, jeśli w treści reklamacji wyraźnie napisałem, że:</p> <p>&quot;Testy przerowadziłem w odpowiednich warunkach (połączenie po kablu, nieobciążony komputer, brak innych korzystających z Internetu urządzeń).&quot;</p> <p>Czy mam rozumieć, że nikt nie przeczytał nawet treści reklamacji?</p> <p>Dziękuję,<br /> Piotr Gabryjeluk</p> </blockquote> <p>Na to oni:</p> <blockquote> <p>Dotyczy: problemy techniczne</p> <p>Reklamacja została rozpatrzona przez: Dział Korespondencji i Reklamacji</p> <p>Podstawa prawna rozstrzygnięcia: § 25 ust. 1 Regulaminu Świadczenia Usług Telekomunikacyjnych</p> <p>Rozstrzygnięcie reklamacji: odmowa</p> <p>Szanowny Panie,</p> <p>działając w imieniu INEA S.A. (dalej „Dostawca usług”) z siedzibą w Poznaniu, ul. Klaudyny Potockiej 25, 60-211, adres do korespondencji: Wysogotowo, ul. Wierzbowa 84, 62-081 Przeźmierowo; niniejszym, na podstawie art. 106 ustawy z dnia 16 lipca 2004 roku – Prawo telekomunikacyjne (Dz. U. 2014 poz. 243 – „Ustawa”) w odpowiedzi na reklamację złożoną w dniu 13 kwietnia 2015 roku chciałabym opisać wynik postępowania reklamacyjnego w przedstawionej sprawie.</p> <p>Odnosząc się do zgłoszonych przez Pana uwag uprzejmie informuję, że szczegółowa odpowiedź została udzielona w odpowiedzi na reklamację z dnia 30 marca 2015 roku numer 0235176. Wskazuję, iż Dostawca usług nie będzie się ponownie odnosił do poruszanych przez Pana kwestii, oraz stanowisko Dostawcy usług we wniesionej sprawie pozostaje niezmienione.</p> <p>Jednocześnie informuję, że przeprowadzona diagnostyka nie wykazała występowania u Pana opisanych problemów z działaniem łącza jak i opisane nieprawidłowości wskazują na nieprawidłową konfigurację Państwa sieci wi-fi.</p> <p>Mając na uwadze powyższe okoliczności, nie odnajduje podstaw do uznania wniesionej reklamacji, którą tym samym należy uznać za niezasadną i udzielić odpowiedzi odmownej.</p> <p>Jednakże, jeżeli opisywane przez Pana nieprawidłowości nadal występują, uprzejmie proszę o kontakt poprzez Infolinie Dostawy usług, a Pana sprawa zostanie ponownie rozpatrzona.</p> <p>Ufam, iż udzielona odpowiedź spotka się z Pana uznaniem, a nasza dalsza współpraca będzie przebiegała pomyślnie dla obu Stron.</p> <p>Z wyrazami szacunku</p> <p>Agnieszka Marczak</p> <p>Specjalista ds. Korespondencji</p> </blockquote> <p>Dużo (za dużo?) pustych słów. Zero konkretów, a zatem ja:</p> <blockquote> <p>Dzień dobry!</p> <p>Informuję, że nie w obecnej chwili problemy z usługą nie występują.</p> <p>Czy mają Państwo coś na przeciwko, żebym opublikował naszą korespondencję (tj. oryginalną reklamację, następnie Waszą odpowiedź, potem moje pytanie o to, czy ktokolwiek przeczytał treść oryginalnej reklamacji, a potem niniejszą odpowiedź), na moim blogu?</p> <p>Jeśli nie wyrażają Państwo zgody, proszę o informację z informacją dlaczego.</p> <p>Dziękuję,<br /> Piotr Gabryjeluk</p> </blockquote> <p>Odpowiedzi (w przewidzianym na odpowiedź czasie 14 dni) brak, a zatem notka na blogu jest!</p> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/gabrys" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=2462&amp;amp;size=small&amp;amp;timestamp=1779324991" alt="Gabrys" style="background-image:url(http://www.wikidot.com/userkarma.php?u=2462)" /></a><a href="http://www.wikidot.com/user:info/gabrys" >Gabrys</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://piotrgabryjeluk.wikidot.com/blog:svn2github-problems-may-update</guid>
				<title>Svn2github problems (May update)</title>
				<link>http://piotrgabryjeluk.wikidot.com/blog:svn2github-problems-may-update</link>
				<description>

&lt;p&gt;&lt;strong&gt;UPDATE2: The service is now resumed.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;UPDATE: The server is now replicated with no data loss. RAID is still recovering though (copying data from one disk to another), so to not overwhelm the whole system I&#039;ll re-enable svn2github syncing only after that is done.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;After migrating &lt;a href=&quot;http://svn2github.com&quot;&gt;svn2github.com&lt;/a&gt; (and several other services) to a new server everything was going smoothly for a month or two, until recently I received an alert regarding RAID degradation.&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=2462&amp;amp;amp;size=small&amp;amp;amp;timestamp=1779324991&quot; alt=&quot;Gabrys&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=2462)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;Gabrys&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Sun, 24 May 2015 16:23:20 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p><strong>UPDATE2: The service is now resumed.</strong></p> <p><strong>UPDATE: The server is now replicated with no data loss. RAID is still recovering though (copying data from one disk to another), so to not overwhelm the whole system I'll re-enable svn2github syncing only after that is done.</strong></p> <p>After migrating <a href="http://svn2github.com">svn2github.com</a> (and several other services) to a new server everything was going smoothly for a month or two, until recently I received an alert regarding RAID degradation.</p> <div class="content-separator" style="display: none:"></div> <p>One of the disk in the RAID failed (reading /dev/sda just fails) and in order to prevent the other disk from failing I disabled any write operation (read: updates) for the svn2github-controlled repos.</p> <p>A new server is on the way, but unfortunately, due to the weekend, it will be back only on Monday. Once the data is migrated I'll re-start updating the repos again.</p> <p>Expect an update on this on Tuesday :-)</p> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/gabrys" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=2462&amp;amp;size=small&amp;amp;timestamp=1779324991" alt="Gabrys" style="background-image:url(http://www.wikidot.com/userkarma.php?u=2462)" /></a><a href="http://www.wikidot.com/user:info/gabrys" >Gabrys</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://piotrgabryjeluk.wikidot.com/blog:svn2github-problems</guid>
				<title>Svn2github problems</title>
				<link>http://piotrgabryjeluk.wikidot.com/blog:svn2github-problems</link>
				<description>

&lt;p&gt;I&#039;m the one behind the &lt;a href=&quot;http://svn2github.com/&quot;&gt;svn2github.com&lt;/a&gt; service. The service was started a few years ago to help me and my team start a PHP project that we wanted to host in Git. The PHP libraries we wanted to use were hosted in Subversion. Given the &lt;a href=&quot;https://getcomposer.org/&quot;&gt;Composer&lt;/a&gt; was not too popular we decided to put the links to the libs into the repo using git submodules.&lt;/p&gt;
&lt;p&gt;Given how basic the git-svn is, and how easy it is to have a Git repo in GitHub, we thought, hey, there must be an automatic mirroring tool to clone publicly available SVN repos to GitHub. The service would be probably called svn2github.com.&lt;/p&gt;
&lt;p&gt;Such service was not there and we struggled looking for one, but again, since this was so easy to set up, I decided that I can do it myself! So I did.&lt;/p&gt;
&lt;p&gt;Svn2github.com operated with only minor administration from my side, but at some point I realized there are over 500 repos mirrored by it, which was fine.&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=2462&amp;amp;amp;size=small&amp;amp;amp;timestamp=1779324991&quot; alt=&quot;Gabrys&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=2462)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;Gabrys&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Fri, 12 Dec 2014 18:31:05 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>I'm the one behind the <a href="http://svn2github.com/">svn2github.com</a> service. The service was started a few years ago to help me and my team start a PHP project that we wanted to host in Git. The PHP libraries we wanted to use were hosted in Subversion. Given the <a href="https://getcomposer.org/">Composer</a> was not too popular we decided to put the links to the libs into the repo using git submodules.</p> <p>Given how basic the git-svn is, and how easy it is to have a Git repo in GitHub, we thought, hey, there must be an automatic mirroring tool to clone publicly available SVN repos to GitHub. The service would be probably called svn2github.com.</p> <p>Such service was not there and we struggled looking for one, but again, since this was so easy to set up, I decided that I can do it myself! So I did.</p> <p>Svn2github.com operated with only minor administration from my side, but at some point I realized there are over 500 repos mirrored by it, which was fine.</p> <div class="content-separator" style="display: none:"></div> <p>But recently the server svn2github is hosted on started to experience some problems, mostly with I/O throughput and I connected them directly to the operation of the svn2github processes.</p> <p>Basically with so many repositories stored at the disk, the periodical task to do just git svn rebase and git push if there were any changes might be challenging due to just the number of IO operations needed to accomplish this. Also at some point the (most important) data just stops fitting in cache and the disk IO needs to be requested each time an FS operation is needed.</p> <p>The problem became apparent to me, because of the other services that I run on the same hardware, mainly the database. It started to be terribly slow meaning all the other apps would take forever to do even a basic task.</p> <p>I needed to suspend the svn2github operation to let the more important services continue to run, but I planned to bring this useful service back to life. As often in such cases I want to add more features while doing that and make the updates more clever, so they don't consume so much server &quot;life&quot; as they were.</p> <p>The first step though is restarting svn2github, which means you can now add more SVN repos to be mirrored to GitHub and the repos will be synchronized with one small exception. Any repository that contains more than 2000 files (including the .git files) will not be automatically updated.</p> <p>I'll update the GitHub descriptions of those &quot;paused&quot; mirrors and if you want them to be &quot;resumed&quot;, I'll ask you to contact me and let me know. This way the service will continue to work for the small repos (which are the majority), which don't cause so much trouble for the machine, while the big repos would be only updated when requested (I assume most of them were needed &quot;once&quot; and now no-one really needs them in place).</p> <p>Happy SVN mirroring! See you on <a href="http://svn2github.com/">svn2github.com</a>!</p> <p><strong>UPDATE: Some svn2github stats</strong></p> <p>To give a notion of scale this project is at here are some stats:</p> <p>Repositories with less than 2000 files each (including the .git files):</p> <p>Number of them: 482<br /> Total size of them on disk: 19G<br /> Total number of files on disk: 954321<br /> The biggest one: 635M (<a href="https://github.com/Wikia/DevIL">DevIL</a>)<br /> The smallest one: just 208k (<a href="https://github.com/Wikia/aszip">aszip</a>)</p> <p>Repositiories with over 2000 files in each:</p> <p>Number of them: 231<br /> The total size: 308G (took 133m58.527s to compute that)<br /> The biggest one: 42G (<a href="https://github.com/svn2github/testingazuan">testingazuan</a>)</p> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/gabrys" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=2462&amp;amp;size=small&amp;amp;timestamp=1779324991" alt="Gabrys" style="background-image:url(http://www.wikidot.com/userkarma.php?u=2462)" /></a><a href="http://www.wikidot.com/user:info/gabrys" >Gabrys</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://piotrgabryjeluk.wikidot.com/blog:work-around-buggy-soundcard</guid>
				<title>Working around a buggy sound card</title>
				<link>http://piotrgabryjeluk.wikidot.com/blog:work-around-buggy-soundcard</link>
				<description>

&lt;p&gt;I found the laptop I bought recently has a weird thing with its soundcard. It plays music OK, it also allows you to change the mixer levels, nothing special, but when you try changing mixer setting while the music is playing the music starts getting choppy and the process handling the mixer tend to freeze. Also you cannot pause the music, sometimes it repeats the same sample over and over and it gets very annoying.&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=2462&amp;amp;amp;size=small&amp;amp;amp;timestamp=1779324991&quot; alt=&quot;Gabrys&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=2462)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;Gabrys&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Tue, 02 Dec 2014 23:34:29 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>I found the laptop I bought recently has a weird thing with its soundcard. It plays music OK, it also allows you to change the mixer levels, nothing special, but when you try changing mixer setting while the music is playing the music starts getting choppy and the process handling the mixer tend to freeze. Also you cannot pause the music, sometimes it repeats the same sample over and over and it gets very annoying.</p> <div class="content-separator" style="display: none:"></div> <p>My approach to this issue was to use PulseAudio software mixer capabilities, so the hardware mixer is never adjusted (other than for the initial setup).</p> <h1><span>Step 1. Getting PulseAudio to use the software mixer</span></h1> <p>I found no good documentation on this other than PulseAudio uses <em>paths</em> to convert the desired volume to the hardware mixer settings and if it lacks the ability to do so it would turn the volume up/down using software. Reading between the lines I realized if I remove the <em>paths</em> I will get what I want. Just do this and restart pulseaudio and you'll have PulseAudio doing all the mixing in software:</p> <div class="code"> <pre><code>sudo mv /usr/share/pulseaudio/alsa-mixer/paths /usr/share/pulseaudio/alsa-mixer/paths.bak</code></pre></div> <h2><span>Verifying it works</span></h2> <p>Open two terminal windows. In each of them open alsamixer. Both should display very simple controls and say Card: PulseAudio. Use F6 to switch to the real card in one of the windows. Usually the cards have plethora of controls, so should yours.</p> <p>Now change the output volume in the alsamixer still saying &quot;Card: PulseAudio&quot;. If the volume reported by the other alsamixer does not change, it works as expected!</p> <p>If you now rename the paths directory back and restart the pulseaudio process, updating the PulseAudio volume should update the real device volume as well.</p> <h1><span>Step 2. Integrating this with XFCE (or other DE)</span></h1> <p>The way xfce4 handles the volume is two-fold:</p> <ul> <li>There's a xfce4-volumed daemon. It only controls the key bindings. It binds volume up, volume down and mute keys to control the real device controls</li> <li>There's a panel applet called &quot;Audio Mixer&quot; that shows the current volume level and lets you change the volume as well.</li> </ul> <p>Both component are optional and both seem to not work with PulseAudio (even through PulseAudio ALSA emulation which tricks alsamixer for instance).</p> <p>We're going to overcome this problem by replacing these components with two other programs.</p> <h2><span><a href="https://github.com/fernandotcl/pa-applet">pa-applet</a></span></h2> <p>pa-applet will replace the &quot;Audio Mixer&quot; applet. The difference is the pa-applet docks to the systray, so is not XFCE-specific. The downside is we don't have control over the specific position of the icon, all we know is it will appear in the systray (so don't forget to have the systray applet added to the panel).</p> <p>In order to install this software you need to clone the source, and run ./autogen.sh, ./configure, make, sudo make install. You will get information about deps missing, for instance:</p> <div class="code"> <pre><code>configure: error: Package requirements (glib-2.0) were not met: No package 'glib-2.0' found</code></pre></div> <p>You need to find the proper *-dev package for each unmet dependency (for this one it will be libglib2.0-dev).</p> <p>I came across one additional problem. The software seems not updated after some GTK+ 3 updates and it uses a deprecated function. Because the code is configured in a way that every warning stops the compilation, it wouldn't let you compile the code unless you open the src/Makefile file and then find and remove the -Werror flag from it.</p> <h2><span><a href="https://launchpad.net/xfce4-volumed-pulse">xfce4-volumed-pulse</a></span></h2> <p>This part will take care of binding the media keys to the pulse audio controls (rather than to the sound card controls).</p> <p>You need to download the tar package, untar it, ./configure, make, sudo make install. It also requires quite a few libs to be installed, but I didn't found any issues when compiling.</p> <h2><span>Hooking this up together</span></h2> <p>Since I didn't need the original xfce4-volume anymore I decided to remove it:</p> <div class="code"> <pre><code>apt-get remove xfce4-volumed</code></pre></div> <p>But because XFCE will try to launch this anyway on each start, I decided to take advantage of it and replace it with a script:</p> <div class="code"> <pre><code>#!/bin/bash /usr/local/bin/xfce4-volumed-pulse /usr/local/bin/pa-applet</code></pre></div> <p>Add the executable bit, restart the laptop and all should be working correctly at this moment.</p> <h1><span>Setting the hw mixer controls</span></h1> <p>Since PulseAudio won't update the hw controls after you follow up this little howto, it's quite important to set all the important channels to 100% (or other number up to your taste). The way to update the hw controls was described before.</p> <p>Open the terminal, type alsamixer and hit F6. This will give the list of ALSA devices besides the PulseAudio emulation, your real sound cards should display as well. Choose the right one and you should be given access to tweak the real card controls.</p> <p>Note if you removed the PulseAudio paths, the PulseAudio controls wouldn't update when you tweak the hw controls.</p> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/gabrys" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=2462&amp;amp;size=small&amp;amp;timestamp=1779324991" alt="Gabrys" style="background-image:url(http://www.wikidot.com/userkarma.php?u=2462)" /></a><a href="http://www.wikidot.com/user:info/gabrys" >Gabrys</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://piotrgabryjeluk.wikidot.com/blog:lamerstwo-allegro</guid>
				<title>Lamerstwo allegro</title>
				<link>http://piotrgabryjeluk.wikidot.com/blog:lamerstwo-allegro</link>
				<description>

&lt;p&gt;Niedawno miałem głupią przygodę z allegro, które pokazało brak klasy w obsłudze klienta, odpowiedzialnością za swój błąd obarczyło sprzedawcę, a mi uniemożliwiło zapłacenie kartą za produkty.&lt;/p&gt;
&lt;p&gt;Przeprowadziłem nieco frustrującą rozmowę z allegro na temat błędu w ich serwisie. Po około miesiącu usłyszałem plotkę jakoby większość ludzi z działu obsługi klienta allegro zostało zwolnionych. Nie zmieniło to jednak w ogóle podejścia do klienta.&lt;/p&gt;
&lt;p&gt;Dzisiaj na forum allegro, mnóstwo zgłoszeń o &amp;quot;zwielokrotnionym działaniu koszyka&amp;quot;, a allegro wciąż przerzuca odpowiedzialność za ich błąd na sprzedawców i kupujących, czego doświadczyła dziś moja żona.&lt;/p&gt;
&lt;p&gt;To zainspirowało mnie do upublicznienia historii mojej rozmowy z allegro.&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=2462&amp;amp;amp;size=small&amp;amp;amp;timestamp=1779324991&quot; alt=&quot;Gabrys&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=2462)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;Gabrys&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Wed, 05 Nov 2014 18:44:48 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>Niedawno miałem głupią przygodę z allegro, które pokazało brak klasy w obsłudze klienta, odpowiedzialnością za swój błąd obarczyło sprzedawcę, a mi uniemożliwiło zapłacenie kartą za produkty.</p> <p>Przeprowadziłem nieco frustrującą rozmowę z allegro na temat błędu w ich serwisie. Po około miesiącu usłyszałem plotkę jakoby większość ludzi z działu obsługi klienta allegro zostało zwolnionych. Nie zmieniło to jednak w ogóle podejścia do klienta.</p> <p>Dzisiaj na forum allegro, mnóstwo zgłoszeń o &quot;zwielokrotnionym działaniu koszyka&quot;, a allegro wciąż przerzuca odpowiedzialność za ich błąd na sprzedawców i kupujących, czego doświadczyła dziś moja żona.</p> <p>To zainspirowało mnie do upublicznienia historii mojej rozmowy z allegro.</p> <div class="content-separator" style="display: none:"></div> <p>Moja wiadomość do allegro (skopiowane z maila, które allegro wysyła jako potwierdzenie, że otrzymali, warto zwrócić uwagę do wagi przywiązanej do bezpieczeństwa, tak dużej, że znak cudzysłowu jest zaeskepowany nawet nie raz, co i tak dla e-maila nie ma sensu, ale aż TRZY RAZY!):</p> <blockquote> <p>Dzień dobry,</p> <p>chciałem kupić przez koszyk 6 żarówek z aukcji: &amp;amp;amp;quot;KIERUNKOWSKAZ LED 5<br /> SMD W5W T10 POMARAŃCZOWY NW5P&amp;amp;amp;quot; (numer 4552723961).</p> <p>Dodałem więc 6 żarówek do koszyka i przeszedłem przez wszystkie etapy<br /> finalizowania zamówienia.</p> <p>Na ostatnim etapie po kliknięciu &amp;amp;amp;quot;potwierdź&amp;amp;amp;quot; pojawił się<br /> komunikat o błędzie technicznym i prośba o spróbowanie ponowne za chwilę.</p> <p>W związku z tym upewniłem się, że transakcji nie ma w<br /> &amp;amp;amp;quot;kupionych&amp;amp;amp;quot;, przeszedłem do koszyka i ponownie zamówiłem<br /> przedmioty (które wciąż tam były). Nie dodawałem kolejnych 6 sztuk do koszyka!</p> <p>Przy płatności okazało się, że mam do zapłaty kwotę za 12 żarówek, a na mój e-mail<br /> przyszły DWA potwierdzenia zakupu po 6 żarówek w każdym przypadku.</p> <p>Proszę o usunięcie jednej z kupionych aukcji (albo przerobienie obu na 3 sztuki),<br /> tak abym mógł zapłacić sprzedającemu za 6 sztuk żarówek i otrzymać produkt, w<br /> ilości której potrzebuję.</p> <p>Proszę o pilne naprawienie Waszego błędu.</p> <p>Dziękuję,<br /> Piotr Gabryjeluk</p> </blockquote> <p>Odpowiedź allegro:</p> <blockquote> <p>Dzień dobry.</p> <p>Po potwierdzeniu zakupu dochodzi do zawarcia umowy, kolejne potwierdzenie dodaje nowe sztuki. Pan potwierdził zakup dwukrotnie:</p> <p>quakee 2,15 zł 6 pon, 15 wrz 2014, 09:13:12<br /> quakee 2,15 zł 6 pon, 15 wrz 2014, 09:12:02</p> <p>Rozumiem jednak, że doszło do nieporozumienia i kupił Pan więcej sztuk, niż Pan zamierzał. Ze strony Allegro nie ma możliwości, żeby anulować Pana zakup, ale proszę skontaktować się ze Sprzedającym, będzie on mógł zwrócić się do nas z prośbą o zwrot prowizji za niesprzedane przedmioty. Pan zostanie tylko poproszony o wyjaśnienia w formularzu, do którego link prześlemy Panu w powiadomieniu.</p> <p>Jeśli Sprzedający jest przedsiębiorcą, może Pan odstąpić od umowy w ciągu 10 dni od chwili otrzymania towaru, tak mówi Ustawa. Natomiast część Sprzedających wyraża zgodę na anulowanie zakupu jeszcze przed wysyłką tego towaru.</p> <p>Proszę również ustalić ze Sprzedającym sposób zapłaty za przedmioty, ponieważ system PayU będzie wymagał zapłaty za całe zakupy.</p> <p>W przyszłości jeśli wystąpi podobny problem proszę nie potwierdzać zakupu kilka razy. Proszę wykonać zrzut ekranu z widocznym błędem i wysłać go do nas. Będziemy mieli wówczas możliwość szczegółowej analizy opisanego problemu.</p> <p>Pozdrawiam,</p> </blockquote> <p>Moja odpowiedź:</p> <blockquote> <p>Dzień dobry,</p> <p>Dziękuje za odpowiedź.</p> <p>Czy w allegro po zakupie przedmiotów pozostają one w koszyku?</p> <p>Kupowałem już wielokrotnie przez koszyk zarówno w allegro jak i w innych serwisach<br /> i dotąd zawsze po potwierdzeniu zakupów, koszyk ulegał opróżnieniu (co ma sens w<br /> kontekście ogólnie pojętego UX).</p> <p>Proszę o ponowne przeczytanie mojej wiadomości i rzeczową odpowiedź.</p> <p>W międzyczasie skontaktuję się ze sprzedawcą na wypadek, gdyby jednak nie<br /> potrafiła mi Pani pomóc.</p> <p>Pozdrawiam,<br /> Piotr Gabryjeluk</p> </blockquote> <p>Odpowiedź allegro:</p> <blockquote> <p>Witam.</p> <p>Po zakupie przedmioty powinny zniknąć z koszyka. Jeśli tak się nie stało, należało się z nami skontaktować przed ponownym potwierdzeniem zakupu.</p> <p>Nie mam mozliwości anulowania zakupu, gdyż w chwili jego potwierdzenia staje się on wiążący dla Pana i Sprzedającego.</p> <p>Nie mamy możliwości weryfikacji ewentualnego problemu technicznego po naszej stronie, kiedy jest już po fakcie.</p> <p>Jeśli w przyszłości wystąpi podobny problem proszę nie potwierdzać zakupu kilka razy, proszę od razu się z nami skontaktować. Sprawa trafi wtedy do Działu Technicznego i będzie weryfikowana.</p> <p>Pozdrawiam,</p> </blockquote> <p>Moja odpowiedź:</p> <blockquote> <p>Dzień dobry,</p> <p>czy zatem na allegro komunikat mówiący o tym, że wystąpił błąd i należy<br /> rozumieć w następujący sposób:</p> <ul> <li>operacja, którą próbowałeś zrobić i tak mogła nastąpić, nawet jeśli na</li> </ul> <p>to nie wygląda (w tym przypadku nie usunięto przedmiotów z koszyka)</p> <ul> <li>nie próbuj ponownie (bo np. kupisz jakieś rzeczy podwójnie)</li> </ul> <p>Dziękuję za odpowiedź,<br /> Piotr Gabryjeluk</p> </blockquote> <p>Zauważyłem, że się pomyliłem w poprzedniej wiadomości, a zatem wysłałem sprostowanie:</p> <blockquote> <p>Przepraszam, do mojej wiadomości wkradł się błąd. Poniżej zredagowane<br /> pytanie:</p> <p>Czy zatem na allegro komunikat mówiący o tym, że wystąpił błąd i należy<br /> spróbować ponownie, należy rozumieć w następujący sposób:</p> <ul> <li>operacja, którą próbowałeś zrobić i tak mogła nastąpić, nawet jeśli na</li> </ul> <p>to nie wygląda (w tym przypadku nie usunięto przedmiotów z koszyka)</p> <ul> <li>nie próbuj ponownie (bo np. kupisz jakieś rzeczy podwójnie)</li> </ul> <p>Dziękuję,<br /> Piotr Gabryjeluk</p> </blockquote> <p>Brak odpowiedzi ze strony allegro, a zatem prośba o odpowiedź:</p> <blockquote> <p>Dzień dobry,</p> <p>czy zamierzają Państwo odpowiedzieć na moje pytanie?</p> <p>Dziękuję,<br /> Piotr Gabryjeluk</p> </blockquote> <p>(W końcu!) odpowiedź:</p> <blockquote> <p>Witam.</p> <p>Jeśli ma Pan zastrzeżenia, co do treści komunikatów i chciałby Pan przesłać sugestię bądź zaproponować nowe rozwiązanie, zachęcam do podzielenia się nią na naszym forum, na stronie:</p> <p><a href="http://cafe.allegro.pl/forumdisplay.php?67-Sugestie-i-pomys%C5%82y">http://cafe.allegro.pl/forumdisplay.php?67-Sugestie-i-pomys%C5%82y</a></p> <p>Tam będą mieli możliwość zapoznania się z nią specjaliści od optymalizacji wprowadzanych rozwiązań.</p> <p>Pozdrawiam,</p> </blockquote> <p>Niezadowolony z tej odpowiedzi, odpisałem:</p> <blockquote> <p>Rozumiem, że nie zamierzają Państwo odpowiedzieć na moje pytanie.</p> <p>Jeżeli nie dostanę odpowiedzi na moje pytanie:</p> <blockquote> <p>Czy zatem na allegro komunikat mówiący o tym, że wystąpił błąd i należy spróbować ponownie, należy rozumieć w następujący sposób:</p> <ul> <li>operacja, którą próbowałeś zrobić i tak mogła nastąpić, nawet jeśli na to nie wygląda (w tym przypadku nie usunięto przedmiotów z koszyka)</li> <li>nie próbuj ponownie (bo np. kupisz jakieś rzeczy podwójnie)</li> </ul> </blockquote> <p>uznam, że:</p> <p>1. Z powodu błędnego działa koszyka oraz błędnego komunikatu w allegro,<br /> zostałem wprowadzony w błąd przez co dwukrotnie zamówiłem towar</p> <p>2. Z powodu dwukrotnego zamówienia towaru, nie miałem możliwości<br /> zapłacenia przez PayU (a zatem ograniczyliście mi możliwość sprawnego<br /> zakupu) a moja przesyłka z powodu potrzeby dodatkowej komunikacji nie<br /> przyjdzie na czas</p> <p>3. Zamiast uczciwie zająć się sprawą: przeprosić sprzedawcę i mnie, i<br /> zaproponować rozwiązanie, zrzucają Państwo odpowiedzialność za własny<br /> błąd na kupującego i sprzedającego wymagając dodatkowej komunikacji poza<br /> allegro, proszenia o zwrot prowizji, a sprzedającego tłumaczenia się z<br /> błędu, który wyniknął z winy allegro.</p> <p>Proszę zatem o odpowiedź na moje pytanie i na przyszłość o nieunikanie<br /> odpowiedzialności za błędne działanie serwisu. Wszyscy rozumieją, że<br /> czasami pojawi się jakiś błąd i nikt nie ma za to pretensji, ale<br /> ignorując ten fakt i zrzucając odpowiedzialność ze błędy na innych<br /> pokazujecie totalny brak klasy (a zdaje się, że allegro nie chce być już<br /> postrzegane jako e-bazarek z tanimi produktami i fatalną obsługą).</p> <p>Dziękuję i liczę na odpowiedź,<br /> Piotr Gabryjeluk.</p> </blockquote> <p>Allegro odpowiada:</p> <blockquote> <p>Witam.</p> <p>Nie mogę odnieść się do Pana prośby. Nie widziałam komunikatu, który Pan widział. Nie przesłał Pan zrzutu ekranu, nie zacytował Pan również dokładnej jego treści.</p> <p>Komunikat, który Pan zobaczył nie jest tutaj jednak najważniejszy. Nie informował on, że nie doszło do zakupu. Potwierdzenie opcji Kup teraz oznacza zakup. Z tego, co Pan napisał wynika, że potwierdził Pan zakup jeden raz, a później kolejny raz, dlatego doszło do podwójnego zakupu.</p> <p>Poprosiłam Pana o kontakt z nami, jeśli w przyszłości problem pojawi się ponownie, gdyż na tę chwilę nie mamy możliwości weryfikacji tego, co stało się, kiedy pierwszy raz dokonał Pan zakupu.</p> <p>Pozdrawiam,</p> </blockquote> <p>Moja odpowiedź:</p> <blockquote> <p>Dzień dobry,</p> <p>proszę zrozumieć, że z mojej perspektywy błąd pojawił się przy drugim<br /> &quot;potwierdzeniu&quot; koszyka. Przyzna Pani, że robienie wtedy screenshota nie<br /> miałoby żadnego sensu.</p> <p>Jeśli zależy Pani na zidentyfikowaniu błędu i ustrzeżenie przed nim<br /> przyszłym użytkowników (żeby im nie musiała Pani wmawiać, że to ich<br /> wina), niech Pani poprosi zespół developerski o logi koszyka.</p> <p>Co do braku możliwości weryfikacji, śmiem w to wątpić. W takiej<br /> aplikacji jak allegro, na pewno jest zapisywane powiązanie transakcji z<br /> konkretnym koszykiem. Jeśli po transakcji koszyk jest czyszczony, nigdy<br /> nie powinno się zdarzyć, że z jednego koszyka są dwie transakcje. Mogę<br /> dla Pani sprawdzić, czy jest to teoretycznie możliwe do zweryfikowania z<br /> kolegami, którzy pracują w allegro. Również łatwo znaleźć listę<br /> wszystkich komunikatów przewidzianych dla błędów w czasie klikania na<br /> konkretny przycisk w czasie finalizacji zamówienia.</p> <p>Proszę powiedzieć, czy podtrzymuje Pani opinię o braku możliwości<br /> weryfikacji mojej sytuacji. Jeśli tak jest, proszę o informację, czy i<br /> kiedy planujecie Państwo logować ID koszyka, z którego powstało<br /> zamówienie, żeby w przyszłości nie zasłaniać się brakiem danych.</p> <p>Czy ma Pani jakiekolwiek informacje świadczące o tym, że faktycznie<br /> potwierdziłem dwa razy zamówienie wiedząc o tym, że za pierwszym razem<br /> się ono powiodło?</p> <p>Co do rad na przyszłość, też mam kilka dla Państwa:</p> <p>1. Proszę się skupiać najpierw na rozwiązaniu sytuacji która już się<br /> wydarzyła a nie na radzeniu waszym użytkownikom co zrobić jak następny<br /> raz spotkają się z błędem w waszym serwisie.</p> <p>2. Jeśli oczekujecie, że użytkownicy nie będą ponownie próbować klikać w<br /> przycisk nie piszcie, żeby próbowali ponownie.</p> <p>3. Jeśli oczekujecie, żeby użytkownicy kontaktowali się z Wami w<br /> przypadku wystąpienia konkretnego błędu, to napiszcie, żeby się<br /> skontaktowali.</p> <p>Czekam na wyjaśnienie i naprawienie mojej sytuacji.</p> <p>Dziękuję,<br /> Piotr Gabryjeluk</p> </blockquote> <p>Allegro w końcu się poddało (powiedzmy):</p> <blockquote> <p>Witam.</p> <p>Sprawa została zgłoszona do Działu Technicznego.</p> <p>Dodam tylko, że bez względu na efekt działań Działu Technicznego, nie będziemy mogli usunąć zakupu z Pana konta i w tej sprawie tak czy inaczej musi się Pan skontaktować z Kontrahentem.</p> <p>Pozdrawiam,</p> </blockquote> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/gabrys" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=2462&amp;amp;size=small&amp;amp;timestamp=1779324991" alt="Gabrys" style="background-image:url(http://www.wikidot.com/userkarma.php?u=2462)" /></a><a href="http://www.wikidot.com/user:info/gabrys" >Gabrys</a></span></p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://piotrgabryjeluk.wikidot.com/blog:accessing-https-over-http</guid>
				<title>Accessing HTTPS Over HTTP</title>
				<link>http://piotrgabryjeluk.wikidot.com/blog:accessing-https-over-http</link>
				<description>

&lt;p&gt;For one my internal projects, I needed a HTTP-to-HTTPS proxy in a way that a client connects to HTTP network inside the trusted network and the server connects through the Internet to the service via HTTPS.&lt;/p&gt;
&lt;p&gt;by &lt;span class=&quot;printuser avatarhover&quot;&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;&lt;img class=&quot;small&quot; src=&quot;http://www.wikidot.com/avatar.php?userid=2462&amp;amp;amp;size=small&amp;amp;amp;timestamp=1779324991&quot; alt=&quot;Gabrys&quot; style=&quot;background-image:url(http://www.wikidot.com/userkarma.php?u=2462)&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://www.wikidot.com/user:info/gabrys&quot;  &gt;Gabrys&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Sat, 01 Nov 2014 16:47:51 +0000</pubDate>
												<content:encoded>
					<![CDATA[
						 <p>For one my internal projects, I needed a HTTP-to-HTTPS proxy in a way that a client connects to HTTP network inside the trusted network and the server connects through the Internet to the service via HTTPS.</p> <div class="content-separator" style="display: none:"></div> <p>I quickly set this up using Apache. Here's the virtual host file:</p> <div class="code"> <pre><code>&lt;VirtualHost *:8371&gt; ServerName localhost ProxyPreserveHost Off SSLProxyEngine On Header edit Set-Cookie secure;.HttpOnly HttpOnly RewriteEngine On RewriteRule ^/(.*) https://remote-server.com/$1 [P,L] ProxyPassReverse / https://remote-server.com/ &lt;/VirtualHost&gt;</code></pre></div> <p>You need to enable the following modules for that: proxy, proxy_http, rewrite, headers</p> <p>Note, above I also mangle the Set-Cookie response headers in a way, that every http-only secure cookie (this means a cookie is transmitted to the server only over a secure transport and is not available on the client side) is converted to a http-only but non-secure.</p> <p>The rule I produced (convert regexp &quot;secure;.HttpOnly&quot; to just &quot;HttpOnly&quot;) may not work for you because I targeted one particular service and the construction of such cookies may be different for the one you want to proxy.</p> <p>The second note is that, the service you're proxying might actually check the protocol on the client side as well, which we cannot mock on the server-level. I was lucky my service didn't have such checks.</p> <p>by <span class="printuser avatarhover"><a href="http://www.wikidot.com/user:info/gabrys" ><img class="small" src="http://www.wikidot.com/avatar.php?userid=2462&amp;amp;size=small&amp;amp;timestamp=1779324991" alt="Gabrys" style="background-image:url(http://www.wikidot.com/userkarma.php?u=2462)" /></a><a href="http://www.wikidot.com/user:info/gabrys" >Gabrys</a></span></p> 
				 	]]>
				</content:encoded>							</item>
				</channel>
</rss>