jQuery Boids (Plugin)

From the README:

"My first attempt making a jQuery plugin, following the guidelines at: http://docs.jquery.com/Plugins/Authoring

Boids code adapted from Javascript Boids by Ben Dowling, see: http://www.coderholic.com/javascript-boids/

If this is bound to the window resize event, then the jQuery resize event plugin by "Cowboy" Ben Alman should be used as it throttles the window resize events. See: http://benalman.com/projects/jquery-resize-plugin/"

The plugin uses HTML Canvas to render the Boids, so a modern browser with Canvas support is required for this to work. I tested with Chrome, Safari and Firefox. IE with Excanvas was painfully slow…

Code is hosted at GitHub: https://github.com/kahara/jQuery-Boids

Demo is at: http://jonikahara.com/lab/jQuery-Boids/test.html

Tagged with:

Categorised as:


Arduino, DS18B20, Ethernet Shield, Pachube.Com

Kotkansaari Sensorium Update 2: The sensor is now outside, and running on parasitic power. Update: The data is now available in a more mobile-friendly web page here. Arduino code, based on (i.e. copypasted & modified a little) stuff from http://www.dial911anddie.com/weblog/2009/12/arduino-ethershield-1wire-temperature-sensor-pachube/ is below. Requires the 1-wire library and the Dallas Temperature Control library, both of which can be downloaded from here. Original code utilized DHCP, but I found this to be somewhat unstable and went with a static IP address instead. DS18B20 gets it's power from Arduino, and the data line (that's the center pin) is connected to Arduino pin 8. Data line is pulled up to +5V through a 4k7 resistor, as suggested in Maxim literature. Parasitic power supply was not used as proper voltage was readily available from Arduino. Please note that even though parasitic power is not used, the pull-up resistor is still necessary (see the data sheet).
#include <Ethernet.h>
#include <OneWire.h>
#include <DallasTemperature.h>

char PACHUBE_API_STRING[] = "";  // Your API key
int PACHUBE_FEED_ID = 0; // Your feed ID 

// Digital IO port used for one wire interface
int ONE_WIRE_BUS = 8 ;

// Ethernet mac address - this needs to be unique
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

// IP addres of www.pachube.com
byte server[] = { 209,40,205,190 };

// Arduino address
byte ip[] = { 10, 0, 0, 223 };
byte gateway[] = { 10, 0, 0, 2 };

char version[] = "PachubeClient Ver 0.01c";

#define CRLF "rn"

// simple web client to connect to Pachube.com 
Client client(server, 80);

// Setup a oneWire instance to communicate with any OneWire device
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature. 
DallasTemperature sensors(&oneWire);

// 1wire device address
DeviceAddress thermometer;

void setup()
{
   // Note: Ethernet shield uses digitial IO pins 10,11,12, and 13   
   Serial.begin(9600);
  
   Serial.println(version);
   Serial.println();
  
   // locate devices on the 1Wire bus
   Serial.print("Locating devices on 1Wire bus...");
   sensors.begin();
   int count = sensors.getDeviceCount();
   Serial.print("Found ");
   Serial.print( count );
   Serial.println(" devices on 1wire bus");

   // select the first sensor   
   for ( int i=0; i<count; i++ )
   {
      if ( sensors.getAddress(thermometer, i) ) 
      {
         Serial.print("1wire device ");
         Serial.print(i);
         Serial.print(" has address: ");
         printAddress(thermometer);
         Serial.println();
      }
      else
      {
         Serial.print("Unable to find address for 1wire device "); 
         Serial.println( i );
      }  
   }
  
   // show the addresses we found on the bus
   Serial.print("Using 1wire device: ");
   printAddress(thermometer);
   Serial.println();

   // set the resolution to 9 bit 
   sensors.setResolution(thermometer, 9);

   Serial.print("Initializing ethernet...");  
   delay(5000);
   Ethernet.begin(mac, ip, gateway);
   delay(5000);
   Serial.println(" done.");
}

void sendData()
{     
   float temp = sensors.getTempC(thermometer);
   //float temp = sensors.getTempF(thermometer);
   Serial.print("Temp=");
   Serial.println(temp);
  
   Serial.println("connecting...");

   if (client.connect()) 
   {
      Serial.println("connected");
      
      client.print(
         "PUT /api/feeds/" );
      client.print(PACHUBE_FEED_ID);
      client.print(".csv HTTP/1.1" CRLF
                   "User-Agent: Fluffy Arduino Ver 0.01" CRLF
                   "Host: www.pachube.com" CRLF 
                   "Accept: */" "*" CRLF  // need to fix this 
                   "X-PachubeApiKey: " );
      client.print(PACHUBE_API_STRING);
      client.print( CRLF 
                    "Content-Length: 5" CRLF
                    "Content-Type: application/x-www-form-urlencoded" CRLF
                    CRLF );
      client.println(temp);
      unsigned long reqTime = millis();
      
      // wait for a response and disconnect 
      while ( millis() < reqTime + 10000) // wait 10 seconds for response  
      {
         if (client.available()) 
         {
            char c = client.read();
            Serial.print(c);
         }

         if (!client.connected()) 
         {
            Serial.println();
            Serial.println("server disconnected");
            break;
         }
      }
      
      Serial.println("client disconnecting");
      Serial.println("");
      client.stop();
   } 
   else 
   {
      Serial.println("connection failed");
   }
}

void printAddress(DeviceAddress deviceAddress)
{
   for (uint8_t i = 0; i < 8; i++)
   {
      if (deviceAddress[i] < 16) Serial.print("0");
      Serial.print(deviceAddress[i], HEX);
   }
}

