« January 2006 | Main | March 2006 »

February 14, 2006

Another Bad UI Decision

I finally solved a problem I had with my text editor on my work computer. The keyboard shortcut CTRL+SHIFT+I just wouldn't work, while the opposite function with CTRL+I worked fine. I figured perhaps the new keyboard was at fault. Some googling later I found that Trillian was the culprit. By default it attaches itself to several hotkey combinations and appears to block other apps. I don't know about you, but installing a system wide hotkey by default seems really wrong. One of the keys to UI design that some one mentioned that stuck with me: If every user doesn't use the function in the same way, you can't automate it. I think that applies here, I don't use any of the hotkeys Trillian installed, but by installing them by default caused problems for me the user.

Comments (0)

February 03, 2006

My Christmas without a Car

It sounds bad, but it worked out nicely.

Heading to work friday morning the week before the christmas break, some fellow decided to turn onto Waverly directly into the left lane that I was traveling in and very closely in front of me. Waverly is one of the few moderate speed roads in the city. The conditions were still slick from the previous day, I managed to get over to the right lane and avoid the car, but after passing by the slow moving vehicle the rear end caught a ridge of snow. The car ended up rotating about 270 degrees and hitting the curb on the left side of the road. The right rear suspension was damaged but I managed to limp the rest of the block to the dealer who happened to be conveniently located. I got a quick estimate at the dealer and it was clear it needed to go through insurance. The car was undriveable at that point, so MPI (insurance) decided to tow it to their facility in Transcona for assessment. It took several days before they picked it up and more than a week in total before they towed it back to the dealer where I originally left it. Actually, they brought it to the body shop next door. You see, when the dealer recently moved to this new location, the body shop became a separate entity and the dealer no longer had accreditation to do insurance repairs. This became a problem. Although the dealer's shop wasn't busy, the body shop was. As a result the body shop wasn't keeping on top of things as the work was done at the dealer's shop and in my opinion it took twice as long to repair as it should have. Anyway, they ended up replacing the entire right rear suspension components with brand new parts. Surprisingly they also had to replace the rear suspension sub frame. How the sub frame got damaged enough to need replacement, but the rim only got scuffed I'm not quite sure. As for the rim, they did a really nice job polishing out the scrapes. So in the end, it took a month to the day to get my car back. I did have to go back and get the alignment re-done because the steering wheel was offset from center.

Now the good. Without a car and not being able to get one from insurance or the repair shop, I didn't want to attempt to get to work, so I took all the remaining days before christmas off. (My estimate was a ~2 hour bus trip each way or really expensive rental) I managed to get a couple major things done. I unpacked and repacked several of the large bins I use for storage and moving. I put most of those into storage, along with all the empty boxes that had piled up in my dining room from moving. I cleaned up my bedroom and reorganized it. I went out and got a new bed. Updated a whole bunch of my web site and got in lots of relaxation.

Not having a car meant the typical christmas events got rearranged. The family came over to my place instead of going to my dads. My mom drove to the family get together, which oddly was a couple weeks early due to christmas vacations this year. And I had to borrow my mom's car to get to a christmas geocaching event.

Comments (0)

Webcam

I had wanted to setup a unique geocache type, a webcam cache. I started with all the extra equipment that I had readily available. I had plenty of video capture cards that work on everything from Macs to Sparcs, but no video camera. Work had tons of surplus Quickcams, but they were just too old and couldn't produce a good outdoor image. So I found a cheap standalone IP based webcam on ebay. Its an Orite IC300. Out of the box, the webcam is only configurable with Internet Explorer (IE) and the live video is an ActiveX control that also only works in IE. Since I myself don't even use IE, I wanted to provide a much more universal interface as well as something that didn't look like a hacked together engrish page. I looked around for examples and couldn't find anything. Most of the webcams out there were broken or just the default webcam pages. So I spent a lot of time creating a site and thought I'd share some of the results. You can view the webcam at http://www2.ertyu.org/webcam/.

