<?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>Long-term Memory &#187; Perl</title>
	<atom:link href="http://blog.dest-unreach.be/tag/perl/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.dest-unreach.be</link>
	<description>A collection of note-to-self&#039;s</description>
	<lastBuildDate>Sun, 29 Jan 2012 16:05:00 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Tail-ing logfiles with visual timing</title>
		<link>http://blog.dest-unreach.be/2011/03/09/tail-ing-logfiles-with-visual-timing</link>
		<comments>http://blog.dest-unreach.be/2011/03/09/tail-ing-logfiles-with-visual-timing#comments</comments>
		<pubDate>Wed, 09 Mar 2011 09:45:33 +0000</pubDate>
		<dc:creator>Niobos</dc:creator>
				<category><![CDATA[Networking & Security]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[log]]></category>
		<category><![CDATA[Perl]]></category>
		<category><![CDATA[script]]></category>

		<guid isPermaLink="false">http://blog.dest-unreach.be/?p=1996</guid>
		<description><![CDATA[I regularly watch log files in real time using the highly appreciated tail -f command. But I usually find myself manually inserting newlines to give a visual clue of which log-lines happened together. Obviously the timestamps in the lines tell you the full story, but it&#8217;s not that visually appealing. So I wrote a very [...]]]></description>
			<content:encoded><![CDATA[<p>I regularly watch log files in real time using the highly appreciated <em>tail -f</em> command. But I usually find myself manually inserting newlines to give a visual clue of which log-lines happened together. Obviously the timestamps in the lines tell you the full story, but it&#8217;s not that visually appealing.</p>
<p><span id="more-1996"></span>So I wrote <a href="/wp-content/uploads/2011/03/logtail.pl">a very simple perl-script</a> that automates this for me. It behaves like <em>cat</em>, but inserts empty lines between input lines proportional to the amount of time between them. The numbers of lines inserted in logarithmically proportional to the elapsed time: one line for the first second, a second line for the next two seconds, a third line for the next 4 seconds, …</p>
<blockquote>
<pre>$ tail -f /var/log/mail.log | logtail.pl | sed 's/ .*//'
2011-03-09T10:33:02+01:00
2011-03-09T10:33:02+01:00
2011-03-09T10:33:02+01:00
2011-03-09T10:33:02+01:00
 
 
 
 
2011-03-09T10:33:36+01:00
2011-03-09T10:33:36+01:00
2011-03-09T10:33:36+01:00
 
 
 
 
2011-03-09T10:34:01+01:00
2011-03-09T10:34:01+01:00
 
 
 
 
 
2011-03-09T10:34:36+01:00
2011-03-09T10:34:36+01:00
2011-03-09T10:34:36+01:00
 
 
 
2011-03-09T10:34:48+01:00
2011-03-09T10:34:48+01:00
2011-03-09T10:34:48+01:00</pre>
</blockquote>
]]></content:encoded>
			<wfw:commentRss>http://blog.dest-unreach.be/2011/03/09/tail-ing-logfiles-with-visual-timing/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ESC data logging</title>
		<link>http://blog.dest-unreach.be/2010/07/14/esc-data-logging</link>
		<comments>http://blog.dest-unreach.be/2010/07/14/esc-data-logging#comments</comments>
		<pubDate>Wed, 14 Jul 2010 16:14:19 +0000</pubDate>
		<dc:creator>Niobos</dc:creator>
				<category><![CDATA[RCheli]]></category>
		<category><![CDATA[gnuplot]]></category>
		<category><![CDATA[logbook]]></category>
		<category><![CDATA[miniTitan]]></category>
		<category><![CDATA[Perl]]></category>
		<category><![CDATA[script]]></category>

		<guid isPermaLink="false">http://blog.dest-unreach.be/?p=1758</guid>
		<description><![CDATA[As mentioned, my new ESC also has data-logging capabilities. The provided software actually has a fairly descend viewer, but it lacks some features. As soon as you download the data, the Log viewer is opened automatically presenting the full log. You can limit the graph to only one session (flight). The bottom shows the different [...]]]></description>
			<content:encoded><![CDATA[<p>As <a href="/2010/07/11/minititan-repairs-contd">mentioned</a>, my new ESC also has data-logging capabilities. The <a href="http://www.castlecreations.com/products/castle_link.html">provided software</a> actually has a fairly descend viewer, but it lacks some features.</p>
<p><span id="more-1758"></span></p>
<p>As soon as you download the data, the Log viewer is opened automatically presenting the full log. You can limit the graph to only one session (flight). The bottom shows the different datasets. Clicking their name adds them to the graph. You can zoom and pan by using the mouse; while hoovering the cursor, the bottom numbers show the numerical value of the different parameters at that instant in time.</p>
<p><img class="alignnone size-full wp-image-1803" title="castle log" src="/wp-content/uploads/2010/07/castle-log.png" alt="" width="805" height="582" /></p>
<p>You can save the data into a &#8220;<a href="/wp-content/uploads/2010/07/example-data.csv">csv file</a>&#8220;. The term CSV is rather loosly interpreted, as the file contains some &#8220;comment lines&#8221; that are not in CSV-format. While the Log Viewer tool provides an export function for the graph data as well, I didn&#8217;t feel like exporting half a dozen of graphs for every flight by hand. So I stirred some perl magic and gnuplot wizardry together into <a href="/wp-content/uploads/2010/07/phoenix-ice-log.pl">a script</a> that reads the CSV log file and produces a set of graphs for each session (flight) in the log:</p>
<p><img class="alignnone size-full wp-image-1797" title="phoenix-log.battery" src="/wp-content/uploads/2010/07/phoenix-log.battery.png" alt="" width="640" height="400" /><br />
<img class="alignnone size-full wp-image-1798" title="phoenix-log.current" src="/wp-content/uploads/2010/07/phoenix-log.current.png" alt="" width="640" height="400" /><br />
<img class="alignnone size-full wp-image-1799" title="phoenix-log.powerout" src="/wp-content/uploads/2010/07/phoenix-log.powerout.png" alt="" width="640" height="400" /><br />
<img class="alignnone size-full wp-image-1800" title="phoenix-log.rpm" src="/wp-content/uploads/2010/07/phoenix-log.rpm_.png" alt="" width="640" height="400" /><br />
<img class="alignnone size-full wp-image-1801" title="phoenix-log.temp" src="/wp-content/uploads/2010/07/phoenix-log.temp_.png" alt="" width="640" height="400" /><br />
<img class="alignnone size-full wp-image-1802" title="phoenix-log.throttle" src="/wp-content/uploads/2010/07/phoenix-log.throttle.png" alt="" width="640" height="400" /></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.dest-unreach.be/2010/07/14/esc-data-logging/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Parsing binary data the easy way</title>
		<link>http://blog.dest-unreach.be/2009/07/08/parsing-binary-data-the-easy-way</link>
		<comments>http://blog.dest-unreach.be/2009/07/08/parsing-binary-data-the-easy-way#comments</comments>
		<pubDate>Wed, 08 Jul 2009 13:20:14 +0000</pubDate>
		<dc:creator>Niobos</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Perl]]></category>
		<category><![CDATA[script]]></category>

		<guid isPermaLink="false">http://blog.dest-unreach.be/?p=1334</guid>
		<description><![CDATA[I was looking for an easy way to parse a binary file. I know what the file contains (it&#8217;s an MPEG2 transport stream) and know the bit-field layout. It&#8217;s just a pain to figure the bits out manually in a hex editor. Google pointed me to 010 Editor which supports binary templates, which is pretty [...]]]></description>
			<content:encoded><![CDATA[<p>I was looking for an easy way to parse a binary file. I know what the file contains (it&#8217;s an MPEG2 transport stream) and know the bit-field layout. It&#8217;s just a pain to figure the bits out manually in a hex editor.</p>
<p>Google pointed me to <a href="http://www.sweetscape.com/010editor/">010 Editor</a> which supports <a href="http://www.sweetscape.com/010editor/templates.html">binary templates</a>, which is pretty much what I was looking for. However, this tool only runs on Windows and is commercial. Enough reason to look further.</p>
<p>That&#8217;s when I came across the <a href="http://search.cpan.org/~semuelf/Data-ParseBinary/lib/Data/ParseBinary.pm">Data::ParseBinary</a> perl module, which is a true relief to use. It supports pretty much every thing you need to parse a binary file:</p>
<ul>
<li>Signed and unsigned integers</li>
<li>Big and little endian</li>
<li>8, 16, 32 and 64 bit integers</li>
<li>Bitfields</li>
<li>Enum-types to specify your own names for values</li>
<li>If-constructs: Fields are present or not depending on the value of another field</li>
</ul>
<p>In short, an incredible tool!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.dest-unreach.be/2009/07/08/parsing-binary-data-the-easy-way/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Restricted rsync over ssh</title>
		<link>http://blog.dest-unreach.be/2009/06/30/restricted-rsync-over-ssh</link>
		<comments>http://blog.dest-unreach.be/2009/06/30/restricted-rsync-over-ssh#comments</comments>
		<pubDate>Tue, 30 Jun 2009 17:16:51 +0000</pubDate>
		<dc:creator>Niobos</dc:creator>
				<category><![CDATA[Networking & Security]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[Perl]]></category>
		<category><![CDATA[rsync]]></category>
		<category><![CDATA[script]]></category>
		<category><![CDATA[SSH]]></category>

		<guid isPermaLink="false">http://blog.dest-unreach.be/?p=1323</guid>
		<description><![CDATA[rsync is a very nice tool to synchronize two directories, especially if they are on different machines. If you require confidentiality of the transferred data, rsync works great over ssh. Besides the standard password authentication, ssh also supports public key authentication. This key-based authentication has the added bonus of having per-key options: you can restrict [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.samba.org/rsync/">rsync</a> is a very nice tool to synchronize two directories, especially if they are on different machines. If you require confidentiality of the transferred data, rsync works great over <a href="http://www.openssh.com/">ssh</a>.</p>
<p>Besides the standard password authentication, ssh also supports <a href="http://sial.org/howto/openssh/publickey-auth/">public key authentication</a>. This key-based authentication has the added bonus of having per-key options:</p>
<ul>
<li>you can restrict the source IP from which this key may be used</li>
<li>you can force a command to be executed instead of allowing the connecting side to specify one</li>
</ul>
<p><span id="more-1323"></span>Combining the power of these tools gives very fine grained control over the rsync process: you can create a &#8220;backup key&#8221; that only allows you to rsync <em>from </em>the server and only from a specified directory. Any other command besides rsync is rejected; rsync <em>to</em> the server or from another directory is also rejected. <a href="http://blog.dest-unreach.be/wp-content/uploads/2009/06/rrsync.pl">This script</a> does it all, it&#8217;s part of the <a href="http://www.samba.org/rsync/download.html">rsync package</a>, but not installed by most distro&#8217;s. An example authorized_keys entry (with an abbreviated key):</p>
<blockquote>
<pre>command="/home/boss/niels/bin/rrsync.pl -ro /home" ssh-rsa AAAAB[...]fE+8QrME= 20090329 rsync key</pre>
</blockquote>
]]></content:encoded>
			<wfw:commentRss>http://blog.dest-unreach.be/2009/06/30/restricted-rsync-over-ssh/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>VoltCraft VC-940 protocol reverse engineered</title>
		<link>http://blog.dest-unreach.be/2009/05/01/voltcraft-vc-940-protocol-reverse-engineered</link>
		<comments>http://blog.dest-unreach.be/2009/05/01/voltcraft-vc-940-protocol-reverse-engineered#comments</comments>
		<pubDate>Fri, 01 May 2009 14:52:54 +0000</pubDate>
		<dc:creator>Niobos</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[MacOSX]]></category>
		<category><![CDATA[Perl]]></category>
		<category><![CDATA[script]]></category>

		<guid isPermaLink="false">http://blog.dest-unreach.be/?p=1119</guid>
		<description><![CDATA[I got another toy to play with: A digital multimeter with RS232 interface and True RMS power measurement. Sadly, it comes with Windows-only software, which I interpreted as a challenge! Since this is electrical measuring equipment, the serial communication should be electrically insulated from the device. The VC-940 uses a photodiode. Since the cable connecting [...]]]></description>
			<content:encoded><![CDATA[<p>I got another toy to play with: A digital multimeter with RS232 interface and True RMS power measurement. Sadly, it comes with Windows-only software, which I interpreted as a challenge!</p>
<p><span id="more-1119"></span>Since this is electrical measuring equipment, the serial communication should be electrically insulated from the device. The VC-940 uses a photodiode. Since the cable connecting the multimeter to the computer only contains an optical receiver, it is impossible for the computer to communicate with the meter. This significally reduces the complexity of a protocol.</p>
<p>This optical part showed to be the first problem. When I insert my RS-232 tester when running the Windows application, I could see data passing; under MacOSX no data would pass.  Besides showing no data, the tester also indicated that the control lines were asserted differently. By asserting the control lines the same way under MacOSX, the problem was resolved. Apparently, the voltages on the control lines are used to power the optical receiver electronics.</p>
<p>The baudrate and other settings were found by simply trying different values. When receiving at 2400bps, 8 databits, no parity and 1 stopbit (2400 8N1 for short), measurements were recorded in the Windows application.</p>
<p><a href="http://blog.dest-unreach.be/wp-content/uploads/2009/05/receive.pl">This perl-script</a> opens the specified serial port, asserts the control lines as required (RTS logical 0, positive voltage; DTS logical 1, negative voltage) and outputs the data to stdout.</p>
<h3>The message format</h3>
<p>When observing the data flow, it was clear that the device sends out a byte-string of 11 bytes roughly every second:</p>
<blockquote>
<pre>B0B0B0B0B03131B0B50D8A
B0B0B0B0B03131B0B50D8A
B0B0B031B63131B0310D8A
B0B034B3323432B3310D8A
B0B03237B53432B3310D8A
...</pre>
</blockquote>
<p>Every message seems to be terminated by 0x0D8A. I used this to synchronize the input. The following table shows what I discovered for the other bits in the message. The nibbles (4 bit group) are numbered from left to right starting from 0.</p>
<table border="0">
<tbody>
<tr>
<th>Nibble</th>
<th>Description</th>
</tr>
<tr>
<td>13</td>
<td>The measurement mode (see below)</td>
</tr>
<tr>
<td>1</td>
<td>First digit</td>
</tr>
<tr>
<td>3</td>
<td>Second digit</td>
</tr>
<tr>
<td>5</td>
<td>Third digit</td>
</tr>
<tr>
<td>7</td>
<td>Forth digit</td>
</tr>
<tr>
<td>9</td>
<td>Fifth digit (not in all modes)</td>
</tr>
<tr>
<td>11</td>
<td>Decimal point position and unit selection (depends on mode)</td>
</tr>
<tr>
<td>17 bit 0</td>
<td>Negative (1) or positive (0)</td>
</tr>
<tr>
<td>17 bit 1</td>
<td>Auto (1) or manual (0) range</td>
</tr>
<tr>
<td>15</td>
<td>AC, DC or AC+DC (depends on mode)</td>
</tr>
</tbody>
</table>
<p>Note that I didn&#8217;t figure out what every bit means&#8230;</p>
<p>The modes are listed below:</p>
<table border="0">
<tbody>
<tr>
<th>Mode</th>
<th>Description</th>
</tr>
<tr>
<td>1</td>
<td><a href="http://en.wikipedia.org/wiki/Volt">V</a> <a href="http://en.wikipedia.org/wiki/Direct_current">DC</a></td>
</tr>
<tr>
<td>2</td>
<td><a href="http://en.wikipedia.org/wiki/Volt">V</a> <a href="http://en.wikipedia.org/wiki/Alternating_current">AC</a></td>
</tr>
<tr>
<td>3</td>
<td>m<a href="http://en.wikipedia.org/wiki/Volt">V</a></td>
</tr>
<tr>
<td>4</td>
<td><a href="http://en.wikipedia.org/wiki/Ohm">Ohm</a></td>
</tr>
<tr>
<td>5</td>
<td><a href="http://en.wikipedia.org/wiki/Farad">Farad</a></td>
</tr>
<tr>
<td>6</td>
<td><a href="http://en.wikipedia.org/wiki/Celsius">ºC</a></td>
</tr>
<tr>
<td>7</td>
<td>u<a href="http://en.wikipedia.org/wiki/Ampere">A</a></td>
</tr>
<tr>
<td>8</td>
<td>m<a href="http://en.wikipedia.org/wiki/Ampere">A</a></td>
</tr>
<tr>
<td>9</td>
<td><a href="http://en.wikipedia.org/wiki/Ampere">A</a></td>
</tr>
<tr>
<td>a</td>
<td><a href="http://en.wikipedia.org/wiki/Ohm">Ohm</a> with beep</td>
</tr>
<tr>
<td>b</td>
<td><a href="http://en.wikipedia.org/wiki/Depletion_region">Diode junction voltage</a></td>
</tr>
<tr>
<td>c</td>
<td><a href="http://en.wikipedia.org/wiki/Frequency">Frequency</a> and <a href="http://en.wikipedia.org/wiki/Duty_cycle">duty cycle</a></td>
</tr>
<tr>
<td>d</td>
<td><a href="http://en.wikipedia.org/wiki/Fahrenheit">ºF</a></td>
</tr>
<tr>
<td>e</td>
<td><a href="http://en.wikipedia.org/wiki/Watt">W</a></td>
</tr>
<tr>
<td>f</td>
<td><a href="http://en.wikipedia.org/wiki/Current_loop">% of 4-20mA loop</a></td>
</tr>
</tbody>
</table>
<p><a href="http://blog.dest-unreach.be/wp-content/uploads/2009/05/decode.pl">This perl-script</a> parses the binary input (from stdin) to readable output:</p>
<blockquote>
<pre>2009-05-01-16-48-52 : 313834b5b3b0b3b0b0 :  184.53 mV
2009-05-01-16-48-53 : 3138343434b0b3b0b0 :  184.44 mV
2009-05-01-16-48-54 : 313834b534b0b3b0b0 :  184.54 mV
2009-05-01-16-48-55 : 313834b3b0b0b3b0b0 :  184.30 mV
2009-05-01-16-48-56 : 313834b037b0b3b0b0 :  184.07 mV
2009-05-01-16-48-57 : 3138b338b5b0b3b0b0 :  183.85 mV</pre>
</blockquote>
]]></content:encoded>
			<wfw:commentRss>http://blog.dest-unreach.be/2009/05/01/voltcraft-vc-940-protocol-reverse-engineered/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>SolarMax MaxTalk protocol reverse engineered</title>
		<link>http://blog.dest-unreach.be/2009/04/15/solarmax-maxtalk-protocol-reverse-engineered</link>
		<comments>http://blog.dest-unreach.be/2009/04/15/solarmax-maxtalk-protocol-reverse-engineered#comments</comments>
		<pubDate>Wed, 15 Apr 2009 16:22:32 +0000</pubDate>
		<dc:creator>Niobos</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[Perl]]></category>
		<category><![CDATA[script]]></category>

		<guid isPermaLink="false">http://blog.dest-unreach.be/?p=1023</guid>
		<description><![CDATA[At my parents place, we installed photovoltaic cells. The produced electricity is converted to AC power and is coupled with the normal grid: if we produce too little, the grid provides the remaining power; overproduction is given to the grid. The inverter (the device that converts DC into AC) is a SolarMax C-series. It has [...]]]></description>
			<content:encoded><![CDATA[<p>At my parents place, we installed <a href="http://en.wikipedia.org/wiki/Solar_cell">photovoltaic cells</a>. The produced electricity is converted to AC power and is coupled with the normal grid: if we produce too little, the grid provides the remaining power; overproduction is given to the grid.</p>
<p>The inverter (the device that converts DC into AC) is a <a href="http://www.solarmax.com/be/en/downloads/string-inverters/c-series-archive/">SolarMax C-series</a>. It has a 2-line LCD display that gives out some basic information: current, voltage, power; produced energy today, this month, this year, &#8230; This is very useful information, but is a bit hard to access. The <a href="http://docs.solarmax.com/SolarMax/Downloads/Stringinverters/Cseries/Instructionmanual/InstructionmanualSM2000CSM6000Cen/">instruction manual</a> reveals that there is a computer interface available to read out its data. Naturally, I wanted to explore this!</p>
<p><span id="more-1023"></span>The interface is physically an <a href="http://en.wikipedia.org/wiki/8P8C">8P8C</a> (usually called RJ45). Electrically it&#8217;s a serial interface. The manual isn&#8217;t exactly clear whether it&#8217;s an <a href="http://en.wikipedia.org/wiki/RS-232">RS-232</a> or an <a href="http://en.wikipedia.org/wiki/RS-485">RS-485</a> interface. After some mailing and calling, the people at <a href="http://www.solarmax.com/index.php?lng=en">Sputnik Engineering</a> just mailed us the <a href="http://blog.dest-unreach.be/wp-content/uploads/2009/04/rs-232-auf-rj-45-kabel.gif">pinout diagram</a> and <a href="http://blog.dest-unreach.be/wp-content/uploads/2009/04/rs-232-zu-rj-45-kabel-fur-solarmax-c-und-e.pdf">document</a> (both in German); it appeared to be RS-232. Their website even has a free utility called <a href="http://www.solarmax.com/be/en/products/data-communication/maxtalk-2-0/">MaxTalk</a> to read out the data!</p>
<p>The MaxTalk program is very basic. It only reads out the data, but does not process it in any way. However, it showed that the PC communicated with the inverter, which is great news!<br />
<a href="http://blog.dest-unreach.be/wp-content/uploads/2009/04/maxtalk-1.png"><img class="alignnone size-thumbnail wp-image-1028" title="maxtalk-1" src="http://blog.dest-unreach.be/wp-content/uploads/2009/04/maxtalk-1-150x150.png" alt="maxtalk-1" width="150" height="150" /></a></p>
<h3>Reverse engineering the protocol</h3>
<p>I wanted to get access to this data myself. This would allow me to run some statistics and/or graphing tools on them. I did not find any documentation on the protocol on the Internet, so I started to reverse engineer it myself.</p>
<p>I&#8217;m not sure of the legal aspect of this. Some facts to keep me safe: the software did not present a <a href="http://en.wikipedia.org/wiki/Software_license_agreement">EULA</a>; I only inspected the bytes traveling over the serial interface and did not touch the application in any way.</p>
<p>There is a wonderful tool called <a href="http://freshmeat.net/projects/socat/">socat</a> that allows me do some plumbing with a data stream: The MaxTalk application is running inside a VMware machine. The serial port of this machine is connected to a <a href="http://en.wikipedia.org/wiki/Unix_domain_socket">unix-domain socket</a> by VMware itself. Socat connects this socket to the real serial interface and spits out a copy of the stream as a bonus. You can even bridge the serial line over TCP if you want to!</p>
<p>Since RS-232 is a fairly easy protocol, the easyest way is just to try out the different settings. I figured out that the SolarMax talked at 19200bps, using 8 databits, no parity and a single stop bit (19200 8N1 for short). The corresponding socat line thus became:</p>
<blockquote>
<pre># socat -v /dev/ttyS1,b19200,cs8,parenb=0,cstopb=0 UNIX-CONNECT:/tmp/serial</pre>
</blockquote>
<p>Here is the (some of the) output I got. I re-assembled the fragments together to make it more readable:</p>
<blockquote>
<pre>&lt;  {FB;05;4E|64:E1D;E11;E1h;E1m;E1M;E2D;E21;E2h;E2m;E2M;E3D;E31;E3h;E3m;E3M|1270}
&gt;  {05;FB;7C|64:E1D=16;E11=8002;E1h=12;E1m=39;E1M=3;E2D=1C;E21=8004;E2h=E;E2m=21;
&gt;  E2M=3;E3D=6;E31=8004;E3h=10;E3m=23;E3M=4|1C4E}
--
&lt;  {FB;05;36|64:CAC;KHR;KDY;KMT;KYR;KT0;KLD;KLM;KLY|0D34}
&gt;  {05;FB;59|64:CAC=1F3E;KHR=26D6;KDY=8E;KMT=8D;KYR=221;KT0=18C7;KLD=78;KLM=F8;
&gt;  KLY=A8F|154C}
--
&lt;  {FB;05;3E|64:ADR;DDY;DMT;DYR;PIN;SWV;THR;TMI;TYP;FRD;LAN|0FC4}
&gt;  {05;FB;61|64:ADR=5;DDY=E;DMT=4;DYR=9;PIN=1428;SWV=7B;THR=13;TMI=A;TYP=BC2;
&gt;  FRD=7D60905;LAN=1|178D}</pre>
</blockquote>
<p>The socat output shows that the messages are pure <a href="http://en.wikipedia.org/wiki/ASCII">ASCII</a>, which is a lot easier to figure out than raw binary.</p>
<p>From this point on, it&#8217;s just some trail-and-error to figure out what the message format looks like, how the responses are formatted and what they mean.</p>
<h3>The message format</h3>
<p>Each message has the following format:</p>
<ul>
<li>&#8216;{&#8216; : start of message indicator</li>
<li>2 characters source address in hex</li>
<li>&#8216;;&#8217;</li>
<li>2 characters destination address in hex</li>
<li>&#8216;;&#8217;</li>
<li>2 characters message length in hex</li>
<li>&#8216;|64:&#8217;</li>
<li>data</li>
<li>&#8216;|&#8217;</li>
<li>4 characters checksum in hex</li>
<li>&#8216;}&#8217; : end of message indicator</li>
</ul>
<p>The computer seems to have address 0xFB. The SolarMax has address 0&#215;05, which is what we configured.</p>
<p>The length field is over the complete message, including the curly braces.</p>
<p>The checksum field is a standard 16-bit checksum over the body: the first character is the source address, the last character is the &#8216;|&#8217; before the checksum.</p>
<p>In messages from computer to SolarMax, the data consists of one or more question-codes, separated by a &#8216;;&#8217;. The response contains the same codes, but includes the answers after an &#8216;=&#8217; sign.</p>
<h3>The codes</h3>
<p>The meaning of the codes was largely educated guessing. Grab all known codes several times and compare what differs. Also compare this with what the Windows-interface shows.</p>
<p><a href="http://blog.dest-unreach.be/wp-content/uploads/2009/04/solarmax-test.pl">This perl-script</a> enumerates all codes that I found. I figured out the meaning of most of them.</p>
<blockquote>
<pre># ./solarmax-test.pl /dev/ttyS1 5
Opening serial port /dev/ttyS1
Setting 19200 8N1
Reading all pending bytes
Address (ADR): 5
Type (TYP): 0xBC2
Software version (SWV): 12.3
Date day (DDY): 15
Date month (DMT): 4
Date year (DYR): 9
Time hours (THR): 18
Time minutes (TMI): 11
Error 1, number (E11): 32770
Error 1, day (E1D): 22
Error 1, month (E1M): 3
Error 1, hour (E1h): 18
Error 1, minute (E1m): 57
Error 2, number (E21): 32772
Error 2, day (E2D): 28
Error 2, month (E2M): 3
Error 2, hour (E2h): 14
Error 2, minute (E2m): 33
Error 3, number (E31): 32772
Error 3, day (E3D): 6
Error 3, month (E3M): 4
Error 3, hour (E3h): 16
Error 3, minute (E3m): 35
Operating hours (KHR): 9953
Energy today [Wh] (KDY): 12900
Energy yesterday [Wh] (KLD): 14200
Energy this month [kWh] (KMT): 154
Energy last monh [kWh] (KLM): 248
Energy this year [kWh] (KYR): 558
Energy last year [kWh] (KLY): 2703
Energy total [kWh] (KT0): 6356
Language (LAN): 1
DC voltage [mV] (UDC): 344700
AC voltage [mV] (UL1): 239400
DC current [mA] (IDC): 330
AC current [mA] (IL1): 520
AC power [mW] (PAC): 89000
Power installed [mW] (PIN): 2580000
AC power [%] (PRL): 3
??? Start ups ??? (CAC): 8004
??? (FRD): 0x7D60905
??? (SCD): 0x3C
??? (SE1): 0x0
??? (SE2): 0x0
??? (SPR): 0x1
#</pre>
</blockquote>
<h3>The result</h3>
<p><img class="alignnone size-full wp-image-1061" title="sm_power20090415" src="http://blog.dest-unreach.be/wp-content/uploads/2009/04/sm_power20090415.png" alt="sm_power20090415" width="497" height="291" /></p>
<p>For those interested: the above graph (with the exception of the &#8216;Showing from [...] to [...]&#8216; lines) was generated using the following rrdtool command:</p>
<blockquote>
<pre>rrdtool --imgformat PNG --start "06:00" --end "21:00" --upper-limit 3100 --lower-limit 0 --rigid \
DEF:Pac=/var/lib/rrdtool/solarmax.1.rrd:Pac:AVERAGE \
DEF:Energy=/var/lib/rrdtool/solarmax.2.rrd:energy:AVERAGE \
VDEF:Pac_cur=Pac,LAST \
VDEF:Pac_avg=Pac,AVERAGE \
VDEF:Pac_peak=Pac,MAXIMUM \
CDEF:Pac_Wh=Pac,3600,/ \
VDEF:Eac=Pac_Wh,TOTAL \
VDEF:Eac2=Energy,TOTAL \
"AREA:Pac#0000ff:Pac    " \
"GPRINT:Pac_cur:%6.2lf%sW" \
"COMMENT:\\n" \
"HRULE:Pac_avg#bbbbff:Average" \
"GPRINT:Pac_avg:%6.2lf%sW" \
"COMMENT:\\n" \
"HRULE:Pac_peak#ff0000:Peak   " \
"GPRINT:Pac_peak:%6.2lf%sW" \
"COMMENT:\\n" \
"GPRINT:Eac:int(Pac)   %6.2lf%sWh\\n" \
"GPRINT:Eac2:meas       %6.2lf%sWh\\n" \
--vertical-label "Watt" --title "Power"</pre>
</blockquote>
<p>The total energy for the day is calculated in two ways: &#8216;int(Pac)&#8217; uses the sampled power-gauge to calculate the total; &#8216;meas&#8217; uses the energy-counter of the inverter. The latter one should be more accurate, but can&#8217;t be read out with as much precision.</p>
<h3>Update 2009-10-09</h3>
<p><a href="mailto:christian.exner@cex-development.de">Chris</a> has made <a href="http://blog.dest-unreach.be/wp-content/uploads/2009/04/solarmax-test-chris.pl">his own variant of the above Perl script</a>:</p>
<blockquote><p>Hi Niobos,</p>
<p>here we go&#8230; find attached to this mail my modification to<br />
your script (a very helpful piece of code <img src='http://blog.dest-unreach.be/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> .</p>
<p>Since i am not the perl-crack i&#8217;ve not yet implemented the<br />
command &#8220;SYS&#8221; and the translation of the returned value<br />
into a readable Operation-State.</p>
<p>At the moment i don&#8217;t know how to convert the returned<br />
value i.e. of &#8220;SYS=4E24,0&#8243; which is 20004,0 in decimal<br />
and means an &#8220;Operation at MPP&#8221;.</p>
<p>ThX&#8230;<br />
Chris</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://blog.dest-unreach.be/2009/04/15/solarmax-maxtalk-protocol-reverse-engineered/feed</wfw:commentRss>
		<slash:comments>58</slash:comments>
		</item>
		<item>
		<title>Reverse engineering the Oregon WMR928NX weather station</title>
		<link>http://blog.dest-unreach.be/2009/01/17/reverse-engineering-the-oregon-wmr928nx-weather-station</link>
		<comments>http://blog.dest-unreach.be/2009/01/17/reverse-engineering-the-oregon-wmr928nx-weather-station#comments</comments>
		<pubDate>Sat, 17 Jan 2009 15:43:19 +0000</pubDate>
		<dc:creator>Niobos</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[electronics]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[Perl]]></category>
		<category><![CDATA[script]]></category>

		<guid isPermaLink="false">http://blog.dest-unreach.be/?p=854</guid>
		<description><![CDATA[Our weather station has a serial connection and comes with Windows-software to view the weather data on your PC. The app is very eye-candy, but doesn&#8217;t do anything more than displaying the data. I&#8217;m more interested in long-term trending. So I wrote my own application to talk to the weather station and store the result [...]]]></description>
			<content:encoded><![CDATA[<p>Our weather station has a serial connection and comes with Windows-software to view the weather data on your PC. The app is very eye-candy, but doesn&#8217;t do anything more than displaying the data. I&#8217;m more interested in long-term trending. So I wrote my own application to talk to the weather station and store the result in an <a href="http://oss.oetiker.ch/rrdtool/">rrdtool</a> database.</p>
<p><span id="more-854"></span></p>
<p>Since the serial interface came with no documentation whatsoever, I had to figure everything out myself. The serial connection on the back of the weather station is a <a href="http://en.wikipedia.org/wiki/DE-9_connector">DE-9</a> connector; the manual specifies it&#8217;s an <a href="http://en.wikipedia.org/wiki/RS-232">RS232</a> output. After some trail-and-error work, I figured out that the communication happened at 9600bps, 8 databits per word, no parity and no stop-bit. <a href="http://freshmeat.net/projects/socat/">Socat</a> was happy to give the hexdump using the following command:</p>
<blockquote><p>socat -u /dev/ttyS0,b9600,cs8,parenb=0,cstopb=0,raw &#8211; | hexdump -C</p></blockquote>
<p>The bursts of data come automatically, there seems to be no need to initialize the weather station. The messages are a few bytes long each.</p>
<p>The messages look fairly similar to the ones described in <a href="http://developer.berlios.de/docman/display_doc.php?docid=86&amp;group_id=174">this document</a> (or my <a href="http://blog.dest-unreach.be/wp-content/uploads/2009/01/weatherstation-protocol.txt">mirrorred copy</a>) for the WMR918 station. <a href="http://blog.dest-unreach.be/wp-content/uploads/2009/01/oregon-parser.pl">This perl-script</a> parses the binary data from its standard input (which will probably come from a socat-pipe) and prints it in human readable form to stderr. It also tries to write the data to rrdtool for archiving, which is what I use to generate nice graphs.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.dest-unreach.be/2009/01/17/reverse-engineering-the-oregon-wmr928nx-weather-station/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Parsing an HTML website in Perl</title>
		<link>http://blog.dest-unreach.be/2008/08/21/parsing-an-html-website-in-perl</link>
		<comments>http://blog.dest-unreach.be/2008/08/21/parsing-an-html-website-in-perl#comments</comments>
		<pubDate>Thu, 21 Aug 2008 16:30:24 +0000</pubDate>
		<dc:creator>Niobos</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[EPG]]></category>
		<category><![CDATA[MythTV]]></category>
		<category><![CDATA[Perl]]></category>

		<guid isPermaLink="false">http://blog.dest-unreach.be/?p=116</guid>
		<description><![CDATA[I always wanted to know how to filter pieces of information from all the HTML-bloat surrounding it. As a proof of concept, I wrote a Perl program that parses the Skynet Electronic Program Guide and turns it into an XMLTV-file. XMLTV is a file-format used by programs like MythTV to present the on-screen program-guide and [...]]]></description>
			<content:encoded><![CDATA[<p>I always wanted to know how to filter pieces of information from all the HTML-bloat surrounding it. As a proof of concept, I wrote a Perl program that parses the <a href="http://www.skynet.be/entertainment-nl/tv/tv-gids">Skynet Electronic Program Guide</a> and turns it into an XMLTV-file. <a href="http://www.xmltv.org/">XMLTV</a> is a file-format used by programs like <a href="http://www.mythtv.org/">MythTV</a> to present the on-screen program-guide and to schedule recordings.</p>
<p><span id="more-116"></span></p>
<p>The Skynet site contains content that is protected by Intellectual Property rights. This program however is for educational purposes only; in most countries this is allowed under &#8220;fair-use&#8221;. To ensure this (and to keep me out of legal trouble), I slowed the program down to an unusable speed.</p>
<p>To figure out how it works, start by trying &#8220;./grab.pl &#8211;help&#8221;; if that doesn&#8217;t get you the answer, feel free to browse through the code.</p>
<h3>Caching</h3>
<p>When experimenting with the grabber, I figured out that the Skynet page requires your browser to revalidate each and every page it serves. Using a standard Perl HTTP-caching module was not an option, since the server disallows caching.</p>
<p>I decided to write my own caching plugin for Perl&#8217;s <a href="http://search.cpan.org/dist/libwww-perl/lib/LWP.pm">LWP module</a>. It uses the special protocol &#8220;cachedhttp://www.example.com&#8221; and is controlled through extra headers in the request. For more information use &#8220;perldoc cachedhttp.pm&#8221;.</p>
<h3>The code</h3>
<p><a href="http://blog.dest-unreach.be/wp-content/uploads/2008/08/grab.pl">grab.pl</a>: the grabber and parser itself</p>
<p><a href="http://blog.dest-unreach.be/wp-content/uploads/2008/08/cachedhttp.pm">URI/cachedhttp.pm</a>: helper module to define the cachedhttp:// URI<br />
<a href="http://blog.dest-unreach.be/wp-content/uploads/2008/08/cachedhttp1.pm">LWP/Protocol/cachedhttp.pm</a>: the real work is done here</p>
<p>I hereby release this code as <a href="http://www.gnu.org/copyleft/gpl.html">GPL</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.dest-unreach.be/2008/08/21/parsing-an-html-website-in-perl/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