void loop()
{
   sensors.requestTemperatures(); // Send the command to get temperatures
   sendData();
   delay( ( 5l * 60l * 1000l) - 11000l  ); // wait 5 minutes
}

Tagged with:

Categorised as:


Visitor Locator, Take Two

The new version that I hacked together stores number of visits per country and shows the totals when a user clicks a countrys' marker. Visits are stored in an SQLite database, which, as you may know, makes things very easy as there is no server to look after etc. I was thinking of using Berkeley DB, because in an app like this, all that SQL is simply unnecessary sugar, but was lazy in the end (as usual). Update: Added country flags in place of the same default icon for every country (see: Custom Icons section in Google Maps API). Update 2: Added tooltip-like functionality, which shows country details in a transient window (label) instead of the default info window. See GxMarker for additional info. Continuing here from where last nights' script ended. This is just the PHP side of things; Google Maps API examples can be found elsewhere. First we open an SQLite database and create a table for our visitor data if table does not exist:
try {
        $db = new PDO('sqlite:' . $_SERVER['DOCUMENT_ROOT'] . '/../db/visitor-locator.sqlite3');
} catch(PDOException $exception) {
        die($exception->getMessage());
}

$stmt = $db->query('SELECT name FROM sqlite_master WHERE type = 'table'');
$result = $stmt->fetchAll();
if(sizeof($result) == 0) {
        $db->beginTransaction();
        $db->exec('CREATE TABLE visits (country TEXT, visits INTEGER, lat TEXT, lng TEXT);');
        $db->commit();
}
Next, check if the country is already in the table and if it is, increment the 'visits' field:
$stmt = $db->query('SELECT country, visits FROM visits WHERE country = '' . $countryname . ''');
$result = $stmt->fetch();

if($result['country']) {
        $db->beginTransaction();
        $stmt = $db->prepare('UPDATE visits SET visits=:visits, lat=:lat, lng=:lng WHERE country=:country');
        $stmt->bindParam(':country', $countryname, PDO::PARAM_STR);
        $visits = $result['visits'] + 1;
        $stmt->bindParam(':visits', $visits, PDO::PARAM_INT);
        $stmt->bindParam(':lat', $lat, PDO::PARAM_STR);
        $stmt->bindParam(':lng', $lng, PDO::PARAM_STR);
        $stmt->execute();
        $db->commit();
}
If country was not in the table, create a row for it:
else {
        $db->beginTransaction();
        $stmt = $db->prepare('INSERT INTO visits (country, visits, lat, lng) VALUES (:country, :visits, :lat, :lng)');
        $stmt->bindParam(':country', $countryname, PDO::PARAM_STR);
        $visits = 1;
        $stmt->bindParam(':visits', $visits, PDO::PARAM_INT);
        $stmt->bindParam(':lat', $lat, PDO::PARAM_STR);
        $stmt->bindParam(':lng', $lng, PDO::PARAM_STR);
        $stmt->execute();
        $db->commit();
}
And lastly, fetch all rows and form a Javascript array for our client-side script to use:
$result = $db->query('SELECT country, visits, lat, lng FROM visits');

echo "<script type=\"text/javascript\">\n";
echo "//<![CDATA[\n";
echo "var tbl_country = []; var tbl_visits = []; var tbl_lat = []; var tbl_lng = []; var count = 0;\n";
foreach($result->fetchAll() as $row) {
        echo 'tbl_country[count] = \'' . $row['country'] . '\'; ';
        echo 'tbl_visits[count] = \'' . $row['visits'] . '\'; ';
        echo 'tbl_lat[count] = \'' . $row['lat'] . '\'; ';
        echo 'tbl_lng[count] = \'' . $row['lng'] . '\';';
        echo " count++;\n";
}
echo "//]]>\n";
echo "</script>\n";

Tagged with:

Categorised as:


URL Fetch API, MiniDom (Google App Engine)

Fetching stuff with the URL Fetch API is simple (especially if one has faith that the source is there and it will deliver inside GAE time limits):

from google.appengine.api import urlfetch
from xml.dom import minidom

def parse(url):
  r = urlfetch.fetch(url)
  if r.status_code == 200:
    return minidom.parseString(r.content)

As is accessing the resulting DOM with MiniDom. Here the source is an Atom feed:

import time

dom = parse(URL)
for entry in dom.getElementsByTagName('entry'):
  try:
    published = entry.getElementsByTagName('published')[0].firstChild.data
    published = time.strftime('%a, %d %b', time.strptime(published, '%Y-%m-%dT%H:%M:%SZ'))
  except IndexError, ValueError:
    pass
  …

Tagged with:

Categorised as:


Berkeley DB XML Python basics

In an earlier post a C++ snippet can be found where a DB XML container was created (or opened if already exists) and a document read from stdin was put into that container. That same snippet done in Python is pretty much identical:

from bsddb3.db import *
from dbxml import *

mgr = XmlManager(DBXML_ALLOW_EXTERNAL_ACCESS)
uc = mgr.createUpdateContext()

try:
        cont = mgr.openContainer("testcontainer.dbxml", DB_CREATE|DBXML_ALLOW_VALIDATION, XmlContainer.WholedocContainer)
        doc = mgr.createDocument()
        input = mgr.createStdInInputStream()
        doc.setContentAsXmlInputStream(input)
        cont.putDocument(doc, uc, DBXML_GEN_NAME)

except XmlException, inst:
        print "XmlException (", inst.ExceptionCode,"): ", inst.What
        if inst.ExceptionCode == DATABASE_ERROR:
                print "Database error code:",inst.DBError

Tagged with:

Categorised as: