<?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>La Gentz Blog</title>
	<atom:link href="http://blog.lagentz.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.lagentz.com</link>
	<description></description>
	<lastBuildDate>Mon, 21 Nov 2011 12:21:35 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.3</generator>
		<item>
		<title>My favourite python easter-egg</title>
		<link>http://blog.lagentz.com/python/my-favourite-python-easter-egg/</link>
		<comments>http://blog.lagentz.com/python/my-favourite-python-easter-egg/#comments</comments>
		<pubDate>Mon, 21 Nov 2011 12:21:19 +0000</pubDate>
		<dc:creator>Gregor Dorfbauer</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[easter egg]]></category>
		<category><![CDATA[zen of python]]></category>

		<guid isPermaLink="false">http://blog.lagentz.com/?p=289</guid>
		<description><![CDATA[Try it! import this If you are curious and don&#8217;t have a python shell near to you: Python PEP-20/]]></description>
			<content:encoded><![CDATA[<p>Try it!</p>
<pre>
import this
</pre>
<p>If you are curious and don&#8217;t have a python shell near to you: <a href="http://www.python.org/dev/peps/pep-0020/" target="_blank">Python PEP-20/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.lagentz.com/python/my-favourite-python-easter-egg/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Usersnap launch!</title>
		<link>http://blog.lagentz.com/general/usersnap-launch/</link>
		<comments>http://blog.lagentz.com/general/usersnap-launch/#comments</comments>
		<pubDate>Mon, 07 Nov 2011 18:20:16 +0000</pubDate>
		<dc:creator>Gregor Dorfbauer</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[feedback tool]]></category>
		<category><![CDATA[launch]]></category>
		<category><![CDATA[new]]></category>
		<category><![CDATA[private beta]]></category>
		<category><![CDATA[screenshot]]></category>
		<category><![CDATA[usersnap]]></category>

		<guid isPermaLink="false">http://blog.lagentz.com/?p=278</guid>
		<description><![CDATA[Today our new product, Usersnap has been launched into private beta! Usersnap is a visual feedback tool. Just add some lines of JavaScript to your webpage and your visitors can send you annotated screenshots of your webpage. It&#8217;s perfect for &#8230; <a href="http://blog.lagentz.com/general/usersnap-launch/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a title="usersnap.com" href="http://usersnap.com" target="_blank"><img class="alignleft size-full wp-image-281" title="logohighresfinal" src="http://blog.lagentz.com/wp-content/uploads/2011/11/logohighresfinal.png" alt="" width="150" height="107" /></a>Today our new product, <a href="http://usersnap.com" target="_blank">Usersnap</a> has been launched into private beta!<br />
Usersnap is a visual feedback tool. Just add some lines of JavaScript to your webpage and your visitors can send you annotated screenshots of your webpage. It&#8217;s perfect for testing / going live of a new webpage. Immediately after a user notices an issue, he/she can send a screenshot without using external tools.</p>
<p>There is no need to install any plugins (no Flash, no 3rd party Javascript needed) and it&#8217;s completely asynchronous (it does not slow down your page in any condition).</p>
<p>Please test it (either on <a href="http://usersnap.com" target="_blank">usersnap.com</a> or directly here in the lower right corner) and feel free to request a free <a href="http://usersnap.com/signup" target="_blank">private beta account</a>!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.lagentz.com/general/usersnap-launch/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Handling SNMP Counter32 overflows on HP1810-G correctly</title>
		<link>http://blog.lagentz.com/python/handling-snmp-counter32-overflows-on-hp1810-g-correctly/</link>
		<comments>http://blog.lagentz.com/python/handling-snmp-counter32-overflows-on-hp1810-g-correctly/#comments</comments>
		<pubDate>Mon, 10 Oct 2011 13:06:10 +0000</pubDate>
		<dc:creator>Gregor Dorfbauer</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[Cisco]]></category>
		<category><![CDATA[Counter32]]></category>
		<category><![CDATA[Counter64]]></category>
		<category><![CDATA[HP1810G-24]]></category>
		<category><![CDATA[OID]]></category>
		<category><![CDATA[overflow]]></category>
		<category><![CDATA[SNMP]]></category>

		<guid isPermaLink="false">http://blog.lagentz.com/?p=262</guid>
		<description><![CDATA[Most network devices can be queried using SNMP nowadays. Luckily, even for a small HP 1810G-24 Switch, about 2000 SNMP OIDs exist &#8211; hooray for graphing. One of the most interesting graphs on a switch is bits in/out on each port. &#8230; <a href="http://blog.lagentz.com/python/handling-snmp-counter32-overflows-on-hp1810-g-correctly/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Most network devices can be queried using <a href="http://en.wikipedia.org/wiki/Simple_Network_Management_Protocol" target="blank">SNMP</a> nowadays. Luckily, even for a small HP 1810G-24 Switch, about 2000 SNMP OIDs exist &#8211; hooray for graphing.<br />
One of the most interesting graphs on a switch is bits in/out on each port.</p>
<p>The HP 1810G-24 switch does not support Counter64-types for octet counters. This post introduces a middleware to fetch the Counter32-types fast enough to build a software Counter64 object to display the correct bandwidth in a munin graph.<br />
<span id="more-262"></span><br />
The OIDs we need for this are defined in the <a href="http://tools.cisco.com/Support/SNMP/do/BrowseMIB.do?local=en&amp;step=2&amp;mibName=IF-MIB" target="_blank">IF-MIB</a> (I really like the <a href="http://tools.cisco.com/Support/SNMP/do/BrowseOID.do?objectInput=ifOutOctets&amp;translate=Translate&amp;submitValue=SUBMIT&amp;submitClicked=true" target="_blank">Cisco SNMP Object Navigator</a> for quick OID &lt;=&gt; Name conversion):</p>
<pre>
IF-MIB::ifInOctets.1 (1.3.6.1.2.1.2.2.1.10.1)
and
IF-MIB::ifOutOctets.1 (1.3.6.1.2.1.2.2.1.16.1)
</pre>
<p>Unfortunately, this values are of the SNMP type Counter32, that means they overflow every 4GB (or, at full gigabit load, approximately every 34 seconds). Fortunately, there are OIDs in a Counter64 variant:</p>
<pre>
IF-MIB::ifHCInOctets.1 (1.3.6.1.2.1.31.1.1.1.6.1)
and
IF-MIB::ifHCOutOctets.1 (1.3.6.1.2.1.31.1.1.1.10.1)
</pre>
<p>Like stated before, the HP1810G-24 (even with the newest firmware P2.2) does not support Counter64 objects.</p>
<p>However, our munin graphing fetches the values every 5 minutes (that means, only one overflow is allowed in this time period &#8211; just below 8 GB traffic in 5 minutes, otherwise aliasing occurs).</p>
<p>To support the full bandwith, we have to fetch the values at least every 34/2 = 17 seconds (according to the <a href="http://en.wikipedia.org/wiki/Sampling_theorem" target="_blank">Nyquist-Shannon sampling theorem</a>) and detect overflows ourselves. An overflow occurs, if the last value was larger than the current value, because packet counters are usually <a href="http://en.wikipedia.org/wiki/Monotonic_function" target="_blank">monotonic functions</a>.</p>
<p>That means: No overflow &#8211; just add the difference from the current value to the last value to the counter. Overflow &#8211; add the maximum number, decreased by the difference of the last value and the current value.</p>
<p>This script &#8220;switch_getcounters.py&#8221; fetches the SNMP values every 10 seconds and accumulates the counters in an external csv file. This csv file will be used instead of real SNMP GETs in the munin plugin.</p>
<pre>
#!/usr/bin/python

from pysnmp.entity.rfc3413.oneliner import cmdgen

import csv, time

name = 'hpswitch'
community = 'public'

SLEEPTIME=10
FILENAME="/tmp/switching.csv"
PORTCOUNT=24

portstatus = []
try:
    infile = file(FILENAME, "rb")
    csvread = csv.reader(infile)
    for row in csvread:
        portstatus.append({"cur_in": int(row[1]),
                            "cur_out": int(row[2]),
                            "last_in": int(row[3]),
                            "last_out": int(row[4]) })
    infile.close()
    if len(portstatus) < PORTCOUNT:
        for i in range(PORTCOUNT-len(portstatus)):
            portstatus.append({"cur_in": 0, "cur_out": 0,
                                "last_in": 0, "last_out": 0 })
except:
    portstatus = []
    for i in range(PORTCOUNT):
        portstatus.append({"cur_in": 0, "cur_out": 0,
                            "last_in": 0, "last_out": 0 })

def getBulk(host, community, oid):
    oid = tuple(map(int, oid.strip('.').split('.')))
    errorIndication, errorStatus, \
    errorIndex, varBindTable = cmdgen.CommandGenerator().bulkCmd(
        cmdgen.CommunityData('hpswitch', 'public'),
        cmdgen.UdpTransportTarget(('hpswitch', 161)),
        0, PORTCOUNT,
        oid
        )
    data = []
    if errorIndication:
        print errorIndication
    else:
        if errorStatus:
            print '%s at %s\n' % (
                errorStatus.prettyPrint(),
                errorIndex and varBinds[int(errorIndex)-1] or '?'
                )
        else:
            for varBindTableRow in varBindTable:

                for name, val in varBindTableRow:
                    data.append(int(val))
    return data

outfile = file(FILENAME, "wb")

csvwrite = csv.writer(outfile)
INT_MAX = 4294967295L

while True:
    start = time.time()
    inOct = getBulk(name, community, "1.3.6.1.2.1.2.2.1.10")[:PORTCOUNT]
    outOct = getBulk(name, community, "1.3.6.1.2.1.2.2.1.16")[:PORTCOUNT]
    outfile.seek(0)

    for i in range(len(inOct)):

        if portstatus[i]["last_in"] > inOct[i]:
            #overflow
            #print "overflow in at %s from %s to %s" % (i, portstatus[i]["last_in"], inOct[i])
            portstatus[i]["cur_in"] += INT_MAX - (portstatus[i]["last_in"] - inOct[i])
        else:
            portstatus[i]["cur_in"] += inOct[i] - portstatus[i]["last_in"]

        if portstatus[i]["last_out"] > outOct[i]:
            #overflow
            #print "overflow out at %s from %s to %s" % (i, portstatus[i]["last_out"], outOct[i])
            portstatus[i]["cur_out"] += INT_MAX - (portstatus[i]["last_out"] - outOct[i])
        else:
            portstatus[i]["cur_out"] += outOct[i] - portstatus[i]["last_out"]

        portstatus[i]["last_in"] = inOct[i]
        portstatus[i]["last_out"] = outOct[i]

        csvwrite.writerow([i+1, portstatus[i]["cur_in"],
                                portstatus[i]["cur_out"],
                                portstatus[i]["last_in"],
                                portstatus[i]["last_out"] ])

    outfile.flush()
    stop = time.time()
    sleep = SLEEPTIME - (stop-start)
    if sleep > 0:
        time.sleep(sleep)

outfile.close()
</pre>
<p>The resulting csv file can be used for every graphing tool you can imagine. The new counters last at least 5 minutes <img src='http://blog.lagentz.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> .<br />
For the full munin-example, I just re-used the Perl snmp__if_ plugin for autoconfiguration, but replaced the value-code with an external call to &#8220;readsnmp&#8221; which converts the snmp value into the munin format.</p>
<p>snmp__if_ (remove the prints for recv. and send.):</p>
<pre>
print `/usr/share/munin/plugins/readsnmp $iface`
</pre>
<p>readsnmp</p>
<pre>
#!/usr/bin/python
import csv, sys

FILENAME="/tmp/switching.csv"
try:
    infile = file(FILENAME, "rb")
    csvread = csv.reader(infile)
except:
    print "recv.value U"
    print "send.value U"
    sys.exit(1)

#munin_args = sys.argv[0].split("_")
iface = 1
try:
    if len(sys.argv) > 1:
        iface = int(sys.argv[1])
except:
    pass

i=0
out = False
for row in csvread:
    i+=1
    if i != iface:
        continue

    out = True
    print "recv.value %s" % row[1]
    print "send.value %s" % row[2]

if not out:
    print "recv.value U"
    print "send.value U"
</pre>
<p>Our nice new munin chart:<br />
<div id="attachment_268" class="wp-caption aligncenter" style="width: 310px"><a href="http://blog.lagentz.com/wp-content/uploads/2011/10/snmp_hpswitch_if_3-day.png"><img class="size-medium wp-image-268" title="Nearly 1GBit display in Munin" src="http://blog.lagentz.com/wp-content/uploads/2011/10/snmp_hpswitch_if_3-day-300x169.png" alt="" width="300" height="169" /></a><p class="wp-caption-text">Correct bandwidth display</p></div></p>
<p>Please note &#8211; if you have a switch with proper Counter64-support, just forget this workaround.<br />
Hope this helps for other HP1810G users,<br />
Gregor</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.lagentz.com/python/handling-snmp-counter32-overflows-on-hp1810-g-correctly/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Benchmarking inside virtual environments (Time is relative)</title>
		<link>http://blog.lagentz.com/general/benchmarking-inside-virtual-environments-time-is-relative/</link>
		<comments>http://blog.lagentz.com/general/benchmarking-inside-virtual-environments-time-is-relative/#comments</comments>
		<pubDate>Wed, 17 Aug 2011 14:15:20 +0000</pubDate>
		<dc:creator>Gregor Dorfbauer</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Benchmarking]]></category>
		<category><![CDATA[KVM]]></category>
		<category><![CDATA[Time]]></category>
		<category><![CDATA[VirtualBox]]></category>
		<category><![CDATA[Virtualization]]></category>

		<guid isPermaLink="false">http://blog.lagentz.com/?p=234</guid>
		<description><![CDATA[A reliable time base is needed for successful benchmarking. But what if the system&#8217;s time is correct in an absolute way, but not in a relative way? During my evaluation of different virtualization techniques I found some strange results &#8211; &#8230; <a href="http://blog.lagentz.com/general/benchmarking-inside-virtual-environments-time-is-relative/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>A reliable time base is needed for successful benchmarking. But what if the system&#8217;s time is correct in an absolute way, but not in a relative way? During my evaluation of different virtualization techniques I found some strange results &#8211; nearly four times the performance <em>inside</em> a VM on VirtualBox vs. the <em>native</em> performance of the host!</p>
<p><span id="more-234"></span>In general a benchmark works as follows: The program gets the start time and iterates a problem for a fixed (or dynamic sized) count. After the iterations, the end time is used to calculate the computations per second:<br />
#of calculations / (end &#8211; start).</p>
<p>I started to evaluate VM solutions by using a very high level benchmark &#8211; the <a href="http://v8.googlecode.com/svn/data/benchmarks/v6/run.html" target="_blank">V8 JavaScript benchmark</a>, because we want to use the virtual machines for automated client side testing, and therefore JavaScript performance matters. Those benchmarks are a little less synthetic than &#8220;SpecINT&#8221; ones, but still can be used just for comparison.</p>
<p>Just for reference, my current workstation with an Intel(R) Core(TM)2 Duo CPU E8400 @ 3.00GHz and Chrome 13.0.782.112:</p>
<div id="attachment_236" class="wp-caption alignnone" style="width: 311px"><img class="size-full wp-image-236" title="native_ubuntu10.04_core2duo 3GHz" src="http://blog.lagentz.com/wp-content/uploads/2011/08/native_ubuntu10.04_core2duo-3GHz.png" alt="" width="301" height="302" /><p class="wp-caption-text">Ubuntu 10.04 / C2D 3GHz / Chrome 13</p></div>
<p>In the next step I checked the performance of KVM (on Proxmox VE 1.8 with Kernel 2.6.35):</p>
<div id="attachment_237" class="wp-caption alignnone" style="width: 313px"><img class="size-full wp-image-237" title="kvm_winxp_i7-2600k 3.7GHz" src="http://blog.lagentz.com/wp-content/uploads/2011/08/kvm_winxp_i7-2600k-3.7GHz.png" alt="" width="303" height="303" /><p class="wp-caption-text">WinXP / i7-2600k 3.7GHz / Chrome 13</p></div>
<p>Ok, the processor is somewhat newer, therefore the virtualized value is higher than my native. Let&#8217;s compare it to VirtualBox (I use it for Desktops):</p>
<div id="attachment_240" class="wp-caption alignnone" style="width: 312px"><img class="size-full wp-image-240" title="virtualbox_winxp_core2duo 3Ghz" src="http://blog.lagentz.com/wp-content/uploads/2011/08/virtualbox_winxp_core2duo-3Ghz.png" alt="" width="302" height="302" /><p class="wp-caption-text">WinXp / C2D 3GHz / Chrome 13</p></div>
<p>Whoops? I could imagine ways how virtualized environments are faster than natives (because of IO and command reordering), but that&#8217;s nearly unbelievable. Another machine showed the same behavior:</p>
<div id="attachment_241" class="wp-caption alignnone" style="width: 312px"><img class="size-full wp-image-241" title="virtualbox_winxp_xeon 2.8 GHz" src="http://blog.lagentz.com/wp-content/uploads/2011/08/virtualbox_winxp_xeon-2.8-GHz.png" alt="" width="302" height="302" /><p class="wp-caption-text">WinXP / Xeon 2.83 GHz / Chrome 13</p></div>
<p>But wait. Remember the first paragraph of my blog post? Time is relative. If the local time inside the VM is wrong relative to other observed time stamps, the whole benchmark result is void.</p>
<p>We need an external time source to verify this assumption. This small python script checks the local time (in a very naive way) against a NTP server, please install &#8220;ntplib&#8221; first (easy_install ntplib).</p>
<pre>
import ntplib
import time
c = ntplib.NTPClient()

RUNS = 5

for SLEEPTIME in xrange(1, 6):
    for i in xrange(RUNS):
        print "Checking sleeptime %s (run %i/%i)" % (SLEEPTIME, i+1, RUNS)
        start_r = c.request('europe.pool.ntp.org', version=3).tx_time
        start_l = time.time()
        time.sleep(SLEEPTIME)
        end_l = time.time()
        end_r = c.request('europe.pool.ntp.org', version=3).tx_time

        diff_l = ((end_l - start_l) - SLEEPTIME)*1000
        diff_r = ((end_r - start_r) - SLEEPTIME)*1000

        print "Diff local: \t\t%20.4f ms\nDiff remote: \t\t%20.4f ms" % (diff_l, diff_r)
</pre>
<p>The script fetches the remote time, the local time, waits some delay, gets the local time ant the remote time again. The difference from the sleeping time is the timing jitter (on WinXP inside VirtualBox 3.2.12 r68302 on a Ubuntu Host):</p>
<pre>
C:\Python27&gt;python time_check.py
Checking sleeptime 1 (run 1/5)
Diff local:                         211.9999 ms
Diff remote:                         78.0435 ms
Checking sleeptime 1 (run 2/5)
Diff local:                         326.0000 ms
Diff remote:                         72.0148 ms
Checking sleeptime 1 (run 3/5)
Diff local:                         332.9999 ms
Diff remote:                         88.6126 ms
Checking sleeptime 1 (run 4/5)
Diff local:                         332.0000 ms
Diff remote:                        131.6137 ms
Checking sleeptime 1 (run 5/5)
Diff local:                         332.9999 ms
Diff remote:                        136.8995 ms
Checking sleeptime 2 (run 1/5)
Diff local:                         666.0001 ms
Diff remote:                        121.3775 ms
Checking sleeptime 2 (run 2/5)
Diff local:                         665.0002 ms
Diff remote:                         93.9560 ms
Checking sleeptime 2 (run 3/5)
Diff local:                         758.9998 ms
Diff remote:                        180.7289 ms
Checking sleeptime 2 (run 4/5)
Diff local:                         932.9998 ms
Diff remote:                         79.1984 ms
Checking sleeptime 2 (run 5/5)
Diff local:                         931.9999 ms
Diff remote:                         94.8648 ms
Checking sleeptime 3 (run 1/5)
Diff local:                        1399.0002 ms
Diff remote:                        112.0291 ms
Checking sleeptime 3 (run 2/5)
Diff local:                        1440.0001 ms
Diff remote:                        160.9039 ms
Checking sleeptime 3 (run 3/5)
Diff local:                        1507.0000 ms
Diff remote:                        111.6266 ms
Checking sleeptime 3 (run 4/5)
Diff local:                        1507.0000 ms
Diff remote:                        129.6673 ms
Checking sleeptime 3 (run 5/5)
Diff local:                        1506.0000 ms
Diff remote:                         91.3072 ms
Checking sleeptime 4 (run 1/5)
Diff local:                        2009.0001 ms
Diff remote:                        144.1569 ms
Checking sleeptime 4 (run 2/5)
Diff local:                        2009.0001 ms
Diff remote:                        129.6859 ms
Checking sleeptime 4 (run 3/5)
Diff local:                        2009.0001 ms
Diff remote:                        112.1640 ms
Checking sleeptime 4 (run 4/5)
Diff local:                        2008.0001 ms
Diff remote:                        134.4972 ms
Checking sleeptime 4 (run 5/5)
Diff local:                        2007.9999 ms
Diff remote:                        115.3836 ms
Checking sleeptime 5 (run 1/5)
Diff local:                        2511.0002 ms
Diff remote:                        179.2526 ms
Checking sleeptime 5 (run 2/5)
Diff local:                        2510.9999 ms
Diff remote:                        136.1961 ms
Checking sleeptime 5 (run 3/5)
Diff local:                        2510.9999 ms
Diff remote:                        206.5678 ms
Checking sleeptime 5 (run 4/5)
Diff local:                        2510.9999 ms
Diff remote:                        155.1700 ms
Checking sleeptime 5 (run 5/5)
Diff local:                        2511.0002 ms
Diff remote:                        360.1360 ms
</pre>
<p>On some runs (for example after a clean reboot) the local time diffs are in the order of milliseconds (you will notice this order on native machines, too) &#8211; the time jitter is dependent on the overall machine load.</p>
<p>I know the time sync is a hard problem for virtualization layers (See the <a href="http://www.vmware.com/files/pdf/Timekeeping-In-VirtualMachines.pdf" target="_blank">VMWare-Whitepaper on Timekeeping</a>) because most classic schedulers (read: all which are not tickless) use timer interrupts, which are somewhat artificial on virtualized environments. Because of this, external clock synchronization with the host system is needed &#8211; you should really disable NTP inside the client, because the external sync is a hard reset of clocks, while NTP tries to adjust the ticking speed (for more information, continue reading this excellent thread on stack overflow: <a href="http://stackoverflow.com/questions/117422/how-can-i-resolve-the-drifting-clock-for-my-virtual-machine">Resolve drifting time inside VMWare</a>).</p>
<p>At least I know that reliable benchmarking inside an VM is not easy. But for the next benchmarking, I should find another reference than time (for example space <img src='http://blog.lagentz.com/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' />  or external timing sources).</p>
<p>Regards,<br />
Gregor</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.lagentz.com/general/benchmarking-inside-virtual-environments-time-is-relative/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to send text messages using Python and a modem</title>
		<link>http://blog.lagentz.com/general/how-to-send-text-messages-using-python-and-a-modem/</link>
		<comments>http://blog.lagentz.com/general/how-to-send-text-messages-using-python-and-a-modem/#comments</comments>
		<pubDate>Fri, 12 Aug 2011 11:20:07 +0000</pubDate>
		<dc:creator>Florian Dorfbauer</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.lagentz.com/?p=223</guid>
		<description><![CDATA[At La Gentz we love to monitor our servers and services. We also love all the fancy warning e-mails if something is going bad at our server room. Recently we realized, there&#8217;s a single issue we can&#8217;t get warned by &#8230; <a href="http://blog.lagentz.com/general/how-to-send-text-messages-using-python-and-a-modem/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>At La Gentz we love to monitor our servers and services. We also love all the fancy warning e-mails if something is going bad at our server room.</p>
<p>Recently we realized, there&#8217;s a single issue we can&#8217;t get warned by e-mail: The <a href="http://www.youtube.com/watch?v=OqxLmLUT-qc" target="_blank">breaking</a> of the <a href="http://uk.answers.yahoo.com/question/index?qid=20070921043726AAYKvqd" target="_blank">interwebs</a> in our office (i.e. our main router crashes or someone accidentally unplugs the red cable)</p>
<p style="text-align: center;"><a href="http://blog.lagentz.com/wp-content/uploads/2011/08/IMG_0078.jpg"><img class="aligncenter" style="margin-top: 5px; margin-bottom: 5px; border: 5px solid #d3d3d3;" title="HUWAI E156G" src="http://blog.lagentz.com/wp-content/uploads/2011/08/IMG_0078.jpg" alt="This is fixing the internet" width="306" height="230" /></a></p>
<p><span id="more-223"></span></p>
<p>That&#8217;s why we decided be notified via text message in such a situation. <a href="https://www.facebook.com/stonar94" target="_blank">Thomas Steiner</a>, our summer intern wrote a nice script and a neat web-service which we now use to warn ourself if our office is loosing the internet connection.</p>
<p>We had a HUAWEI E156G mobile internet stick which is capable to send text messages.<br />
Here&#8217;s how to detect if the stick is recognized:</p>
<pre>dmesg | grep tty
# should yield something like:
option1 ttyUSB1: GSM modem (1-port) converter now attached to ttyUSB1</pre>
<p>We used minicom to talk to the modem and to check, if it does what we want (you might have to set up the correct port were your modem is connected in .minirc.dlf</p>
<pre>minicom -o
gedit .minirc.dlf</pre>
<p>Most modems &#8220;speak&#8221; AT commands, the following links were quite useful:</p>
<p><a href="http://www.developershome.com/sms/smsIntro.asp">http://www.developershome.com/sms/smsIntro.asp</a><br />
<a href="http://nobbi.com/atgsm.html">http://nobbi.com/atgsm.html</a><br />
<a href="http://www.shapeshifter.se/2008/04/30/list-of-at-commands/">http://www.shapeshifter.se/2008/04/30/list-of-at-commands/</a></p>
<p>Here&#8217;s the main python-snippet to send text messages:</p>
<pre>import serial
from curses import ascii

connection = '/dev/ttyUSB0'                    # port
pin = '1234'                                   # pin

def sendSMS(message, telephoneNumber):
    """Send a SMS"""
    ser = serial.Serial(connection, 9600, timeout=5)  # open port

    ser.write('AT+CPIN="%s"\r\n' %pin)                # PIN-Code
    ser.write('AT+CMGF=1\r\n')                        # to TEXTMODE

    ser.write('AT+CMGS="%s"\r\n' %telephoneNumber)    # tel number
    ser.write(message)                                # message
    ser.write(ascii.ctrl('z'))                        # end session

sendSMS('Fire - exclamation mark - fire - exclamation mark - \
         help me - exclamation mark. 123 Cavendon Road. Looking \
         forward to hearing from you. Yours truly, Maurice Moss.',
         '+4312345678')</pre>
<p>Since we don&#8217;t have any python on our routers, we packed this little script into a neat web-service which can now be called like:</p>
<pre>curl http://textmachina:5555/txtmsg/send/+431234567/Message</pre>
<p>We put this line in a nice shell script (including the necessary urlencoding for the message). This is quite handy, especially in busybox-situations.</p>
<p>Kudos goes to Thomas Steiner!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.lagentz.com/general/how-to-send-text-messages-using-python-and-a-modem/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using the Kinect for public User-Interfaces on Ubuntu Linux</title>
		<link>http://blog.lagentz.com/python/using-the-kinect-for-public-user-interfaces-on-ubuntu-linux/</link>
		<comments>http://blog.lagentz.com/python/using-the-kinect-for-public-user-interfaces-on-ubuntu-linux/#comments</comments>
		<pubDate>Tue, 19 Jul 2011 10:52:44 +0000</pubDate>
		<dc:creator>Gregor Dorfbauer</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[User-Interface]]></category>
		<category><![CDATA[Kinect]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[User interface]]></category>

		<guid isPermaLink="false">http://blog.lagentz.com/?p=206</guid>
		<description><![CDATA[The Microsoft Kinect is a affordable (around 100 EUR) device for natural interaction. I present a way to use the Kinect under Ubuntu Linux 10.10 (x64) as an input device for a browser remote control using OpenNI, Sensor Kinect and &#8230; <a href="http://blog.lagentz.com/python/using-the-kinect-for-public-user-interfaces-on-ubuntu-linux/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>The Microsoft Kinect is a affordable (around 100 EUR) device for natural interaction. I present a way to use the Kinect under Ubuntu Linux 10.10 (x64) as an input device for a browser remote control using OpenNI, Sensor Kinect and the NITE toolkit.<br />
Kudos goes to <a title="Mathias' Blog" href="http://www.zieglergasse.at/blog/" target="_blank">Mathias Frey</a> (Vienna University of Economics) for being cool enough to commission us with this cutting edge evaluation!</p>
<p><span id="more-206"></span>Prerequisites</p>
<p>Just install the following standard Ubuntu packages which are needed to install the 3rd party libraries:</p>
<pre>
apt-get install g++ python monodevelop libusb-1.0.0-dev \
freeglut3-dev xdotool
</pre>
<p>You can install OpenNI, Sensor Kinect and NITE by downloading them:</p>
<ol>
<li><a href="http://www.openni.org/downloadfiles/opennimodules/openni-binaries/latest-unstable/161-openni-unstable-build-for-ubuntu-10-10-x64-64-bit-v1-3-2/download">http://www.openni.org/downloadfiles/opennimodules/openni-binaries/latest-unstable/161-openni-unstable-build-for-ubuntu-10-10-x64-64-bit-v1-3-2/download</a></li>
<li><a href="https://github.com/avin2/SensorKinect">https://github.com/avin2/SensorKinect</a></li>
<li><a href="http://www.openni.org/downloadfiles/opennimodules/openni-compliant-middleware-binaries/latest-unstable/175-primesense-nite-unstable-build-for-ubuntu-10-10-x64-64-bit-v1-4-1">http://www.openni.org/downloadfiles/opennimodules/openni-compliant-middleware-binaries/latest-unstable/175-primesense-nite-unstable-build-for-ubuntu-10-10-x64-64-bit-v1-4-1</a></li>
</ol>
<p>In every extracted directory, just run</p>
<pre>
sudo ./install.sh
</pre>
<p>When installing NITE, you are asked by a key (you can use 0KOIk2JeIBYClPWVnMoRKn5cdY4= for evaluation purposes as written on the SensorKinect github page).</p>
<p>You can check your installation afterwards by starting NiViewer (located in OpenNI/Samples/Bin/Release). This will show you a depth and a color image captured from the Kinect:</p>
<p><a href="http://blog.lagentz.com/wp-content/uploads/2011/07/niviewer_room.jpg"><img class="alignnone size-medium wp-image-207" title="niviewer_room" src="http://blog.lagentz.com/wp-content/uploads/2011/07/niviewer_room-268x300.jpg" alt="" width="268" height="300" /></a></p>
<p>One interesting demo application is the hand detection from the NITE toolkit. Without calibrating your skeleton, your hand can be tracked just by waving it a few times:</p>
<p><a href="http://blog.lagentz.com/wp-content/uploads/2011/07/hand_tracking.png"><img class="alignnone size-medium wp-image-208" title="hand_tracking" src="http://blog.lagentz.com/wp-content/uploads/2011/07/hand_tracking-300x178.png" alt="" width="300" height="178" /></a></p>
<p>According to the NITE API such easy trackings can be written in little code. Just make sure to enable the context manager on the events &#8220;Wave&#8221; and &#8220;RaiseHand&#8221;:</p>
<pre>
XnStatus rc = XN_STATUS_OK;
// Create and initialize point tracker
g_pSessionManager = new XnVSessionManager;
rc = g_pSessionManager-&gt;Initialize(&amp;g_Context, "Wave",
                                      "RaiseHand");
if (rc != XN_STATUS_OK)
{
    printf("Couldn't init the Session Manager: %s\n",
        xnGetStatusString(rc));
    delete g_pSessionManager;
    return rc;
}
</pre>
<p>To use your hand as input device, just instantiate a XnVSelectableSlider2D (you could also use XnVSelectableSlider1D, but then you are limited to horizontal or vertical movements).</p>
<pre>
g_pMainSliderXY = new XnVSelectableSlider2D(1,1);
g_pMainSliderXY-&gt;RegisterValueChange(NULL,
    &amp;MainSliderXY_OnValueChange);
g_pMainSliderXY-&gt;RegisterItemSelect(NULL,
    &amp;MainSliderXY_OnSelect);
g_pMainSliderXY-&gt;RegisterActivate(NULL,
    &amp;MainSliderXY_OnActivate);
g_pMainSliderXY-&gt;RegisterDeactivate(NULL,
    &amp;MainSliderXY_OnDeactivate);
g_pMainSliderXY-&gt;RegisterPrimaryPointCreate(NULL,
    &amp;MainSliderXY_OnPrimaryCreate);
g_pMainSliderXY-&gt;RegisterPrimaryPointDestroy(NULL,
    &amp;MainSliderXY_OnPrimaryDestroy);
</pre>
<p>Inside the MainSliderXY_OnValueChange callback you can add your gesture detection, as you get the x/y value of your tracked hand.</p>
<pre>
void XN_CALLBACK_TYPE MainSliderXY_OnValueChange(
    XnFloat fxValue, XnFloat fyValue, void* cxt)
</pre>
<p>When you have detected a gesture (for example: xValue is at least some time at value 0 or similar) you can send commands to any X11-Window you can imagine.<br />
One small example sends a keystroke to a web browser (written in a small python wrapper script) &#8211; just make sure that the window is focused before you send a keystroke, as xdotool just generates raw Xevent keypresses.</p>
<pre>
import subprocess

BROWSER = "firefox"

def focus():
    p = subprocess.Popen(["xdotool", "search", "--name",
                    BROWSER],
        shell=False,stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        stdin=subprocess.PIPE)
    p.wait()
    out = p.stdout.read()
    idwin =	out.split("\n")[0]
    subprocess.call(["xdotool", "windowactivate",
            "%s" % idwin])

def send_command(command):
    print "sending command %s " %command
    subprocess.call(["xdotool", "key", "%s" % command ])
</pre>
<p>The Kinect is a great tool to develop natural interaction devices. I hope this low-level article clarifies the basics of using the SensorKinect library.</p>
<p>If you want to have a full working example, don&#8217;t hesitate to ask by email!</p>
<p>Hope this helps,<br />
Gregor</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.lagentz.com/python/using-the-kinect-for-public-user-interfaces-on-ubuntu-linux/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>La Gentz at last years SenchaCon</title>
		<link>http://blog.lagentz.com/general/la-gentz-at-last-years-sencha-con/</link>
		<comments>http://blog.lagentz.com/general/la-gentz-at-last-years-sencha-con/#comments</comments>
		<pubDate>Wed, 22 Jun 2011 14:55:33 +0000</pubDate>
		<dc:creator>Gregor Dorfbauer</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://blog.lagentz.com/?p=200</guid>
		<description><![CDATA[Have a close look at the promotional image of next years Sencha con, Florian Dorfbauer of La Gentz is presenting our ExtJS-Solutions to the experts! http://secure.lenos.com/lenos/sencha/SenchaCon2011/agenda.htm]]></description>
			<content:encoded><![CDATA[<p>Have a close look at the promotional image of next years Sencha con, Florian Dorfbauer of La Gentz is presenting our ExtJS-Solutions to the experts!</p>
<p><a title="Sencha Con Agenda" href="http://secure.lenos.com/lenos/sencha/SenchaCon2011//agenda.htm" target="_blank">http://secure.lenos.com/lenos/sencha/SenchaCon2011/agenda.htm</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.lagentz.com/general/la-gentz-at-last-years-sencha-con/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>NodeJS &#8211; parsing and transforming large XML documents</title>
		<link>http://blog.lagentz.com/nodejs/nodejs-parsing-and-transforming-large-xml-documents/</link>
		<comments>http://blog.lagentz.com/nodejs/nodejs-parsing-and-transforming-large-xml-documents/#comments</comments>
		<pubDate>Mon, 18 Apr 2011 12:45:24 +0000</pubDate>
		<dc:creator>Josef</dc:creator>
				<category><![CDATA[nodejs]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[JSON]]></category>
		<category><![CDATA[parsing]]></category>
		<category><![CDATA[rapid application development]]></category>
		<category><![CDATA[xml]]></category>

		<guid isPermaLink="false">http://blog.lagentz.com/?p=115</guid>
		<description><![CDATA[If you are working with legacy data you often get in troubles with the problem that you have large amout of data. A few weeks ago, I had to parse large XML files, extract some data, convert it, add manually &#8230; <a href="http://blog.lagentz.com/nodejs/nodejs-parsing-and-transforming-large-xml-documents/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>If you are working with legacy data you often get in troubles with the problem that you have large amout of data. A few weeks ago, I had to parse large XML files, extract some data, convert it, add manually generated data and after that save the output to a JSON file. (We need this because later this file was used as input for our own ExtJS/Sencha component).</p>
<p><span id="more-115"></span>On my development machine nodeJS is already installed. Have a look at the <a href="https://github.com/joyent/node/wiki/Installation" target="_blank">NodeJS installation guide</a>, if you want to install it yourself. Now you can write executable programs in JavaScript based on Google&#8217;s V8 engine.</p>
<p>I downloaded a <a href="https://github.com/isaacs/sax-js" target="_blank">SAX XML parser library</a> for NodeJS (written by isaacs). It&#8217;s very easy to include it into my workspace, just add a single line to include &#8220;sax.js&#8221;. The second component I need is the file system component to read the content of the XML file.</p>
<pre>var fs = require('fs');
var sax = require('./sax');</pre>
<p>First thing you have to do is creating a new instance of the parser.</p>
<pre>parser = sax.parser(strict);</pre>
<p>The parser itself is working event driven, like almost everything in NodeJS. When you are using an event driven XML parser it&#8217;s very useful to use a state-diagram &#8211; then it&#8217;s easier to grasp which type of node you are currently visiting.</p>
<p>Now there are some predefined hooks which you can use to listen for events like, open tag, close tag, etc&#8230;</p>
<pre>parser.ontext = function(t) {
   console.log('This is the text in that node: ' + t);
};</pre>
<pre>parser.onopentag = function(node) {
   //on new tag opened
};</pre>
<p>At the end the only thing you have to do is to launch the parser process. Just read the contents of the file into a String buffer (called file_buf) and then put it to the parser library.</p>
<pre>try {
    var file_buf = fs.readFileSync('./demistified.xml');
    parser.write(file_buf.toString('utf8')).close();
} catch(ex) {
    // keep 'em silent
}</pre>
<p>In the event hooks you can start to build your own data structure, NodeJS is built to parse and hold a lot of complex data. In my use case I had a file with about 20MB of XML data and I extracted out of this huge amount of data, 180 data nodes within 2 seconds.</p>
<p>At the end if you need your internal data structure (mostly you will use array and object combinations) saved to a file you can easily use the command:</p>
<pre>fs.writeFileSync('test.json', JSON.stringify(DataNodeSpace));</pre>
<p>This writes the array DataNodeSpace in JSON format to the file test.json.</p>
<p>To modify, traverse, add properties to an array or a object in JavaScript or more in NodeJS it is very fast and easy. I was totally amazed how fast you can build a XML parser (10 lines of code) and after the (more or less complex *g*) parsing algorithm run you can transform the data elements very easy and comfortable.</p>
<p>I hope now you have a little overview how to parse XML files in NodeJS.</p>
<p>Stay tuned, in the future I will have some cool stories for you dealing with NodeJS and the cooooolest database mongoDB.</p>
<p>Josef</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.lagentz.com/nodejs/nodejs-parsing-and-transforming-large-xml-documents/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>New Power Source for La Gentz Data Centers</title>
		<link>http://blog.lagentz.com/general/new-power-source-for-la-gentz-data-centers/</link>
		<comments>http://blog.lagentz.com/general/new-power-source-for-la-gentz-data-centers/#comments</comments>
		<pubDate>Fri, 01 Apr 2011 08:49:10 +0000</pubDate>
		<dc:creator>Gregor Dorfbauer</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[CO2 neutral]]></category>
		<category><![CDATA[data center]]></category>
		<category><![CDATA[Green IT]]></category>

		<guid isPermaLink="false">http://blog.lagentz.com/?p=179</guid>
		<description><![CDATA[In times of a nearing energy crisis, La Gentz tries to operate their data center as independent as possible. Because of the decrease in demand of our family&#8217;s cider products, we thought about a biogas plant, which powers our own &#8230; <a href="http://blog.lagentz.com/general/new-power-source-for-la-gentz-data-centers/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>In times of a nearing energy crisis, La Gentz tries to operate their data center as independent as possible. Because of the decrease in demand of our family&#8217;s cider products, we thought about a biogas plant, which powers our own data centers.</p>
<div id="attachment_186" class="wp-caption alignnone" style="width: 310px"><a href="http://blog.lagentz.com/wp-content/uploads/2011/04/greenit.jpg"><img class="size-medium wp-image-186" title="Green IT" src="http://blog.lagentz.com/wp-content/uploads/2011/04/greenit-300x199.jpg" alt="" width="300" height="199" /></a><p class="wp-caption-text">Green-IT</p></div>
<p><span id="more-179"></span></p>
<blockquote><p>The decrease in demand of our family&#8217;s cider products led to the idea to produce CO2-neutral energy by using cider bio gas (CBG) technology.</p>
<p>Dr. Florian Dorfbauer, CEO La Gentz</p></blockquote>
<div id="attachment_189" class="wp-caption alignnone" style="width: 325px"><a href="http://blog.lagentz.com/wp-content/uploads/2011/04/0000009bf20ee600b.jpg"><img class="size-medium wp-image-189" title="Our family's apple garden" src="http://blog.lagentz.com/wp-content/uploads/2011/04/0000009bf20ee600b-300x188.jpg" alt="" width="315" height="198" /></a><p class="wp-caption-text">Our family&#39;s apple garden</p></div>
<p>In the last year, we have planned out new biogas CHP plant with an average power of 23 Megawatt. The remainder (our data center just needs about 14 MW for today) is sold to electric distributors. We can now say, our data center is absolutely CO2-neutral.</p>
<p>Some photographs of our new plant (which started operating this week):</p>
<div id="attachment_193" class="wp-caption alignnone" style="width: 310px"><a href="http://blog.lagentz.com/wp-content/uploads/2011/04/lg_biogas_powerplant.jpg"><img class="size-medium wp-image-193" title="La Gentz CHP plant" src="http://blog.lagentz.com/wp-content/uploads/2011/04/lg_biogas_powerplant-300x224.jpg" alt="" width="300" height="224" /></a><p class="wp-caption-text">Our new 23 MW biogas plant</p></div>
<div id="attachment_191" class="wp-caption alignnone" style="width: 310px"><a href="http://blog.lagentz.com/wp-content/uploads/2011/04/dampfturbine-379296.jpg"><img class="size-medium wp-image-191" title="Turbine" src="http://blog.lagentz.com/wp-content/uploads/2011/04/dampfturbine-379296-300x195.jpg" alt="" width="300" height="195" /></a><p class="wp-caption-text">This gas turbine transforms gas energy into electric energy.</p></div>
<p><a href="http://blog.lagentz.com/wp-content/uploads/2011/04/Biogas_von_1_ha.jpg"><img class="alignnone size-medium wp-image-187" title="Biogas_von_1_ha" src="http://blog.lagentz.com/wp-content/uploads/2011/04/Biogas_von_1_ha-300x267.jpg" alt="" width="300" height="267" /></a></p>
<p>All those interested can visit our new plant on our open day on May, 1 2011. Please send a short <span class="mh-hyperlinked"><a href='http://www.google.com/recaptcha/mailhide/d?k=01Z_QclM0WAXtftYDVo_WwbQ==&c=Tgjz5h6caQ8dVDMt3f4zkCaY6R8mL8SQlbBlP1KhSfU=' onclick="window.open('http://www.google.com/recaptcha/mailhide/d?k=01Z_QclM0WAXtftYDVo_WwbQ==&amp;c=Tgjz5h6caQ8dVDMt3f4zkCaY6R8mL8SQlbBlP1KhSfU=', '', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=500,height=300'); return false;">e-mail</a></span> for registration.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.lagentz.com/general/new-power-source-for-la-gentz-data-centers/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>How to compile and build a QtWebkit application with MS Visual Studio 2008</title>
		<link>http://blog.lagentz.com/general/how-to-compile-and-build-a-qtwebkit-application-with-ms-visual-studio-2008/</link>
		<comments>http://blog.lagentz.com/general/how-to-compile-and-build-a-qtwebkit-application-with-ms-visual-studio-2008/#comments</comments>
		<pubDate>Mon, 28 Mar 2011 14:29:58 +0000</pubDate>
		<dc:creator>Michael Mayrhofer</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[browser]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Embedded]]></category>
		<category><![CDATA[Qt]]></category>
		<category><![CDATA[Visual Studio]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://blog.lagentz.com/?p=127</guid>
		<description><![CDATA[Sometimes you want to use a modern browser (read: not Internet Explorer 6.0 for instance) inside your client application, in order to display external web pages or dynamic web applications. If you want to build your own browser application QtWebkit &#8230; <a href="http://blog.lagentz.com/general/how-to-compile-and-build-a-qtwebkit-application-with-ms-visual-studio-2008/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Sometimes you want to use a modern browser (read: not Internet Explorer 6.0 for instance) inside your client application, in order to display external web pages or dynamic web applications.<br />
If you want to build your own browser application QtWebkit provides an easy to use API.</p>
<p>This Blog post provides an easy, step by step guide to integrate the Qt WebKit browser component into your client application.<span id="more-127"></span></p>
<p>1. step: Download and install the latest version of the <em>Qt libraries for VS 2008</em> from the manufacturer&#8217;s homepage (<a href="http://qt.nokia.com/downloads/">http://qt.nokia.com/downloads/</a>).</p>
<p>2. step: Run Visual Studio 2008 and create a new Qt application (e.g.: &#8220;QtWebkitApp&#8221;).</p>
<p><a href="http://blog.lagentz.com/wp-content/uploads/2011/03/VS-Qt-Project.png"><img class="alignnone size-medium wp-image-130" title="VS Qt Project" src="http://blog.lagentz.com/wp-content/uploads/2011/03/VS-Qt-Project-300x247.png" alt="" width="300" height="247" /></a></p>
<p>3. step: Set up the project settings as follows: Add the modules &#8220;network&#8221;, &#8220;ActiveQt Server&#8221;, &#8220;ActiveQt container&#8221; and &#8220;Webkit&#8221;. Now create the project.</p>
<p><a href="http://blog.lagentz.com/wp-content/uploads/2011/03/VS-Qt-Project-Settings.png"><img class="alignnone size-medium wp-image-133" title="VS Qt Project Settings" src="http://blog.lagentz.com/wp-content/uploads/2011/03/VS-Qt-Project-Settings-300x234.png" alt="" width="300" height="234" /></a></p>
<p>4. step: Open the generated header file &#8220;qtwebkitapp.h&#8221;. Add a new class &#8220;QWebView&#8221;. In the class &#8220;QtWebkitApp&#8221;, add two slots &#8220;adjustLocation&#8221; and &#8220;changeLocation&#8221; and two member variables &#8220;QLineEdit *locationEdit&#8221; and &#8220;QWebView *view&#8221;. After that the header file should look like as follows:</p>
<pre>#ifndef QTWEBKITAPP_H
#define QTWEBKITAPP_H

#include
#include "ui_qtwebkitapp.h"

//New class
class QWebView;

class QtWebkitApp : public QMainWindow
{
    Q_OBJECT

public:
    QtWebkitApp(QWidget *parent = 0, Qt::WFlags flags = 0);
    ~QtWebkitApp();

protected slots:
    //Event handler
    void adjustLocation();
    void changeLocation();

private:
    Ui::QtWebkitAppClass ui;
    //Address inputfield and browser view
    QLineEdit *locationEdit;
    QWebView *view;
};

#endif // QTWEBKITAPP_H</pre>
<p>5. step: Open the generated code file &#8220;qtwebkitapp.cpp&#8221;.</p>
<p>6. step: Include &#8220;QtGui&#8221; and &#8220;QtWebKit&#8221;.</p>
<pre>#include &lt;QtGui&gt;
#include &lt;QtWebKit&gt;</pre>
<p>7. step: Add the following code to the &#8220;QtWebkitApp&#8221; constructor to create and initialize the browser view and the toolbar.</p>
<pre>//Window title
QString titleQString = QString("La Gentz BrowserApp");
QUrl url = QUrl(QString("http://www.lagentz.com"));

//Enables the use of the platform-specific proxy settings, and only those
QNetworkProxyFactory::setUseSystemConfiguration(true);

view = new QWebView(this);
//Set attribute false to disable javascript
view-&gt;settings()-&gt;setAttribute(QWebSettings::JavascriptEnabled, true);
view-&gt;load(url);

#ifdef ENABLE_TOOLBAR
//Register callback on loadFinished event to set the address in the inputfield
connect(view, SIGNAL(loadFinished(bool)), SLOT(adjustLocation()));
locationEdit = new QLineEdit(this);
//Set the inputfield layout behaviour
locationEdit-&gt;setSizePolicy(QSizePolicy::Expanding, locationEdit-&gt;sizePolicy().verticalPolicy());
//Register callback on returnPressed event to navigate to the typed address
connect(locationEdit, SIGNAL(returnPressed()), SLOT(changeLocation()));

//Add the navigation toolbar
QToolBar *toolBar = addToolBar(tr("Navigation"));
toolBar-&gt;addAction(view-&gt;pageAction(QWebPage::Back));
toolBar-&gt;addAction(view-&gt;pageAction(QWebPage::Forward));
toolBar-&gt;addAction(view-&gt;pageAction(QWebPage::Reload));
toolBar-&gt;addAction(view-&gt;pageAction(QWebPage::Stop));
toolBar-&gt;addWidget(locationEdit);
#endif

setCentralWidget(view);
setWindowTitle(titleQString);

#ifdef WINDOW_IS_MAXIMIZED
showMaximized();
#else
//Position x, y, width and height
setGeometry(100, 100, 800, 600);
#endif</pre>
<p>8. step: Add the callback handler function for the &#8220;loadFinished&#8221; event. The event will be triggered when the website has been loaded. Then it is necessary to update the address input field.</p>
<pre>void QtWebkitApp::adjustLocation()
{
    //Set the address inputfield
    locationEdit-&gt;setText(view-&gt;url().toString());
}</pre>
<p>9. step: Add the callback handler function for the &#8220;returnPressed&#8221; event. This event will be triggered when the address inputfield has the focus and &lt;Return&gt; is pressed. Then the browser should navigate to the entered website.</p>
<pre>void QtWebkitApp::changeLocation()
{
    //Navigate to the entered address
    view-&gt;load(QUrl(locationEdit-&gt;text()));
    view-&gt;setFocus();
}</pre>
<p>10. step: Compile and run the program.</p>
<p><a href="http://blog.lagentz.com/wp-content/uploads/2011/03/BrowserWindow.png"><img class="alignnone size-medium wp-image-138" title="BrowserWindow" src="http://blog.lagentz.com/wp-content/uploads/2011/03/BrowserWindow-300x225.png" alt="" width="300" height="225" /></a></p>
<p>11. and last step: If your browser application should be able to display images, play flash videos, etc. you have to ship plugins. You can find a list of available plugins under <a href="http://doc.qt.nokia.com/stable/plugins-howto.html">http://doc.qt.nokia.com/stable/plugins-howto.html</a> -&gt; &#8220;Static Plugins&#8221;. The plugins are located in the <em>Qt libraries for VS 2008</em> install directory. Just copy them with your browser application and add the config file &#8220;qt.conf&#8221; where you specify the plugin directory. E.g.:</p>
<pre>[Paths]
Plugins = .\\plugins</pre>
<p>Enjoy your own browser application!<br />
Michael</p>
<p>Download: <a href="http://blog.lagentz.com/wp-content/uploads/2011/03/source.zip">Visual Studio project files + source code</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.lagentz.com/general/how-to-compile-and-build-a-qtwebkit-application-with-ms-visual-studio-2008/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

