<?xml version="1.0" encoding="utf-8" ?>
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:syn="http://purl.org/rss/1.0/modules/syndication/" xmlns="http://purl.org/rss/1.0/">




    



<channel rdf:about="http://nitric.co.za/site-feed/RSS">
  <title>Nitric Software Laboratory RSS</title>
  <link>http://nitric.co.za</link>

  <description>
    
      Updates and blog posts from Nitric Software Laboratory in Cape Town
    
  </description>

  

  
            <syn:updatePeriod>daily</syn:updatePeriod>
            <syn:updateFrequency>1</syn:updateFrequency>
            <syn:updateBase>2011-07-07T11:34:51Z</syn:updateBase>
        

  <image rdf:resource="http://nitric.co.za/logo.png"/>

  <items>
    <rdf:Seq>
      
        <rdf:li rdf:resource="http://nitric.co.za/portfolio/esurvey"/>
      
      
        <rdf:li rdf:resource="http://nitric.co.za/blog-posts/clementine-excellent-music-player"/>
      
      
        <rdf:li rdf:resource="http://nitric.co.za/blog-posts/fakeexcel-class"/>
      
      
        <rdf:li rdf:resource="http://nitric.co.za/blog-posts/we-have-moved"/>
      
      
        <rdf:li rdf:resource="http://nitric.co.za/blog-posts/scite-how-i-configure-my-python-editor-of-choice"/>
      
      
        <rdf:li rdf:resource="http://nitric.co.za/blog-posts/disper-for-easily-switching-displays-in-ubuntu"/>
      
      
        <rdf:li rdf:resource="http://nitric.co.za/blog-posts/themeroller-dev-tool-bookmarklet"/>
      
      
        <rdf:li rdf:resource="http://nitric.co.za/who"/>
      
      
        <rdf:li rdf:resource="http://nitric.co.za/blog-posts/old-rotary-dialler-telephones"/>
      
      
        <rdf:li rdf:resource="http://nitric.co.za/blog-posts/reading-the-daily-maverick-on-kindle"/>
      
      
        <rdf:li rdf:resource="http://nitric.co.za/products/emon"/>
      
      
        <rdf:li rdf:resource="http://nitric.co.za/portfolio/watermanlive-1"/>
      
      
        <rdf:li rdf:resource="http://nitric.co.za/blog-posts/listen.py-little-script-to-stream-internet-radio-for-an-hour-and-then-stop"/>
      
      
        <rdf:li rdf:resource="http://nitric.co.za/contact"/>
      
      
        <rdf:li rdf:resource="http://nitric.co.za/portfolio/content-management-systems"/>
      
    </rdf:Seq>
  </items>

</channel>


  <item rdf:about="http://nitric.co.za/portfolio/esurvey">
    <title>eSurvey</title>
    <link>http://nitric.co.za/portfolio/esurvey</link>
    <description>eSurvey is a unique new electronic survey platform that we developed
for our client Outprosys. Outprosys is a leading document processing
and data capture provider.</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p><a class="external-link" href="http://www.outprosys.com/home/quote.php">eSurvey</a> is a unique new electronic survey platform that we developed for our client <a class="external-link" href="http://www.outprosys.com">Outprosys</a>. <a class="external-link" href="http://www.outprosys.com/">Outprosys</a> is a leading document processing and data capture provider.</p>
<p><a class="external-link" href="http://www.outprosys.com/home/quote.php">eSurvey</a> allows market research companies to take their existing paper surveys online - and digitally offline. First, <b>scanned images</b> of the survey are loaded into the system. Then using a drag 'n drop tool form fields are overlayed on top of the images. Quotas are then set up and assigned to different interviewers. The interviewers log in on their laptops, tablets or smartphones and all pages and questions are downloaded for offline use on the mobile browser (no app installation required). The interviewer then hits the road, finds respondents and captures their responses while offline. When online again they upload their captured data and reports are quickly generated in spreadsheeet format.  <a class="external-link" href="http://www.outprosys.com/home/quote.php"></a></p>
<p><a class="external-link" href="http://www.outprosys.com/home/quote.php">eSurvey</a> is made with a <a class="external-link" href="http://jquerymobile.com/">jQuery Mobile</a> user interface. It makes use of the html5 applicationCache and localStorage APIs to allow for offline capturing. The server side is a CherryPy python application with a MySQL database.</p>
<p>For more info and a demo see here: <a href="http://www.outprosys.com/home/quote.php" target="_blank">http://www.outprosys.com/home/quote.php</a></p>
<p><img class="image-inline" src="esurvey.png" /></p>]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Nicholas Spagnoletti</dc:creator>
    <dc:rights></dc:rights>
    <dc:date>2011-12-07T14:03:02Z</dc:date>
    <dc:type>Page</dc:type>
  </item>


  <item rdf:about="http://nitric.co.za/blog-posts/clementine-excellent-music-player">
    <title>Clementine = excellent music player</title>
    <link>http://nitric.co.za/blog-posts/clementine-excellent-music-player</link>
    <description>Having the right music player is vitally important to being able to get dev work done.</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p><a class="external-link" href="http://www.clementine-player.org/">Clementine</a> is great. Does playlists nicely. Does lovely crossfades that makes it feel like the machine has soul. You can first import your music for fast searching of metadata but you can also just play straight from filesystem. Has a nice artist info thing that fetches some stuff about the current song off the net. And it hasn't crashed once unlike Banshee or Rhythmbox. Nice one. We'll be using it in <a class="external-link" href="http://www.alexanderbar.co.za">the bar</a>.</p>
<p><a class="external-link" href="http://www.clementine-player.org/">http://www.clementine-player.org/</a></p>]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Nicholas Spagnoletti</dc:creator>
    <dc:rights></dc:rights>
    <dc:date>2011-12-06T13:50:00Z</dc:date>
    <dc:type>Blog Entry</dc:type>
  </item>


  <item rdf:about="http://nitric.co.za/blog-posts/fakeexcel-class">
    <title>FakeExcel class</title>
    <link>http://nitric.co.za/blog-posts/fakeexcel-class</link>
    <description>To get the iMC client running on Ubuntu I wrote this FakeExcel class.</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p><a class="external-link" href="http://incidentmc.com">iMC</a> is our product for managing and recording employee-related incidents. My father wrote the product in Python with wxWidgets so in theory getting it to run on Ubuntu should have been easy. However there were a few tricky issues because of dependencies on Excel and the COM interface that's available in win32 python that allows you to control Excel programatically.</p>
<p>In preparation for one of our new ventures (<a class="external-link" href="http://alexanderbar.co.za">Alexander Bar</a>) I needed to get iMC up and running on Ubuntu as we are going to use iMC to help manage our bar staff so what I did was to write a FakeExcel class which provides same methods but reads and writes the files as plain old CSV. If the file being read is a .xls I quickly run it through <a class="external-link" href="http://www.wagner.pp.ru/~vitus/software/catdoc/">xls2csv</a>. So unfortunately one loses the nice formatting and calculations in the report templates but for now it works as a solution to be able to get data in and out of iMC. There'll be many missing methods and properties as I only wrote replacements for what was being used in iMC.</p>
<p>By the way if you're in Gauteng go check out the iMC stand at the <a class="external-link" href="http://hr-africa.com/hrde/">HRD Expo</a> at the Sandton Convention centre this week.</p>
<pre>import os
import subprocess
import csv
import tempfile

'''
FakeExcel.py - reading/writing of "xls" files (actually csv)

If the file being read is a .xls we quickly run it through xls2csv. <br />Please use, modify, redistribute freely. Lots of missing methods and properties - please post any modifications/improvements. <br />It would be very nice if someone made this work with Python Uno so we could retain formatting &amp; calculations.

Dependency: catdoc package (apt-get install catdoc)

Nicholas Spagnoletti
nicholas@nitric.co.za
2011-10-02

'''

def openx(path):
    'Open a file on windows using whatever system default opener is and if that fails then with gnome-open'
    try:
        os.startfile(path)
    except AttributeError:
        subprocess.Popen(["gnome-open", path])



class Value(object):
    'Class for getting and setting cell Values'
    def __init__(self, parent, rownum, colnum):
        self.parent=parent
        self.rownum=rownum
        self.colnum=colnum
    def __repr__(self):
        return self.Value
    def __setattr__(self, a, v):
        if a=='Value':
            self.parent._cells[(self.rownum, self.colnum)] = v
        else:
            return super(Value,self).__setattr__(a,v)
            
    def __getattr__(self, a):
        if a=='Value':
            try:
                return self.parent._cells[(self.rownum, self.colnum)]
            except KeyError:
                return None

    
class Sheet(object):
    'Class corresponding to sheet in Workbook (only ever have one sheet as we are actually dealing with csv'
    def __init__(self, parent):
        self._cells = {}
        self.parent=parent
        sample = self.parent.file.read(2096)
        dialect = csv.Sniffer().sniff(sample)
        self.parent.file.seek(0)
        r = csv.reader(self.parent.file, dialect=dialect)
        for rownum, line in enumerate(r):
            for colnum, v in enumerate(line):
                if v!= u'\x0c':
                    nv = Value(self, rownum+1, colnum+1)
                    nv.Value = v
      
            
    def Cells(self, row, col):
        nv = Value(self, row, col)
        return nv
            

class Workbooks(object):
    'Opens and parses .csv and .xls files, sets a Sheet, and provides method for saving out as .csv'
    path=None
    def __init__(self, parent):
        self.parent=parent
    def Open(self, path):
        self.path=path
        if path.endswith('.xls'):
            s = subprocess.Popen(["xls2csv", path], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            csv, err = s.communicate()
            t = tempfile.TemporaryFile()
            t.write(csv)
            t.seek(0)
            self.file = t
        else:
            self.file = open(path)
        
        sheet = Sheet(self)
        self.parent.ActiveSheet=sheet
        Sheets = (sheet,)
        return self
    def SaveAs(self, path):
        self.path=path
        with open(path, 'w') as f:
            w = csv.writer(f)
            keys = sorted(self.parent.ActiveSheet._cells.keys())
            cells = self.parent.ActiveSheet._cells
            prevrow = None
            for k in keys:
                row, col = k
                if prevrow!=row and row&gt;1:
                    w.writerow(line)
                if prevrow!=row:
                    line = []
                line.append(cells.get(k))
                prevrow = row
            
    def Close(self, SaveChanges=False):
        if SaveChanges:
            self.SaveAs(self.path)
        self.parent.ActiveSheet._cells = {}

class FakeExcel(object):
    'Instantiates a Workbooks object'
    def __init__(self):
        self.Workbooks = Workbooks(self)
    def Quit(self):
        pass
  
        
        

if __name__=="__main__":
    excel = FakeExcel()
    excel.Workbooks.Open('/tmp/public.xls')
    sheet = excel.ActiveSheet
    row = 1
    while sheet.Cells(row,1).Value != None:
        print sheet.Cells(row,1).Value
        row += 1
    #now let's change a val
    sheet.Cells(3,1).Value = 'Changed'
    row = 1
    while sheet.Cells(row,1).Value != None:
        print sheet.Cells(row,1).Value
        row += 1
    excel.Workbooks.SaveAs('/tmp/public.csv')
    #Open on the desktop
    openx('/tmp/public.csv')
    

</pre>]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Nicholas Spagnoletti</dc:creator>
    <dc:rights></dc:rights>
    <dc:date>2011-10-02T13:49:12Z</dc:date>
    <dc:type>Blog Entry</dc:type>
  </item>


  <item rdf:about="http://nitric.co.za/blog-posts/we-have-moved">
    <title>We have moved!</title>
    <link>http://nitric.co.za/blog-posts/we-have-moved</link>
    <description>After many years of the Bandwidth Barn, we have moved to 78 Strand Street.</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>Yes, after many many years of being in the Bandwidth Barn, we have finally decided to move into our own offices. Our new address is 78 Strand Street. Our postal address stays the same as Box 7207, Rogge Bay, 8012.</p>
<p>We will miss many of our barn neighbours, and especially the barn staff who have always been so good to us.</p>]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Edward van Kuik</dc:creator>
    <dc:rights></dc:rights>
    <dc:date>2011-09-21T13:34:01Z</dc:date>
    <dc:type>Blog Entry</dc:type>
  </item>


  <item rdf:about="http://nitric.co.za/blog-posts/scite-how-i-configure-my-python-editor-of-choice">
    <title>SciTE - how I configure my python editor of choice</title>
    <link>http://nitric.co.za/blog-posts/scite-how-i-configure-my-python-editor-of-choice</link>
    <description>SciTE is what I want from an editor - fast, highly configurable and not Eclipse.</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>It took me a long time to find the right editor. After trying out many IDEs and editors and always running back to <a class="external-link" href="http://www.nedit.org/">NEdit</a> for - seriously - a decade I finally switched to <a class="external-link" href="http://www.scintilla.org/SciTE.html">SciTE</a>. SciTE is what I want from an editor - fast, highly configurable and not Eclipse.</p>
<p>The first thing is to generate a python text file for calltips and autocompletion using <a class="external-link" href="http://www.koders.com/python/fid7000B9C96CF2C6FB5BCE9DF700365C5B2A1F36A7.aspx">this script</a>. (I had to add some exception catching in places but unfortunately have lost my modified version of that file, sorry.)</p>
<p>Then although it's very old you can also grab the PHP one <a class="external-link" href="http://www.scintilla.org/php.api">from here</a>. (This doesn't bother me as my PHP is also very old)</p>
<p>Then from the SciTE Options menu choose 'Open User Options File'  - here is the config that I put there with all the options I've decided are best for me:</p>
<pre>#python autocomplete and tooltips settings - python.api is in my home dir<br />api.*.py=$(SciteUserHome)/python.api<br />autocomplete.python.ignorecase=1<br />autocomplete.python.start.characters=.<br />autocomplete.python.fillups=(<br />calltip.python.ignorecase=1<br />calltip.python.word.characters=._$(chars.alpha)$(chars.numeric)<br /><br />#php autocomplete and tooltip settings - php.api is in my home dir<br />api.$(file.patterns.php)=$(SciteUserHome)/php.api<br />autocomplete.php.ignorecase=1<br />autocomplete.php.start.characters=.<br />autocomplete.php.fillups=(<br />calltip.php.ignorecase=1<br />calltip.php.word.characters=._$(chars.alpha)$(chars.numeric)<br /><br />#also use words in current buffer as choices for autocomplete<br />autocompleteword.automatic=1<br />#even if only one option then must still explicitly choose<br />autocomplete.choose.single=0<br /><br />#utf8, of course, silly<br />code.page=65001<br />#check whether file modified by another process<br />load.on.activate=1<br />#ask me whether to save unsaved files when closing<br />are.you.sure=1<br />#use same instance of scite if already running<br />check.if.already.open=1<br />#allow open this number of files at same time<br />buffers=25<br />#keep list of recent files<br />save.recent=1<br />#when starting scite reopen previous buffers<br />save.session=1<br />#show full path in title bar to current file<br />title.full.path=1<br />#show line numbers<br />line.margin.visible=1<br />#width of line numbers<br />line.margin.width=4<br /><br />#indentation<br />tabsize=4<br />indent.size=4<br />#ooh, tabs please<br />use.tabs=1<br />#wrap long lines<br />wrap=1<br /><br />#let's always use monospace<br />font.base=$(font.monospace)<br />font.comment=$(font.monospace)<br />font.text=$(font.monospace)</pre>
<p>For more options and documentation on these look here:<br /><a class="external-link" href="http://www.scintilla.org/SciTEDoc.html">http://www.scintilla.org/SciTEDoc.html</a></p>]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Nicholas Spagnoletti</dc:creator>
    <dc:rights></dc:rights>
    <dc:date>2011-08-25T09:30:00Z</dc:date>
    <dc:type>Blog Entry</dc:type>
  </item>


  <item rdf:about="http://nitric.co.za/blog-posts/disper-for-easily-switching-displays-in-ubuntu">
    <title>disper - for easily switching displays &amp; resolutions on the fly in Ubuntu</title>
    <link>http://nitric.co.za/blog-posts/disper-for-easily-switching-displays-in-ubuntu</link>
    <description>Thanks to disper I can easily switch between primary and secondary monitors or changing resolutions without restarting X even if using the Nvidia drivers.</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>Our home machine is our media watching box with an Nvidia GeForce 9500 GT with Nvidia driver version 270.41.06. We have an RGB-over-cat5 cable (another whole story which Edward will have to write about) running to the TV which acts as the second monitor in a TwinView configuration. The resolutions of the TV and primary monitor are slightly different which wasn't really a problem in Ubuntu Classic but since Unity there appeared a second menu bar on the primary monitor because of the overlap (Having the monitors in a left-and-right layout didn't work in practice either because when full screening Flash video it would full screen on the wrong monitor)</p>
<p>Since I don't really need to ever use both monitors at the same time I was looking for an easy way to switch between using either the primary monitor and the TV. Generally, when finding something to watch, one browses around for a bit and then buffer up the stream, full screen it and then go and sit down to watch. Opening nvidia-settings and going through a bunch of steps every time wasn't a good enough solution and having to restart X session would of course be a total no-no.</p>
<p>Then I found <a class="external-link" href="http://willem.engen.nl/projects/disper/">disper</a> which is fantastic and works perfectly for me. It is a command line tool to change your display settings on the fly. I set this command to run when pressing ctrl+scrolllock:</p>
<p><code>disper --cycle-stages="-S -r 1360x768: -s" --cycle</code></p>
<p>(which means that each time that command is run disper will cycle between showing the secondary and primary monitors. I had to specify the resolution for the secondary monitor.)</p>
<p>Voila. Can sit back and enjoy the <a class="external-link" href="http://www.thedailyshow.com">Daily Show</a>. Disper will also prove useful at talks and presentations which are always preceded by ritualistic fighting with the projector.</p>]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Nicholas Spagnoletti</dc:creator>
    <dc:rights></dc:rights>
    <dc:date>2011-08-08T09:16:20Z</dc:date>
    <dc:type>Blog Entry</dc:type>
  </item>


  <item rdf:about="http://nitric.co.za/blog-posts/themeroller-dev-tool-bookmarklet">
    <title>Themeroller Dev Tool Bookmarklet</title>
    <link>http://nitric.co.za/blog-posts/themeroller-dev-tool-bookmarklet</link>
    <description>For the last few months the very useful Themeroller Dev Tool Bookmarklet has been broken in newish versions of Firefox. I've posted a fixed version.</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>We love <a class="external-link" href="http://jqueryui.com">jQuery UI</a> and <a class="external-link" href="http://jqueryui.com/themeroller/">Themeroller</a> which allows us - and our clients - to re-theme their web apps interactively. Then a few months ago after an upgrade to Firefox 4 we found the Themeroller bookmarklet no longer worked. Someone posted a solution on the jQuery UI forum which while not rocket science is a little bit of a hassle to do so I thought I'd Be Nice and put my fixed one up for others to use:</p>
