<?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>jansipke.nl &#187; Programming</title>
	<atom:link href="http://www.jansipke.nl/category/programming/feed" rel="self" type="application/rss+xml" />
	<link>http://www.jansipke.nl</link>
	<description>Technology Blog</description>
	<lastBuildDate>Tue, 10 Jan 2012 09:20:42 +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>Grep lines before and after matched line</title>
		<link>http://www.jansipke.nl/grep-lines-before-and-after-matched-line</link>
		<comments>http://www.jansipke.nl/grep-lines-before-and-after-matched-line#comments</comments>
		<pubDate>Thu, 21 Jul 2011 08:26:48 +0000</pubDate>
		<dc:creator>jansipke</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Grep]]></category>

		<guid isPermaLink="false">http://www.jansipke.nl/?p=1193</guid>
		<description><![CDATA[The command grep is really useful for finding matches of a certain word in files or streams. However, until recently I didn&#8217;t know how to display lines before and after the matched line(s). Let&#8217;s say we have a file named test.txt that contains the following content: ALICE was beginning to get very tired of sitting [...]]]></description>
			<content:encoded><![CDATA[<p>The command <em>grep</em> is really useful for finding matches of a certain word in files or streams. However, until recently I didn&#8217;t know how to display lines before and after the matched line(s).</p>
<p>Let&#8217;s say we have a file named <em>test.txt</em> that contains the following content:</p>
<blockquote>
<pre>ALICE was beginning to get
very tired of sitting by
her sister on the bank
and of having nothing to do:
once or twice she had peeped
into the book her sister was reading,
but it had no pictures or conversations in it,
"and what is the use of a book," thought Alice,
"without pictures or conversations?'</pre>
</blockquote>
<p>If we use <em>grep</em> to find lines matching &#8220;bank&#8221;, we write:</p>
<blockquote>
<pre>grep bank test.txt</pre>
</blockquote>
<p>and get:</p>
<blockquote>
<pre>her sister on the bank</pre>
</blockquote>
<p>If we want to list some line(s) before the matched line, we write:</p>
<blockquote>
<pre>grep -B1 bank test.txt</pre>
</blockquote>
<p>where the 1 denotes the number of lines to list, and get:</p>
<blockquote>
<pre>very tired of sitting by
her sister on the bank</pre>
</blockquote>
<p>If we want to list some line(s) after the matched line, we write:</p>
<blockquote>
<pre>grep -A2 bank test.txt</pre>
</blockquote>
<p>where the 2 denotes the number of lines to list, and get:</p>
<blockquote>
<pre>her sister on the bank
and of having nothing to do:
once or twice she had peeped</pre>
</blockquote>
<p>The two options can be combined as well, but I leave that as an exercise to the reader <img src='http://www.jansipke.nl/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> .</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jansipke.nl/grep-lines-before-and-after-matched-line/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Temperature graphs</title>
		<link>http://www.jansipke.nl/temperature-graphs</link>
		<comments>http://www.jansipke.nl/temperature-graphs#comments</comments>
		<pubDate>Wed, 24 Nov 2010 14:22:20 +0000</pubDate>
		<dc:creator>jansipke</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Arduino]]></category>
		<category><![CDATA[S555TH]]></category>

		<guid isPermaLink="false">http://www.jansipke.nl/?p=1157</guid>
		<description><![CDATA[In a previous article we looked at remote measurement of temperature and humidity. Now it is time to show the results of the temperature measurements. First a recap of the setup: Three remote temperature and humidity sensors are located in the living room, the garage and outside. The following graph shows the output of about [...]]]></description>
			<content:encoded><![CDATA[<p>In a <a href="measuring-temperature-and-humidity-with-a-jeenode">previous article</a> we looked at remote measurement of temperature and humidity. Now it is time to show the results of the temperature measurements. First a recap of the setup:</p>
<p><a href="http://www.jansipke.nl/wp-content/uploads/temp-hygro-setup.png"><img class="alignnone size-full wp-image-1158" title="temp-hygro-setup" src="http://www.jansipke.nl/wp-content/uploads/temp-hygro-setup.png" alt="" width="511" height="155" /></a>Three remote temperature and humidity sensors are located in the living room, the garage and outside. The following graph shows the output of about 1 week:</p>
<p><a href="http://www.jansipke.nl/wp-content/uploads/temp.png"><img class="alignnone size-full wp-image-1161" title="temp" src="http://www.jansipke.nl/wp-content/uploads/temp.png" alt="" width="581" height="282" /></a>As you can see, the garage is not isolated very well. The temperature in the garage is quite similar to the temperature outside. If the weather predictions are correct, we will see temperatures below 0 degrees centigrade soon. Finally a test for the parsing of negative values!</p>
<p>Luckily, the isolation of the living room is much better than that of the garage. During the night the temperature drops only 2 degrees from 20 to 18, even though the thermostat is programmed to keep the temperature above 15 degrees. The spikes to about 25 degrees are a result of the placement of the sensor in the living room: early in the afternoon, the sun sometimes shines directly on it.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jansipke.nl/temperature-graphs/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Measuring temperature and humidity with a JeeNode</title>
		<link>http://www.jansipke.nl/measuring-temperature-and-humidity-with-a-jeenode</link>
		<comments>http://www.jansipke.nl/measuring-temperature-and-humidity-with-a-jeenode#comments</comments>
		<pubDate>Thu, 30 Sep 2010 13:46:26 +0000</pubDate>
		<dc:creator>jansipke</dc:creator>
				<category><![CDATA[Hardware]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Arduino]]></category>
		<category><![CDATA[JeeNode]]></category>
		<category><![CDATA[RX868]]></category>
		<category><![CDATA[S555TH]]></category>

		<guid isPermaLink="false">http://www.jansipke.nl/?p=1121</guid>
		<description><![CDATA[In a previous article we looked at the Arduino. Now we will look at an (almost) Arduino compatible clone, the JeeNode. It is a bit smaller and cheaper than the original version and operates at 3.3V instead of 5V. This makes it easy to connect 3.3V peripherals, such as the radio module RX868 by ELV. [...]]]></description>
			<content:encoded><![CDATA[<p>In a <a href="http://www.jansipke.nl/programming-the-arduino-ethernet-shield">previous article</a> we looked at the <a href="http://www.arduino.cc">Arduino</a>. Now we will look at an (almost) Arduino compatible clone, the <a href="http://cafe.jeelabs.net/lab/jn4/">JeeNode</a>.</p>
<p><a href="http://www.jansipke.nl/wp-content/uploads/jeenode.jpg"><img class="alignnone size-medium wp-image-1122" title="jeenode" src="http://www.jansipke.nl/wp-content/uploads/jeenode-300x85.jpg" alt="" width="300" height="85" /></a>It is a bit smaller and cheaper than the original version and operates at 3.3V instead of 5V. This makes it easy to connect 3.3V peripherals, such as the radio module <a href="http://www.elv.de/output/controller.aspx?cid=74&amp;detail=10&amp;detail2=12822&amp;flv=1&amp;bereich=&amp;marke=">RX868</a> by <a href="http://www.elv.de">ELV</a>.</p>
<p><a href="http://www.jansipke.nl/wp-content/uploads/jeenode-rx868.png"><img class="alignnone size-full wp-image-1138" title="jeenode-rx868" src="http://www.jansipke.nl/wp-content/uploads/jeenode-rx868.png" alt="" width="300" height="193" /></a>Connecting this device to the JeeNode means that we can listen to signals sent out by the temperature and humidity sensor <a href="http://produkt.conrad.de/45973183/temperatur/feuchtesensor-s555th.htm">S555TH</a>.</p>
<p><a href="http://www.jansipke.nl/wp-content/uploads/s555th.png"><img class="alignnone size-medium wp-image-1126" title="s555th" src="http://www.jansipke.nl/wp-content/uploads/s555th-300x108.png" alt="" width="300" height="108" /></a>Many thanks go out to <a href="http://jeelabs.org">JeeLabs</a> for providing the On-Off Keying (OOK) decoding used by the S555TH, and Pieter Meulenhoff for supplying me with the idea of using this sensor and initial versions of the software.</p>
<p>The S555TH transmits the following data within the S300 protocol:<a href="http://www.jansipke.nl/wp-content/uploads/TempHumid.png"><img class="alignnone size-full wp-image-1129" title="TempHumid" src="http://www.jansipke.nl/wp-content/uploads/TempHumid.png" alt="" width="645" height="60" /></a>The first byte contains the sign of the temperature value and the address of the sensor. If the first bit is &#8217;0&#8242;, the temperature sign is &#8216;+&#8217;, else it is &#8216;-&#8217;. The second to fourth bit are used for the address (1-8) of the sensor. This is used for identifying the sensor, but also helps in avoiding packet collisions. Each sensor will wait for (177 minus 0.5 * address) seconds between transmissions.</p>
<p>The second through fourth bytes contain the temperature and humidity values. For example, the humidity value is obtained by multiplying 10 with the first nibble of the fourth byte, adding the second nibble of the fourth byte, and adding 0.1 times the first nibble of the third byte.</p>
<p>In code this looks like:</p>
<blockquote>
<pre>uint8_t address = 1 + ((buf[0] &gt;&gt; 4) &amp; 0x07);
int16_t temperature = (buf[0] &gt;&gt; 7 ? -1 : 1) * (100 * (buf[2] &amp; 0x0F) + 10 * (buf[1] &gt;&gt; 4) + 1 * (buf[1] &amp; 0x0F));
uint16_t humidity = 100 * (buf[3] &gt;&gt; 4) + 10 * (buf[3] &amp; 0x0F) + 1 * (buf[2] &gt;&gt; 4);

Serial.print("S555TH: address=");
Serial.print(address, DEC);
Serial.print(" temperature=");
Serial.print(temperature / 10.0, 1);
Serial.print(" humidity=");
Serial.println(humidity / 10.0, 1);</pre>
</blockquote>
<p>Note that we multiplied the temperature and humidity values by 10 to be able to print them nicely to the serial monitor, in which we divide by 10 again.</p>
<p><a href="http://www.jansipke.nl/res/arduino/TempHumid.pde">The complete Arduino sketch can be downloaded here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jansipke.nl/measuring-temperature-and-humidity-with-a-jeenode/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Programming the Arduino ethernet shield</title>
		<link>http://www.jansipke.nl/programming-the-arduino-ethernet-shield</link>
		<comments>http://www.jansipke.nl/programming-the-arduino-ethernet-shield#comments</comments>
		<pubDate>Wed, 08 Sep 2010 20:04:18 +0000</pubDate>
		<dc:creator>jansipke</dc:creator>
				<category><![CDATA[Hardware]]></category>
		<category><![CDATA[Networking]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Arduino]]></category>

		<guid isPermaLink="false">http://www.jansipke.nl/?p=1097</guid>
		<description><![CDATA[The Arduino is an open-source electronics prototyping platform based on flexible, easy-to-use hardware and software. It features an IDE that allows you to program the Arduino using a standard USB cable. Several shields exist that extend the functionality of the standard Arduino platform. In the picture above the Arduino is shown on the left and [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.jansipke.nl/wp-content/uploads/arduino.png"><img class="alignnone size-full wp-image-1099" title="arduino" src="http://www.jansipke.nl/wp-content/uploads/arduino.png" alt="" width="400" height="150" /></a>The <a href="http://arduino.cc/">Arduino</a> is an open-source electronics prototyping platform based on flexible, easy-to-use hardware and software. It features an <a href="http://arduino.cc/en/Main/Software">IDE</a> that allows you to program the Arduino using a standard USB cable. Several shields exist that extend the functionality of the standard Arduino platform. In the picture above the Arduino is shown on the left and the ethernet shield is shown on the right.</p>
<p>The ethernet shield adds IP communication, acting as a client or as a server. The most well-known protocols are supported right out of the box, including TCP, UDP and ICMP. Several enthousiasts have added support for even more protocols, such as DHCP and NTP.</p>
<p>Creating programs for the Arduino with the ethernet shield is simple:</p>
<blockquote>
<pre>#include 

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 10, 0, 0, 177 };
byte server[] = { 64, 233, 187, 99 }; // Google

Client client(server, 80);

void setup()
{
   Ethernet.begin(mac, ip);
   Serial.begin(9600);

   delay(1000);

   Serial.println("connecting...");

   if (client.connect()) {
      Serial.println("connected");
      client.println("GET /search?q=arduino HTTP/1.0");
      client.println();
   } else {
      Serial.println("connection failed");
   }
}

void loop()
{
   if (client.available()) {
      char c = client.read();
      Serial.print(c);
   }

   if (!client.connected()) {
      Serial.println();
      Serial.println("disconnecting.");
      client.stop();
      for(;;)
         ;
   }
}
</pre>
</blockquote>
<p>Every Arduino program has at least two parts: a <em>setup()</em> function and a <em>loop()</em> function. The Arduino IDE creates an actual proper C program around these two functions before it uploads the complete program to the Arduino.</p>
<p><a href="http://www.jansipke.nl/wp-content/uploads/serial-monitor.png"><img class="alignnone size-full wp-image-1110" title="serial-monitor" src="http://www.jansipke.nl/wp-content/uploads/serial-monitor.png" alt="" width="203" height="107" /></a>The Arduino IDE contains a serial monitor, which allows you to send strings to the Arduino program or receive strings from it. The example program above shows how the <em>Serial</em> class works. In the <em>setup() </em>function, the serial communication is started at 9600 baud. In the <em>loop()</em> function, data is sent over the serial line with the method <em>Serial.print()</em>. If the serial line is actually connected, the program on the Arduino will halt until the serial monitor is opened. If the serial line is not connected, e.g. when you are done debugging, the program will run normally.</p>
<p>The ethernet library contains the <em>Ethernet</em> class. In the <em>setup()</em> function, the ethernet stack is started with <em>Ethernet.begin(mac, ip)</em>. The <em>mac</em> and <em>ip</em> parameters are both byte arrays. If only these two parameters are present and the IP address has the form <em>a.b.c.d</em>, the gateway is assumed to be <em>a.b.c.1</em> and the subnetmask is assumed to be <em>255.255.255.0</em>. There are other constructors that take one or two extra parameters for people with different network setups.</p>
<p>After ethernet initialization, the class <em>Client</em> is used to create a TCP connection to the supplied server IP address and port number. The <em>Client.connect()</em> method tries to connect to the server and a call to <em>Client.println()</em> sends data over the TCP connection to the server. The <em>Client.available()</em> method tells if the server has sent data over the TCP connection to our client. If it has, a call to <em>Client.read()</em> gives these bytes.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jansipke.nl/programming-the-arduino-ethernet-shield/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Model View Controller (MVC) with JSP and JSTL</title>
		<link>http://www.jansipke.nl/model-view-controller-mvc-with-jsp-and-jstl</link>
		<comments>http://www.jansipke.nl/model-view-controller-mvc-with-jsp-and-jstl#comments</comments>
		<pubDate>Tue, 20 Jul 2010 07:28:32 +0000</pubDate>
		<dc:creator>jansipke</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[JSP]]></category>
		<category><![CDATA[JSTL]]></category>
		<category><![CDATA[MVC]]></category>

		<guid isPermaLink="false">http://www.jansipke.nl/?p=1069</guid>
		<description><![CDATA[In this article we will create a small web application that uses the Model View Controller (MVC) pattern with Java Server Pages (JSP) and JSP Standard Template Library (JSTL). A container like Tomcat is needed to run this combination. Thanks go out to the author of the JSP &#8211; MVC Tutorial, who thought of the [...]]]></description>
			<content:encoded><![CDATA[<p>In this article we will create a small web application that uses the <a href="http://en.wikipedia.org/wiki/Model-view-controller">Model View Controller (MVC)</a> pattern with <a href="http://java.sun.com/products/jsp/">Java Server Pages (JSP)</a> and <a href="http://java.sun.com/products/jsp/jstl/">JSP Standard Template Library (JSTL)</a>. A container like <a href="http://tomcat.apache.org/">Tomcat</a> is needed to run this combination.</p>
<p>Thanks go out to the author of the <a href="http://www.datadisk.co.uk/html_docs/jsp/jsp_mvc_tutorial.htm">JSP &#8211; MVC Tutorial</a>, who thought of the sample application that we will use here, the coffee advisor. The user is first presented with a choice in coffee taste she prefers. Pressing a button moves on to a page with advise about the type of coffee to drink based on that taste.</p>
<p>An MVC application has three parts:</p>
<p><a href="http://www.jansipke.nl/wp-content/uploads/mvc.png"><img class="alignnone size-full wp-image-1081" title="mvc" src="http://www.jansipke.nl/wp-content/uploads/mvc.png" alt="" width="447" height="250" /></a></p>
<ul>
<li>Model. The model is the domain-specific representation of the data upon which  the application operates. In our case this is implemented in the <em>CoffeeExpert</em> class.</li>
<li>View. The view renders the model into a form suitable for interaction,  typically a user interface element. In our case this is implemented in a JSP file called <em>coffee.jsp</em>.</li>
<li>Controller. The controller receives input and initiates a response by making calls on model objects. In our case this is implemented in the <em>CoffeeSelect</em> class.</li>
</ul>
<p>In addition to these three file we need a <em>web.xml</em> file that tells the container how to map a URL (e.g. <em>/CoffeeSelect.do</em>) into a class to run (e.g. <em>com.example.web.CoffeeSelect</em>). We also need a start page for the user input, which we will call <em>coffee.html</em>. In total this means we should create a  <em>.war</em> file with the following structure:<br />
<a href="http://www.jansipke.nl/wp-content/uploads/coffee-advisor-war.png"><img class="alignnone size-full wp-image-1075" title="coffee-advisor-war" src="http://www.jansipke.nl/wp-content/uploads/coffee-advisor-war.png" alt="" width="243" height="198" /></a></p>
<p><strong>coffee.html</strong></p>
<blockquote>
<pre>&lt;html&gt;
    &lt;body&gt;
        &lt;h2&gt;Coffee Advisor Input&lt;/h2&gt;
        &lt;form method="POST" action="CoffeeSelect.do"&gt;
            &lt;select name="taste" size=1"&gt;
                &lt;option value="milky"&gt;Milky&lt;/option&gt;
                &lt;option value="froffy"&gt;Froffy&lt;/option&gt;
                &lt;option value="icey"&gt;Icey&lt;/option&gt;
                &lt;option value="strong"&gt;Spaced Out&lt;/option&gt;
            &lt;/select&gt;
            &lt;br/&gt;&lt;br/&gt;
            &lt;input type="Submit"/&gt;
        &lt;/form&gt;
    &lt;/body&gt;
&lt;/html&gt;
</pre>
</blockquote>
<p><strong>CoffeeExpert.java</strong></p>
<blockquote>
<pre>package com.example.model;

import java.util.*;

public class CoffeeExpert {
    public List&lt;String&gt; getTypes(String taste) {
        List&lt;String&gt; result = new ArrayList&lt;String&gt;();
        if (taste.equals("milky")) {
            result.add("Latte");
            result.add("Cappuccino");
        } else if (taste.equals("froffy")) {
            result.add("Latte");
            result.add("Cappuccino");
            result.add("Frappuccino");
        } else if (taste.equals("icey")) {
            result.add("Frappuccino");
        } else if (taste.equals("strong")) {
            result.add("Espresso");
            result.add("Double espresso");
        } else {
            result.add("Vending machine");
        }
        return (result);
    }
}
</pre>
</blockquote>
<p><strong>CoffeeSelect.java</strong></p>
<blockquote>
<pre>package com.example.web;

import java.io.IOException;
import java.util.List;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.example.model.CoffeeExpert;

public class CoffeeSelect extends HttpServlet {

    private static final long serialVersionUID = 1L;

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
        List&lt;String&gt; types = new CoffeeExpert().getTypes(request.getParameter("taste"));
        request.setAttribute("types", types);
        RequestDispatcher view = request.getRequestDispatcher("coffee.jsp");
        view.forward(request, response);
    }
}
</pre>
</blockquote>
<p><strong>coffee.jsp</strong></p>
<blockquote>
<pre>&lt;%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %&gt;

&lt;html&gt;
    &lt;body&gt;
        &lt;h2&gt;Coffee Advisor Output&lt;/h2&gt;
        &lt;c:forEach var="type" items="${types}"&gt;
            &lt;c:out value="${type}"/&gt;
            &lt;br /&gt;
        &lt;/c:forEach&gt;
    &lt;/body&gt;
&lt;/html&gt;
</pre>
</blockquote>
<p><strong>web.xml</strong></p>
<blockquote>
<pre>&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;
&lt;web-app xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
    version="2.4"&gt;

    &lt;servlet&gt;
        &lt;servlet-name&gt;Coffee&lt;/servlet-name&gt;
        &lt;servlet-class&gt;com.example.web.CoffeeSelect&lt;/servlet-class&gt;
    &lt;/servlet&gt;

    &lt;servlet-mapping&gt;
        &lt;servlet-name&gt;Coffee&lt;/servlet-name&gt;
        &lt;url-pattern&gt;/CoffeeSelect.do&lt;/url-pattern&gt;
    &lt;/servlet-mapping&gt;
&lt;/web-app&gt;
</pre>
</blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.jansipke.nl/model-view-controller-mvc-with-jsp-and-jstl/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Changing CPU and memory settings on XenServer VMs</title>
		<link>http://www.jansipke.nl/changing-cpu-and-memory-settings-on-xenserver-vms</link>
		<comments>http://www.jansipke.nl/changing-cpu-and-memory-settings-on-xenserver-vms#comments</comments>
		<pubDate>Tue, 08 Jun 2010 15:33:18 +0000</pubDate>
		<dc:creator>jansipke</dc:creator>
				<category><![CDATA[Cloud computing]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[XenServer]]></category>

		<guid isPermaLink="false">http://www.jansipke.nl/?p=1057</guid>
		<description><![CDATA[You can change the CPU and memory settings of XenServer virtual machines using the API. XenServer allows you to set the priority of the virtual machine CPU (called weight), set a limit on the amount of CPU the virtual machine can use (called cap) and set the amount of memory the virtual machine gets. CPU [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.jansipke.nl/wp-content/uploads/xenserver.png"><img class="alignnone size-full wp-image-940" title="xenserver" src="http://www.jansipke.nl/wp-content/uploads/xenserver.png" alt="" width="327" height="61" /></a></p>
<p>You can change the CPU and memory settings of XenServer virtual machines using the API. XenServer allows you to set the priority of the virtual machine CPU (called <em>weight</em>), set a limit on the amount of CPU the virtual machine can use (called <em>cap</em>) and set the amount of memory the virtual machine gets.</p>
<p><strong>CPU priority</strong></p>
<p>You can set the <em>weight</em> parameter to a number between 1 and 65536. The default value is 256, meaning normal priority. A virtual machine with a weight of 512 will get twice as much CPU as a virtual machine with a weight of 256 on a contended XenServer host. The following code sets the <em>weight</em> to 128, meaning that it will get half as much CPU as a normal virtual machine.</p>
<blockquote>
<pre>Map&lt;String, String&gt; vcpuParameters = new HashMap&lt;String, String&gt;();
vcpuParameters.put("weight", "128");
vm.setVCPUsParams(connection, vcpuParameters);
</pre>
</blockquote>
<p><strong>CPU limit</strong></p>
<p>You can set the <em>cap</em> parameter to a percentage number. The default value is 0, meaning there is no cap. The value 100 represents one virtual CPU, so half a virtual CPU can be set by using the value 50. The following code sets the <em>cap</em> to 35, meaning that it will not get more than 35 percent of one virtual CPU, even if the physical CPU is not used to its top.</p>
<blockquote>
<pre>Map&lt;String, String&gt; vcpuParameters = new HashMap&lt;String, String&gt;();
vcpuParameters.put("cap", "35");
vm.setVCPUsParams(connection, vcpuParameters);
</pre>
</blockquote>
<p><strong>Memory</strong></p>
<p>You can set the amount of memory assigned to a virtual machine in bytes. The following code sets the amount of memory to 1 GB (1,073,741,824 bytes).</p>
<blockquote>
<pre>vm.setMemoryStaticMax(connection, new Long(1073741824));
</pre>
</blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.jansipke.nl/changing-cpu-and-memory-settings-on-xenserver-vms/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Installing Sun JDK 6 on Ubuntu 10.04</title>
		<link>http://www.jansipke.nl/installing-sun-jdk-6-on-ubuntu-10-04</link>
		<comments>http://www.jansipke.nl/installing-sun-jdk-6-on-ubuntu-10-04#comments</comments>
		<pubDate>Thu, 27 May 2010 13:21:32 +0000</pubDate>
		<dc:creator>jansipke</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://www.jansipke.nl/?p=1005</guid>
		<description><![CDATA[The Sun JDK can be installed on Ubuntu by adding a repository and installing with apt-get. The following works with the latest versions of both at the time of writing: Sun JDK 6 update 20 Ubuntu 10.04 sudo add-apt-repository "deb http://archive.canonical.com/ lucid partner" sudo apt-get update sudo apt-get install sun-java6-jdk If the command add-apt-repository is [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.jansipke.nl/wp-content/uploads/java-ubuntu.png"><img class="alignnone size-full wp-image-1013" title="java-ubuntu" src="http://www.jansipke.nl/wp-content/uploads/java-ubuntu.png" alt="" width="180" height="46" /></a></p>
<p>The Sun JDK can be installed on Ubuntu by adding a repository and installing with apt-get. The following works with the latest versions of both at the time of writing:</p>
<ul>
<li><a href="http://java.sun.com/javase/downloads/index.jsp">Sun JDK 6 update 20</a></li>
<li><a href="http://www.ubuntu.com/">Ubuntu 10.04</a></li>
</ul>
<blockquote>
<pre>sudo add-apt-repository "deb http://archive.canonical.com/ lucid partner"
sudo apt-get update
sudo apt-get install sun-java6-jdk
</pre>
</blockquote>
<p>If the command <em>add-apt-repository</em> is missing, install it with the following command:</p>
<blockquote>
<pre>sudo apt-get install python-software-properties
</pre>
</blockquote>
<p>With the <em>alternatives</em> system in place, the Java executable is automatically available:</p>
<blockquote>
<pre>/usr/bin/java -&gt; /etc/alternatives/java
/etc/alternatives/java -&gt; /usr/lib/jvm/java-6-sun/jre/bin/java
</pre>
</blockquote>
<p>Setting up JAVA_HOME can now be done by editing <em>/etc/profile</em> and adding to the bottom:</p>
<blockquote>
<pre>export JAVA_HOME=/usr/lib/jvm/java-6-sun
</pre>
</blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.jansipke.nl/installing-sun-jdk-6-on-ubuntu-10-04/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Getting CPU, memory, disk and network metrics from XenServer</title>
		<link>http://www.jansipke.nl/getting-cpu-memory-disk-and-network-metrics-from-xenserver</link>
		<comments>http://www.jansipke.nl/getting-cpu-memory-disk-and-network-metrics-from-xenserver#comments</comments>
		<pubDate>Sat, 08 May 2010 18:56:20 +0000</pubDate>
		<dc:creator>jansipke</dc:creator>
				<category><![CDATA[Cloud computing]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[XenServer]]></category>

		<guid isPermaLink="false">http://www.jansipke.nl/?p=978</guid>
		<description><![CDATA[In a previous article we looked at getting CPU and memory metrics from XenServer. As noted in that article, as of version 5.5 of XenServer, the preferred way of getting virtual machine metrics is through HTTP calls to get RRD XML files. We showed how to revert to the old way of doing things, but [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.jansipke.nl/wp-content/uploads/metrics1.png"><img class="alignnone size-full wp-image-1001" title="metrics" src="http://www.jansipke.nl/wp-content/uploads/metrics1.png" alt="" width="630" height="116" /></a></p>
<p>In a <a href="http://www.jansipke.nl/getting-xenserver-vm-metrics-in-java">previous article</a> we looked at getting CPU and memory metrics from XenServer. As noted in that article, as of version 5.5 of XenServer, the preferred way of getting virtual machine metrics is through HTTP calls to get RRD XML files. We showed how to revert to the old way of doing things, but in this article we will look into the new, preferred way. This has the added benefit that disk and network metrics are also available, along with a history of metrics.</p>
<p>The first thing to note is that the metrics are not available through the XenServer API. The RRD XML files are stored on the physical machines that currently host the virtual machines. For example, if you have two physical machines (P1 and P2) with two virtual machines running on each of them (V1a, V1b, V2a and V2b), you need to query P1 for the metrics of V1a and V1b and query P2 for the metrics of V2a and V2b. If a virtual machine is not running at the moment, you can get the (old) metrics from the master in the pool.</p>
<p>Each physical machine has an HTTP interface at the following location:</p>
<blockquote>
<pre>http://machine_name_or_ip/rrd_updates?start=1234567890
</pre>
</blockquote>
<p>The parameter <em>start</em> tells the server to only give metrics starting at this timestamp (seconds since January 1st 1970). The call requires a username and password, which will be asked if you connect through a webbrowser. The following code does this in Java:</p>
<blockquote>
<pre>Connection connection = new Connection(new URL(MASTER_HOST));
Session.loginWithPassword(connection, USERNAME, PASSWORD, APIVersion.latest().toString());

Map hostRecords = Host.getAllRecords(connection);
for (Host host : hostRecords.keySet()) {
    URL url = new URL("http://" + host.getAddress(connection) + "/rrd_updates?start=" + (System.currentTimeMillis() / 1000 - TIME_WINDOW));
    URLConnection urlConnection = url.openConnection();
    String encoding = new BASE64Encoder().encode((USERNAME + ":" + PASSWORD).getBytes());
    urlConnection.setRequestProperty ("Authorization", "Basic " + encoding);

    String rrdXportData = IOUtils.toString(urlConnection.getInputStream());
}
</pre>
</blockquote>
<p>The code needs two libraries:</p>
<ul>
<li><em>commons-io-1.4.jar</em>. This package contains the code to get a string containing the data of an inputstream.</li>
<li><em>xenserver-5.5.0-1.jar</em>. This package contains the code to connect to the XenServer pool.</li>
</ul>
<p>The following constants are used in this piece of code and need to be filled in:</p>
<ul>
<li><em>MASTER_HOST</em>. This is the IP address or hostname of the master host in the pool.</li>
<li><em>TIME_WINDOW</em>. XenServer will return RRD updates of the last <em>TIME_WINDOW</em> seconds.</li>
<li><em>USERNAME </em>and <em>PASSWORD</em>. These are the credentials for connecting to the master host and the other physical hosts in the pool.</li>
</ul>
<p>At the end of this piece of code we have the string <em>rrdXportData</em> containing the RRD XML data. Now we need to parse this data to get the metrics we want. The following listing contains the most important parts of this string (edited for clarity):</p>
<blockquote>
<pre>&lt;xport&gt;
   &lt;meta&gt;
      &lt;start&gt;1273342925&lt;/start&gt;
      &lt;step&gt;5&lt;/step&gt;
      &lt;end&gt;1273342980&lt;/end&gt;
      &lt;rows&gt;13&lt;/rows&gt;
      &lt;columns&gt;31&lt;/columns&gt;
      &lt;legend&gt;
         &lt;entry&gt;AVERAGE:vm:19ef51bd-2cbc-50d1-3fa2-ad8878699203:cpu0&lt;/entry&gt;
         &lt;entry&gt;AVERAGE:vm:19ef51bd-2cbc-50d1-3fa2-ad8878699203:vif_4_tx&lt;/entry&gt;
         ...
      &lt;/legend&gt;
   &lt;/meta&gt;
   &lt;data&gt;
      &lt;row&gt;
         &lt;t&gt;1273342980&lt;/t&gt;
         &lt;v&gt;0.0002&lt;/v&gt;
         &lt;v&gt;0.0&lt;/v&gt;
         ...
      &lt;/row&gt;
      &lt;row&gt;
         &lt;t&gt;1273342975&lt;/t&gt;
         &lt;v&gt;0.0003&lt;/v&gt;
         &lt;v&gt;0.0&lt;/v&gt;
         ...
      &lt;/row&gt;
      ...
   &lt;/data&gt;
&lt;/xport&gt;
</pre>
</blockquote>
<p>The following Java code will parse this RRD XML string and make it available in the four variables shown at the top. The variable <em>metricsTimelines</em> contains a hashmap of string to double[]. The string is the metric name (e.g. <em>AVERAGE:vm:19ef51bd-2cbc-50d1-3fa2-ad8878699203:cpu0</em>) and the double[] contains the values for this metric from <em>startTime</em> to <em>endTime</em> with a step size of <em>step</em>. Note that the value at <em>endTime</em> is at position 0 and the value at  <em>startTime</em> is at the end of the array.</p>
<blockquote>
<pre>int endTime = 0;
HashMap&lt;String, double[]&gt; metricsTimelines = null;
int startTime = 0;
int step = 0;

try {
   DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
   domFactory.setNamespaceAware(true);
   DocumentBuilder builder = domFactory.newDocumentBuilder();
   StringReader stringReader = new StringReader(rrdXportData);
   InputSource inputSource = new InputSource(stringReader);
   Document doc = builder.parse(inputSource);
   stringReader.close();

   ArrayList&lt;ArrayList&lt;String&gt;&gt; dataRows = new ArrayList&lt;ArrayList&lt;String&gt;&gt;();
   ArrayList&lt;String&gt; legends = new ArrayList&lt;String&gt;();
   NodeList xportChildNodes = doc.getDocumentElement().getChildNodes();
   for (int i = 0; i &lt; xportChildNodes.getLength(); i++) {
      Node xportChildNode = xportChildNodes.item(i);
      if (xportChildNode.getNodeName().equals("meta")) {
         NodeList metaChildNodes = xportChildNode.getChildNodes();
         for (int j = 0; j &lt; metaChildNodes.getLength(); j++) {
            Node metaChildNode = metaChildNodes.item(j);
            if (metaChildNode.getNodeName().equals("step")) {
               step = new Integer(metaChildNode.getTextContent()).intValue();
            } else if (metaChildNode.getNodeName().equals("start")) {
               startTime = new Integer(metaChildNode.getTextContent()).intValue();
            } else if (metaChildNode.getNodeName().equals("end")) {
               endTime = new Integer(metaChildNode.getTextContent()).intValue();
            } else if (metaChildNode.getNodeName().equals("legend")) {
               NodeList legendChildNodes = metaChildNode.getChildNodes();
               for (int k = 0; k &lt; legendChildNodes.getLength(); k++) {
                  Node legendChildNode = legendChildNodes.item(k);
                  legends.add(k, legendChildNode.getTextContent());
               }
            }
         }
      } else if (xportChildNode.getNodeName().equals("data")) {
         NodeList dataChildNodes = xportChildNode.getChildNodes();
         for (int j = 0; j &lt; dataChildNodes.getLength(); j++) {
            Node rowNode = dataChildNodes.item(j);
            NodeList rowChildNodes = rowNode.getChildNodes();
            ArrayList&lt;String&gt; dataRow = new ArrayList&lt;String&gt;();
            for (int k = 1; k &lt; rowChildNodes.getLength(); k++) {
               Node rowChildNode = rowChildNodes.item(k);
               dataRow.add(k - 1, rowChildNode.getTextContent());
            }
            dataRows.add(dataRow);
         }
      }
   }

   int nrDataRows = dataRows.size();
   int nrLegends = legends.size();

   metricsTimelines = new HashMap&lt;String, double[]&gt;();
   for (int i = 0; i &lt; nrLegends; i++) {
      metricsTimelines.put(legends.get(i), new double[nrDataRows]);
   }
   for (int i = 0; i &lt; nrLegends; i++) {
      for (int j = 0; j &lt; nrDataRows; j++) {
         double[] values = metricsTimelines.get(legends.get(i));
         values[j] = new Double(dataRows.get(j).get(i)).doubleValue();
      }
   }
} catch (Exception e) {
   e.printStackTrace();
}
</pre>
</blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.jansipke.nl/getting-cpu-memory-disk-and-network-metrics-from-xenserver/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Using Google Visualization API with own data source</title>
		<link>http://www.jansipke.nl/using-google-visualization-api-with-own-data-source</link>
		<comments>http://www.jansipke.nl/using-google-visualization-api-with-own-data-source#comments</comments>
		<pubDate>Mon, 29 Mar 2010 18:18:18 +0000</pubDate>
		<dc:creator>jansipke</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Google Visualization]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.jansipke.nl/?p=946</guid>
		<description><![CDATA[The Google Visualization API allows you to create charts and maps based on data you provide. This data can be in a Google Spreadsheet or be something you provide yourself. The visualizations themselves are mostly written in Javascript, although there are some written in Flash. In this article we will create an HTML page with [...]]]></description>
			<content:encoded><![CDATA[<p>The <a href="http://code.google.com/apis/visualization/interactive_charts.html">Google Visualization API</a> allows you to create charts and maps based on data you provide. This data can be in a Google Spreadsheet or be something you provide yourself. The visualizations themselves are mostly written in Javascript, although there are some written in Flash.</p>
<p><a href="http://www.jansipke.nl/wp-content/uploads/visualization.png"><img class="alignnone size-full wp-image-963" title="visualization" src="http://www.jansipke.nl/wp-content/uploads/visualization.png" alt="" width="631" height="219" /></a></p>
<p>In this article we will create an <a href="http://www.jansipke.nl/res/visualization/index.html">HTML page with multiple charts in it</a> and a <a href="http://jansipke.nl/res/visualization/chart-data.py">data source that is generated by a Python program</a>. We start with the HTML page that has two named div&#8217;s in it (<em>visualization1</em> and <em>visualization2</em>), including the Javascript code that loads the two charts into these div&#8217;s.</p>
<blockquote>
<pre>&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&gt;
&lt;html xmlns="http://www.w3.org/1999/xhtml"&gt;
   &lt;head&gt;
      &lt;meta http-equiv="content-type" content="text/html; charset=utf-8"/&gt;
      &lt;title&gt;
         Google Visualization API
      &lt;/title&gt;
      &lt;script type="text/javascript" src="http://www.google.com/jsapi"&gt;&lt;/script&gt;
      &lt;script type="text/javascript"&gt;
         google.load('visualization', '1', {packages: ['columnchart', 'linechart']});
      &lt;/script&gt;
      &lt;script type="text/javascript"&gt;

         var query1, visualization1;
         var query2, visualization2;

         function initialize() {
            visualization1 = new google.visualization.ColumnChart(document.getElementById('visualization1'));
            query1 = new google.visualization.Query('http://jansipke.nl/res/visualization/chart-data.py');
            query1.setRefreshInterval(5);
            query1.send(drawVisualization1);

            visualization2 = new google.visualization.LineChart(document.getElementById('visualization2'));
            query2 = new google.visualization.Query('http://jansipke.nl/res/visualization/chart-data.py');
            query2.setRefreshInterval(5);
            query2.send(drawVisualization2);
         }

         function drawVisualization1(response) {
            if (response.isError()) {
               alert('Error in query: ' + response.getMessage() + ' ' + response.getDetailedMessage());
               return;
            }
            visualization1.draw(response.getDataTable(), {legend: 'bottom', title: 'ColumnChart'});
         }

         function drawVisualization2(response) {
            if (response.isError()) {
               alert('Error in query: ' + response.getMessage() + ' ' + response.getDetailedMessage());
               return;
            }
            visualization2.draw(response.getDataTable(), {legend: 'bottom', title: 'LineChart'});
         }

         google.setOnLoadCallback(initialize);
      &lt;/script&gt;
   &lt;/head&gt;
   &lt;body&gt;
      &lt;div&gt;
         &lt;div id="visualization1" style="height: 250px; width: 400px; border: 1px solid; float: left;" /&gt;
      &lt;/div&gt;
      &lt;div&gt;
         &lt;div id="visualization2" style="height: 250px; width: 400px; border: 1px solid; float: left; margin-left: 10px" /&gt;
      &lt;/div&gt;
   &lt;/body&gt;
&lt;/html&gt;
</pre>
</blockquote>
<p>There are two things that you <strong>really</strong> need to do before this works correctly:</p>
<ul>
<li>Make sure that the parent node of the div that holds your chart, is not also the parent of one of the other div&#8217;s that holds a chart. In the HTML page above we surrounded the chart div with another div to accomplish this.</li>
<li>The chart is updated with new data every 5 seconds. It is a known bug of the Google Visualization API that the data needs to be fetched from another server then the one that is hosting the HTML page for the refresh to actually work. In the HTML page above the data source <em>chart-data.py</em> is therefore fetched from <em>jansipke.nl</em> and the HTML is fetched from <em>www.jansipke.nl</em>.</li>
</ul>
<p>We will create our own data source in Python. There is a description of how you should do this on the <a href="http://code.google.com/apis/visualization/documentation/dev/implementing_data_source.html">Writing Your Own Data Source</a> page from Google. One of the most common mistakes in writing these data sources is the need for the program to read the request identifier (<em>reqId</em>) and return this value in the response. The API needs this to distinguish between responses for different charts on the same page.</p>
<blockquote>
<pre>import cgi, random

def index(req):
   reqId = None
   if (req.args):
      for arg in req.args.split("&amp;"):
         (key, value) = arg.split("=")
         if (key == "tqx"):
            for parameter in value.split(";"):
               if (parameter.find("%3A") &gt; 0):
                  (par_key, par_value) = parameter.split("%3A")
               if (par_key == "reqId"):
                  reqId = par_value

   a = str(random.randint(1, 3))
   b = str(random.randint(1, 3))
   c = str(random.randint(1, 3))
   d = str(random.randint(1, 3))

   s = ""
   s += "google.visualization.Query.setResponse(n"
   s += "{n"
   if (reqId != None):
      s += "   reqId:'" + reqId + "',n"
   s += "   status:'ok',n"
   s += "   table:n"
   s += "   {n"
   s += "      cols:n"
   s += "      [n"
   s += "         {id:'Col1',label:'',type:'string'},n"
   s += "         {id:'Col2',label:'Label1',type:'number'},n"
   s += "         {id:'Col3',label:'Label2',type:'number'},n"
   s += "         {id:'Col4',label:'Label3',type:'number'}n"
   s += "      ],n"
   s += "      rows:n"
   s += "      [n"
   s += "         {c:[{v:'a',f:'a'},{v:1.0,f:'1'},{v:1.0,f:'1'},{v:" + a + ",f:'1'}]},n"
   s += "         {c:[{v:'b',f:'b'},{v:2.0,f:'2'},{v:1.5,f:'1'},{v:" + b + ",f:'1'}]},n"
   s += "         {c:[{v:'c',f:'c'},{v:3.0,f:'3'},{v:2.5,f:'1'},{v:" + c + ",f:'1'}]},n"
   s += "         {c:[{v:'d',f:'d'},{v:4.0,f:'1'},{v:2.0,f:'1'},{v:" + d + ",f:'1'}]}n"
   s += "      ]n"
   s += "   }n"
   s += "});"

   return s
</pre>
</blockquote>
<p>We can test this data source by following the link without parameters and following the link with the <em>reqId</em> parameter present:</p>
<ul>
<li><a href="http://jansipke.nl/res/visualization/chart-data.py">http://jansipke.nl/res/visualization/chart-data.py</a></li>
</ul>
<ul>
<li><a href="http://jansipke.nl/res/visualization/chart-data.py?tqx=reqId%3A0">http://jansipke.nl/res/visualization/chart-data.py?tqx=reqId%3A0</a></li>
</ul>
<p>Notice that the first one does not have <em>reqId</em> present in the response, but the second one does.</p>
<p><strong>Update</strong>: it seems that the refreshing of data only happens correctly in Firefox and Opera. IE doesn&#8217;t refresh at all and Chrome only refreshes once. Oh joy!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jansipke.nl/using-google-visualization-api-with-own-data-source/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Creating web charts using Open Flash Chart</title>
		<link>http://www.jansipke.nl/creating-web-charts-using-open-flash-chart</link>
		<comments>http://www.jansipke.nl/creating-web-charts-using-open-flash-chart#comments</comments>
		<pubDate>Wed, 24 Mar 2010 19:32:06 +0000</pubDate>
		<dc:creator>jansipke</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Flash]]></category>
		<category><![CDATA[JSON]]></category>
		<category><![CDATA[Open Flash Chart]]></category>

		<guid isPermaLink="false">http://www.jansipke.nl/?p=908</guid>
		<description><![CDATA[Open Flash Chart gives you the possibility to have Flash based charts on your website without the need to know Flash. All it takes is a JSON file that describes the chart. This JSON file can be a static file that you created yourself with a text editor or dynamically created by a program, e.g. [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://teethgrinder.co.uk/open-flash-chart-2/">Open Flash Chart</a> gives you the possibility to have Flash based charts on your website without the need to know Flash. All it takes is a JSON file that describes the chart. This JSON file can be a static file that you created yourself with a text editor or dynamically created by a program, e.g. written in Java or Python.</p>
<p>There are several different types of charts that can be displayed. Some of them are shown here:</p>
<p><a href="http://www.jansipke.nl/wp-content/uploads/charts1.png"><img class="alignnone size-full wp-image-925" title="charts1" src="http://www.jansipke.nl/wp-content/uploads/charts1.png" alt="" width="635" height="100" /></a><a href="http://www.jansipke.nl/wp-content/uploads/charts2.png"><img class="alignnone size-full wp-image-929" title="charts2" src="http://www.jansipke.nl/wp-content/uploads/charts2.png" alt="" width="617" height="100" /></a></p>
<p>We start by creating an HTML page that will contain the chart:</p>
<blockquote>
<pre>&lt;html&gt;
   &lt;head&gt;
      &lt;script type="text/javascript" src="<a href="view-source:http://www.jansipke.nl/tno/charts/swfobject.js">swfobject.js</a>"&gt;&lt;/script&gt;
      &lt;script type="text/javascript"&gt;
         swfobject.embedSWF("open-flash-chart.swf", "my_chart1", "600", "250",
                            "9.0.0", "expressInstall.swf", {"data-file":"chart1.data"});
      &lt;/script&gt;
   &lt;/head&gt;
   &lt;body&gt;
      &lt;div id="my_chart1"&gt;&lt;/div&gt;
   &lt;/body&gt;
&lt;/html&gt;
</pre>
</blockquote>
<p>Then we create a JSON file called <em>chart1.data</em> that describes how the chart should look:</p>
<blockquote>
<pre>{
  "title":{
    "text":  "Bar Glass Chart",
    "style": "{font-size: 20px; color:#0000ff; font-family: Verdana; text-align: center;}"
  },

  "bg_colour": "#FFFFFF",

  "x_axis":
  {
    "stroke":      1,
    "tick_height": 10,
    "colour":      "#CCCCCC",
    "grid_colour": "#00ff00",
    "labels":
    {
      "labels": ["Server 1", "Server 2", "Server 3"]
    }
  },

  "y_axis":
  {
    "steps":       20,
    "tick_length": 100,
    "colour":      "#CCCCCC",
    "grid_colour": "#00FF00",
    "offset":      0,
    "max":         100
  },

  "elements":
  [
    {
      "type":      "bar_glass",
      "alpha":     0.5,
      "colour":    "#9933CC",
      "text":      "CPU load",
      "font-size": 10,
      "values" :   [90, 60, 70]
    },
    {
      "type":      "bar_glass",
      "alpha":     0.5,
      "colour":    "#CC9933",
      "text":      "Memory usage",
      "font-size": 10,
      "values" :   [60, 70, 90]
    }
  ]
}
</pre>
</blockquote>
<p>Copy the HTML file, the JSON file and the <em>open-flash-chart.swf</em> and <em>swfobject.js</em> files from the Open Flash Chart website to your own webserver and point your webbrowser to the HTML file. The result should look like the chart on <a href="/res/openflashchart/">this page</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jansipke.nl/creating-web-charts-using-open-flash-chart/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