My first thought was to update the Orite camera to a newer firmware version. (If in doubt, update, cross fingers and see if that fixes anything without breaking anything else.) Unfortunately it seems I had an older version which couldn't do field upgrades. After a lengthy conversation with the Canadian rep, who seemed less than reliable at first, I shelled out a few bucks to upgrade to the newest hardware version. Finally after getting the unit back, I found nothing new :(
I did manage to dig up some technical information from the rep's website though. The camera provides JPEG still frame and MJPEG live stream interfaces.

See Update Below

Providing a live stream is obviously the most difficult, but its also the most rewarding. Netscape/Mozilla/Firefox based browsers support displaying an MJPEG stream natively. So now I had support for two major browser groups, the ActiveX control from the manufacturer for IE and the MJPEG stream for Netscape & Mozilla based browsers. I wanted universality though. It then boiled down to JAVA. I evaluated many many packages and they all sucked in some way or another. I settled on Cambozola (I'm still hoping Cortado will get updated and work better). There were still issues with permissions and functionality though. I didn't want to expose the IP camera itself too publicly, ideally I wanted it on the internal private network with the viewer on a public webserver. Unfortunately JAVA's security prevents an unsigned applet from accessing remote locations. I ended up setting up a proxy for the JPEG and MJPEG data from the camera on the webserver for the JAVA applet to use (webcamproxy.php). This prevents having to sign the applet with weak or unknown credentials. (At one point I remember having to click "I trust Andy." hehe) The proxy also inserts a timestamp into the JPEG data (timestamp.php). I went with an older version of the applet because it seemed to work better. The JAVA applet, although it works, doesn't work well enough to use exclusively. So with the ActiveX, MJPEG and JAVA live streaming versions I had enough to support any reasonable browser that could display a live stream, but I needed to select the optimal version for each browser. I used the Full Featured PHP Browser Detection & OS Detection code to do basic auto-select but allow a manual override (live.php). So thats the bells and whistles, a few basics to tidy up. The main page provides a basic JPEG image that is refreshed using javascript (index.html). It ended up after working on all this, that a borrowed ActiveX control from Axis (another webcam company) worked better than the one provided by Orite (The Orite control (WinWebPush.cab) is provided by the webcam chip manufacturer, Winbond).

Update
I wasn't quite satisfied with the performance of the webcam. Each viewer would end up running off a separate stream to the webcam (which lead to a few cam crashes) and they would run the live stream as fast as they could or until I ran out of bandwidth. Instead I inserted Motion between the webcam and the website. It grabs a single stream from the cam and distributes to the web. It adds the ability to produce an configured frame rate mjpeg stream, as well as to vary frame rate based on detected motion or idle state. It also adds its a timestamp and can generate periodic snapshots and many other image modification abilities. I also changed the live page to use mjpeg for Safari and Konquerer which now support mjpeg natively.

If you want to revert to the simpler method without motion, change webcamproxy.php as follows:
- motion server->webcam address and change the port too (8081->80 likely)


$urlstring = "GET /GetData.cgi?Status=1 HTTP/1.0\r\n\r\n

or if you want to use a password on the webcam

$urlstring = "GET /GetData.cgi?Status=1 HTTP/1.0\r\nAuthorization: BASIC ".base64_encode ("username:password')."\r\n\r\n";

JAVA applet: webcamViewer.jar

ActiveX control: AMC.cab

webcamproxy.php:

<?php
  set_time_limit(0);
  $fp = fsockopen ("motion server", 8081, $errno, $errstr, 30);
  if (!$fp) {
    echo "$errstr ($errno)<br>\n";
  } else {
    $urlstring = "GET / HTTP/1.0\r\n\r\n";
    fputs ($fp, $urlstring);
    while ($str = trim(fgets($fp, 4096)))
      header($str);
    fpassthru($fp);
    fclose($fp);
  }
?>

live.php:

<?php
//...Full Featured PHP Browser Detection & OS Detection code goes here
$style = (isset($_GET['style'])) ? $_GET['style'] : auto;
?>
<html>
<body>
<?php
if
(
  (
    ($style == 'auto')
    &&
    (browser_detection( 'browser' ) == 'ie')
    &&
    (
      (browser_detection( 'os' ) == 'win')
      ||
      (browser_detection( 'os' ) == 'nt')
    )
  )
  ||
  ($style == 'activex')
)
{
?>
<object id="Player" width="640" height="480" border="0"
classid="CLSID:745395C8-D0E1-4227-8586-624CA9A10A8D" codebase="AMC.cab">
  <param name="AutoStart" value="1">
  <param name="UIMode" value="none">
  <param name="MediaType" value="mjpeg-unicast">
  <param name="NetworkTimeout" value="5000">
  <param name="MediaUsername" value="webcam">
  <param name="MediaPassword" value="webcam">
  <param name="MediaURL"value="http://www2.ertyu.org/webcam/webcamproxy.php">
</object>
<a href="live.php?style=mjpeg" class="header">MJPEG</a>
<a href="live.php?style=activex" class="selected">ActiveX</a>
<a href="live.php?style=java" class="header">Java</a>
<?php
}
else if
(
  (
    ($style == 'auto')
    &&
    (
      (browser_detection( 'browser' ) == 'moz')
      ||
      (browser_detection( 'browser' ) == 'ns')
      ||
      (browser_detection( 'browser' ) == 'saf')
      ||
      (browser_detection( 'browser' ) == 'konq')
    )
  )
  ||
  ($style == 'mjpeg')
)
{
?>
<img src="webcamproxy.php">
<a href="live.php?style=mjpeg" class="selected">MJPEG</a>
<a href="live.php?style=activex" class="header">ActiveX</a>
<a href="live.php?style=java" class="header">Java</a>
<?php
}
else
{
?>
<applet code="com.charliemouse.cambozola.Viewer"' archive="webcamViewer.jar" width="640" height="480">
  <param name="url" value="webcamproxy.php">
  <param name="accessories" value="Info"/>
  <param name="accessorystyle" value="overlay">
</applet>
<a href="live.php?style=mjpeg" class="header">MJPEG</a>
<a href="live.php?style=activex" class="header">ActiveX</a>
<a href="live.php?style=java" class="selected">Java</a>
<?php
}
?>
</body>
</html>

index.html:

<html>
<head>
<script language="Javascript" type="text/javascript">
   <!-- hide
    var x = 30;
    var y = 1;
    var now;
  
    function startClock() {
     x = x-y;
     document.form1.clock.value = x;
     if (x <= 1) reload();
     timerID = setTimeout("startClock()", 1000);
    }
  
    function reload() {
     now = new Date();
     var camImg = "snapshot.jpg" + "?" + now.getTime();
     document.campicture.src = camImg;
     x = 30;
     document.form1.clock.value = x;
    }
   // end hide -->
</script>
</head>
<body onLoad="startClock()">
<img name="campicture" src="snapshot.jpg" border=0
alt="WebCam"></td>
<form NAME="form1">Auto Reload
in ~<input TYPE="text" NAME="clock" SIZE="2" VALUE> seconds.</form>
</body>
</html>

motion.conf excerpts:

netcam_url http://webcam.ertyu.org/Jpeg/CamImg.jpg
snapshot_interval 25
text_right
text_left %Y-%m-%d\n%T-%q %Z
target_dir /WEBSITE_LOCATION
snapshot_filename snapshot
webcam_port 8081
webcam_motion off
webcam_maxrate 2

Although Motion supports periodic output I already had it setup via script running with cron.
grab.sh:

#!/bin/csh

set DIRROOT='/DIR/webcam-archive'
set URL="http://webcam.ertyu.org/Jpeg/CamImg.jpg"

set YEAR=`date "+%Y"`
set MONTH=`date "+%m"`
set DAY=`date "+%d"`
set TIME=`date "+%R"`

if !(-d $DIRROOT/$YEAR/$MONTH/$DAY/) then
mkdir -p $DIRROOT/$YEAR/$MONTH/$DAY
endif

wget -O $DIRROOT/$YEAR/$MONTH/$DAY/$TIME.jpg $URL >& /dev/null

Comments (7)




Created By: Steven Nikkel (steven_nikkel@ertyu.org)
This webpage and others materials are Copyright © 1997-2016 Steven Nikkel, All Rights Reserved
counter