<p><a class="external-link" href="http://themeroller.nitric.co.za/">http://themeroller.nitric.co.za/</a></p>
<p>Open that page and drag the button onto your Firefox bookmarks toolbar. Then open on any 'themerollered' page and voila - works perfectly for me in Firefox 5.0</p>
<p>Here's that forum posting by the way:<br /><a class="external-link" href="http://forum.jquery.com/topic/the-firefox-themeroller-bookmarklet-does-not-update-the-html-page-when-changing-theme-colors">http://forum.jquery.com/topic/the-firefox-themeroller-bookmarklet-does-not-update-the-html-page-when-changing-theme-colors</a></p>]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Nicholas Spagnoletti</dc:creator>
    <dc:rights></dc:rights>
    <dc:date>2011-07-22T14:15:00Z</dc:date>
    <dc:type>Blog Entry</dc:type>
  </item>


  <item rdf:about="http://nitric.co.za/who">
    <title>Who</title>
    <link>http://nitric.co.za/who</link>
    <description>About the people at Nitric.</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<h2>Edward van Kuik</h2>
<p>Edward van Kuik completed his Bachelor of  Science majoring in Computer Science from University of Cape Town, South  Africa in 1996. After university he worked at the Energy and  Development Research Centre designing applications to optimise  engineering design problems using genetic algorithms.  In 1998, Edward  started working for De Beers Marine as a Software Engineer in the  Mineral Resources Unit working on mostly seismic-related systems in C++.  In 2001, he started his own Company, Nitric Industries, (the one you're  reading about now) and has been looking a little stressed ever since.  Edward van Kuik believes in Linux, open standards and open source technologies.</p>
<h2>Nicholas Spagnoletti</h2>
<p>Nicholas is an experienced software  developer. He graduated from UCT with an humanities degree in 2000.  While studying he worked for his father's sofware business and began his  PHP career by doing the company website. He gained more experience as a  web developer at the .com era sports website Sportal before joining  Edward full-time at Nitric in 2001. Since then he has worked on hundreds  of projects of all sizes. The bulk of work has been in designing and  implementing business operations systems for other small-to-medium  enterprises. He is also a playwright - look out for his play <a href="http://londonroad.co.za/">London Road</a></p>
<h2>Andrew Spagnoletti</h2>
<p>Andrew is the father of Nicholas, recently  retired from Korbitec and now teaming up with Nitric to launch his  latest development, (Staff)<a href="http://www.incidentmc.com/"> Incident Management and Control</a>.  Andrew developed the AJS Legal Accounting and Practice Management  System in 1980, which he sold to Global Technologies Limited in 2000, by  which time AJS had a client base of approximately 450 legal practices  in South Africa, from small to large. Andrew remained CEO of AJS within  the Glotec group of companies for 4 years. During the last 6 months with  Glotec Andrew spent considerable time with the employment law division  of a major client, Cliffe Dekker, with a view to encapsulating the  lawyers expertise into a Business Process Management engine developed by  Andrew. This project was not completed because Andrew left Glotec and  in late 2004 joined Korbitec to drive the development of Ghost Practice.  A few years later Andrew developed a program specifically for small  legal practices, before retiring from Korbitec in August 2010. Incident  Management and Control was borne out of Andrew's experiences in software  development over the years, and informed by the time spent with the  Cliffe Dekker labour lawyers.</p>]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Nicholas Spagnoletti</dc:creator>
    <dc:rights></dc:rights>
    <dc:date>2011-07-21T11:05:00Z</dc:date>
    <dc:type>Page</dc:type>
  </item>


  <item rdf:about="http://nitric.co.za/blog-posts/old-rotary-dialler-telephones">
    <title>Old Rotary Dialler telephones</title>
    <link>http://nitric.co.za/blog-posts/old-rotary-dialler-telephones</link>
    <description>Making a little 10-telephone exchange using a 10 channel sound card and some Arduino's.</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>I wanted to make a little 10-telephone exchange out of old rotary dial telephones. I've been collecting old rotary dial phones from markets and antique shops. Nicholas even bought an old rotary dial payphone! So I bought a <a class="external-link" href="http://www.m-audio.com/products/en_us/Delta1010LT.html">Delta-1010LT</a> sound card because someone said it will work nicely with ALSA. I found a nice python jack library simply called 'jack' to chat to a jackd sound server via numpy arrays. I decided to just use the <a class="external-link" href="http://arduino.cc/en/Main/ArduinoBoardUno">Arduino</a> running <a class="external-link" href="http://firmata.org/wiki/Main_Page">firmata</a> and use <a class="external-link" href="https://bitbucket.org/tino/pyfirmata/src">pyfirmata</a> to read to the various pins on the Arduino to detect the onhook and <a class="external-link" href="http://en.wikipedia.org/wiki/Pulse_dialing">pulse dialling</a> and also to blink a little LED on the phone when the phone rings (using the ringers would be too loud for my purpose). Then I hugely abused some ethernet cables way beyond their original purpose. (I have a habit of doing that.)</p>
<p>You can dial one of the other phones, and even break-in to another conversation for a multi-way chat. Oh and you can dial 222 and get the BBC World Service via gstreamer. :)</p>
<p>Thanks to Colin Braye for helping me rewire and soldier up some phones and circuits like the 8 op-amps I suddenly realised I needed.</p>]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Edward van Kuik</dc:creator>
    <dc:rights></dc:rights>
    <dc:date>2011-07-21T10:45:00Z</dc:date>
    <dc:type>Blog Entry</dc:type>
  </item>


  <item rdf:about="http://nitric.co.za/blog-posts/reading-the-daily-maverick-on-kindle">
    <title>Reading The Daily Maverick on Kindle</title>
    <link>http://nitric.co.za/blog-posts/reading-the-daily-maverick-on-kindle</link>
    <description>I love the Daily Maverick but frustratingly they don't offer a Kindle edition - Calibre to the rescue!</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p><a class="external-link" href="http://www.thedailymaverick.co.za">The Daily Maverick</a> is great. Excellent journalism and intelligent opinion. Unfortunately they're completely seduced by shiny baubles and are pouring all their resources into creating an iPad version set to launch next month.</p>
<p>They are quite stubborn about producing a Kindle version; doubly frustrating because I'd actually happily <i>pay</i> for this (I already subscribe to the <a class="external-link" href="http://www.mg.co.za">M&amp;G</a> kindle edition).</p>
<p><a class="external-link" href="http://calibre-ebook.com">Calibre</a> has a very useful feature which can turn an RSS feed (or a number of RSS feeds) into an ebook for reading later on your Kindle or similar device.</p>
<p>Enter the Daily Maverick's RSS feed: http://www.thedailymaverick.co.za/rss as a Custom news source.</p>
<p>Select 'MOBI' as the output format and then transfer to Kindle either with the USB cable or by sending it to your Kindle email address (remember if you send it to your free Kindle address it will be delivered free of charge as long as you're on a WIFI network) The result is a near perfect reading experience similar to what you get if you subscribe to the <a class="external-link" href="http://www.mg.co.za/">M&amp;G</a> or Newsweek in the Kindle store.</p>
<p>.</p>
<p style="text-align: center; "><img alt="Calibre" class="image-inline" src="../images/calibretdm.png/image_large" /></p>]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Nicholas Spagnoletti</dc:creator>
    <dc:rights></dc:rights>
    <dc:date>2011-07-20T11:02:49Z</dc:date>
    <dc:type>Blog Entry</dc:type>
  </item>


  <item rdf:about="http://nitric.co.za/products/emon">
    <title>Emon</title>
    <link>http://nitric.co.za/products/emon</link>
    <description>Emon is a monitoring tool that replaces paper-based logging with an SMS based capturing system. Data capturers out in the field send codes via SMS to the Emon number - 31028. Emon validates and stores the information and provides web and email reports and exports of the data.
</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p><a class="external-link" href="http://emon.co.za">Emon</a> stands for Environmental Monitoring and can be used for any kind of manual data capture.<br />Data is captured by codes that are predefined for each <a class="external-link" href="http://emon.co.za/">Emon</a> service. This allows many records to be batched together in a single text message.</p>
<p style="text-align: center; "><img alt="emon" class="image-inline" src="../images/emon.jpg" /></p>
<p><a class="external-link" href="http://emon.co.za/">Emon</a> is currently in use at a number of landfill sites where it is  necessary to know the quantity and type of waste. As vehicles arrive at  each site, monitoring staff compose an SMS with single letter codes of  what kind of vehicle and what kind of waste is arriving. Once they reach  the 160 character limit of a text message, they send off the SMS to  31028 and start with a new message. Thus hundreds of records can be  captured in almost real time at a cost of less than R10 using any type  of cellphone.</p>
<p> </p>
<p style="text-align: center; "><img alt="Example of a report showing data collected by Emon" class="image-inline" src="../images/Screenshot.png/image_preview" /></p>]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Nicholas Spagnoletti</dc:creator>
    <dc:rights></dc:rights>
    <dc:date>2011-07-20T10:25:28Z</dc:date>
    <dc:type>Page</dc:type>
  </item>


  <item rdf:about="http://nitric.co.za/portfolio/watermanlive-1">
    <title>Watermanlive</title>
    <link>http://nitric.co.za/portfolio/watermanlive-1</link>
    <description>We developed Watermanlive for our client Waterman Marine Consultancy who are based in the French riviera. Their business is in management and surveying services for motor and sailing yachts.

</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p><a class="external-link" href="http://watermanlive.com">Watermanlive</a> (or WML for short) is a tool for managing new builds, major refits, vessel maintenance and compliance to international maritime regulations and standards. <a class="external-link" href="http://watermanlive.com/">WML</a> is for captains, insurance brokers, underwriters, surveyors, engineers, operators and owners to manage risk, build, maintenance and compliance issues on board their vessels.<br /><br /><a class="external-link" href="http://watermanlive.com">WML</a> has a powerful and flexible surveying module. Choose from preset survey templates or create your own set of survey questions. Once you've set up the survey you can load it on a mobile device such as a smartphone, Android tablet or iPad which you can take on board the vessel with you to conduct the survey. When you're online again, upload the survey results and <a class="external-link" href="http://watermanlive.com/">WML</a> will automatically create issues and notifications on all flagged items.<br /><br />Built in to <a class="external-link" href="http://watermanlive.com/">WML</a> is an issue tracking system for managing issues, damage claims and warranty.  These can be manually created at any time. Also when a survey is conducted, an issue is automatically created for any item that requires attention - this could be a component needing technical attention, a missing or expired certificate or document or any other compliance or safety issue.<br /><br /><a class="external-link" href="http://watermanlive.com/">WML</a> also keeps track of the vessel's documents  - photos, scans of certificates, regulations, contracts with crew, financial information etc. These are presented with an easily navigable gallery-style web interface and can be easily managed online.<br /><br /><br /></p>
<p style="text-align: center; "><img alt="Showing dashboard of vessels " class="image-inline" src="../images/wmlscreenshot.png" /></p>
<p style="text-align: left; "><a class="external-link" href="http://watermanlive.com/">WML</a><i> was developed using Python, CherryPy, MySQL, Mako templates, jQuery and jQuery UI.</i></p>]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Nicholas Spagnoletti</dc:creator>
    <dc:rights></dc:rights>
    <dc:date>2011-07-20T09:55:00Z</dc:date>
    <dc:type>Page</dc:type>
  </item>


  <item rdf:about="http://nitric.co.za/blog-posts/listen.py-little-script-to-stream-internet-radio-for-an-hour-and-then-stop">
    <title>listen.py: Little script to stream internet radio for an hour and then stop </title>
    <link>http://nitric.co.za/blog-posts/listen.py-little-script-to-stream-internet-radio-for-an-hour-and-then-stop</link>
    <description>To avoid accidentally wasting lots of bandwidth I made this little python script that will play an internet stream using gstreamer for an hour and then stop. </description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<div id="content-core">
<div class="kssattr-macro-text-field-view kssattr-templateId-newsitem_view kssattr-atfieldname-text plain" id="parent-fieldname-text">
<p>In the mornings I like listening to the BBC World Service  while having breakfast and getting ready. I used to use my Worldspace  satellite receiver but a while ago they ceased operating and a few  months ago they stopped broadcasting the BBC. I realised I would have to  listen to it over the net. The Worldspace radio had a very useful  builtin FM modulator so you could listen around your home on normal FM  radios. I purchased a cheap FM modulator to attach to my computer so  that we can listen all over the flat on normal FM radios.</p>
<p>To solve the problem of accidentally leaving the stream running all  day and chowing all our expensive international bandwidth, I wrote this  little app which uses wx to make a very simple GUI that has a button to  start playing the stream (using gstreamer of course) and a timer that  counts down. After an hour the stream stops.</p>
<p>Dependencies are wxpython and the python-gstreamer bindings. On Ubuntu you can install these packages:</p>
<pre>apt-get install python-gst0.10 python-wxgtk2.8</pre>
<p>Here's the script, where you can choose between the World Service and  BBC Radio 4 - add any other streams to the streams list of tuples.</p>
<pre>#!/usr/bin/python<br />import gst<br />import wx<br />import time<br /><br />player = gst.element_factory_make("playbin", "player")<br /><br />streams = [<br /> ('BBC World Service', 'http://mp32.bbc.streamuk.com:80/'),<br /> ('BBC Radio 4', 'mms://wm-live.bbc.net.uk/wms/bbc_ami/radio4/radio4_bb_live_int_ep1_sl0?BBC-UID=b4adbcdf5ba7eea337440a77610973cee5bd1676f0b0524162a83074f35cc068&amp;amp;SSO2-UID=')<br />]<br /><br /><br />class mainwin(wx.Frame):<br />    playfor=60*60<br />    s=playfor<br />    <br />    def __init__(self, parent=None):<br />        super(mainwin,self).__init__(parent, wx.ID_ANY, title='Listen to the BBC')<br />        <br />        panel = wx.Panel(self, wx.ID_ANY)<br />        sizer = wx.BoxSizer(wx.VERTICAL)<br />        self.button = wx.Button(panel, wx.ID_ANY, 'Start')<br />        self.cb = wx.ComboBox(panel, choices=[s[0] for s in streams],style=wx.CB_DROPDOWN|wx.CB_READONLY,value=streams[0][0])<br />        <br />        self.timer = wx.Timer(self)<br />        self.Bind(wx.EVT_TIMER, self.update, self.timer)<br />        <br />        self.label = wx.StaticText(panel)<br />            <br />        panel.SetSizer(sizer)<br />        sizer.Add(self.cb)<br />        sizer.Add(self.button)<br />        sizer.Add(self.label)<br />        <br />        <br />        self.Bind(wx.EVT_BUTTON, self.toggle, self.button)<br />        <br />    <br />    def toggle(self, evt=None):        <br />        label = self.button.GetLabel()<br />        station = self.cb.GetValue()<br />        if label=='Start':<br />            for s, uri in streams:<br />                if station==s:<br />                    player.set_property('uri', uri)<br />            player.set_state(gst.STATE_PLAYING)<br />            self.button.SetLabel('Stop')<br />            self.timer.Start(1000)<br />            <br />        elif label=='Stop':<br />            self.s=1<br />            self.update()<br />            player.set_state(gst.STATE_NULL)<br />            self.button.SetLabel('Start')<br />    <br />    def update(self, evt=None):<br />        self.s -= 1<br />        if self.s &lt;= 0:<br />            player.set_state(gst.STATE_NULL)<br />            <br />            self.button.SetLabel('Start')<br />            self.timer.Stop()<br />            self.s=self.playfor<br />            self.label.SetLabel('')<br />        else:<br />            mins = self.s / 60<br />            secs = self.s % 60<br />            self.label.SetLabel("%02d:%02d" % (mins,secs))<br />        <br />        <br /><br />if __name__ == '__main__':<br />    app = wx.PySimpleApp()<br />    frame = mainwin().Show()<br />    app.MainLoop()</pre>
</div>
</div>]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Nicholas Spagnoletti</dc:creator>
    <dc:rights></dc:rights>
    <dc:date>2011-06-25T16:38:44Z</dc:date>
    <dc:type>Blog Entry</dc:type>
  </item>


  <item rdf:about="http://nitric.co.za/contact">
    <title>Contact</title>
    <link>http://nitric.co.za/contact</link>
    <description>Our Contact Details</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p><a accesskey="9" class="link-overlay" href="contact-info" rel="#pb_2" title="Contact">Click here to contact us via web form</a></p>
<h2>Postal Address</h2>
<p>Box 7207<br />Roggebaai<br />8012</p>
<h2>Physical Address</h2>
<p>78 Strand Street<br /> Cape Town<br />8001</p>
<h2>Phone Numbers</h2>
<p><b>Phone: </b>021-300-1073 (VOIP landline hence the funny prefix)<br /><b>Fax: </b>086 710 8657</p>
<h2>Email Addresses</h2>
<p>Accounts Enquiries: accounts@nitric.co.za<br />General Enquiries: info@nitric.co.za</p>]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>admin</dc:creator>
    <dc:rights></dc:rights>
    <dc:date>2011-06-13T20:55:00Z</dc:date>
    <dc:type>Page</dc:type>
  </item>


  <item rdf:about="http://nitric.co.za/portfolio/content-management-systems">
    <title>Content Management, Client Area and E-commerce </title>
    <link>http://nitric.co.za/portfolio/content-management-systems</link>
    <description>Over the years, we have developed various Content Management Systems, for a wide range of businesses. Projects include websites for Supa Strikas, Sturrock Shipping, Media24 and Caltex.</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>We've had a long association with <a class="external-link" href="http://webfactory.co.za">Webfactory</a> and have worked on various content management and client-area systems over the years. Some of these include:</p>
<ul>
<li><a class="external-link" href="http://www.anabalat.com">Ana Balat</a></li>
<li><a class="external-link" href="http://www.treatcolic.com">TreatColic.com</a></li>
<li><a class="external-link" href="http://montroseasset.com">Montrose Asset Management</a></li>
<li><a class="external-link" href="http://leopardantiques.com">Leopard Antiques</a></li>
</ul>
<p>Our legacy system <a class="external-link" href="http://wnn.nitric.co.za">WNN</a> still provides basic news and CMS services to sites such as the <a class="external-link" href="http://www.districtsixmuseum.co.za">District Six Museum.</a></p>
<p>We create our content management systems with context-sensitive 'Edit' links that appear to  authorised users making it almost as easy to edit the site as it is to  browse it.</p>
<p>We've developed many custom tools that fulfill  requirements for newsletter sending, client document management,  personal information databases, syndication, image management, invoicing, payment gateways and  surveys &amp; questionnaires.</p>
<p>We make use of various third  party open-source tools such as Image Magick, PDF utilities and ffmpeg to  ensure that our content updaters don't spend unnecessary amounts of time  fighting with dimensions and file formats.</p>
<p>More recently together with <a class="external-link" href="http://www.supastrikas.co.za">Supa Strikas</a> we've developed the backend and comic-browsing interface for the <a class="external-link" href="http://www.caltex75th.com">Caltex75th.com</a> site.</p>]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>admin</dc:creator>
    <dc:rights></dc:rights>
    <dc:date>2011-06-13T19:55:00Z</dc:date>
    <dc:type>Page</dc:type>
  </item>





</rdf:RDF>

