Archive

Archive for November, 2009

Making maps from GIS data with Inkscape

November 25th, 2009

NOTE- I more or less dropped this project, in favor of a more precise approach, as outlined in Using Google Maps to produce usable, printable maps. This is being left just to give other people ideas.

Background

I was recently asked by one of the officers of our volunteer fire department if I could come up with a good map of our town that could be laminated and put in the trucks. We currently have a really simple PDF map of our town, but it was done by a for-profit entity and is only available as the single-size PDF. The map itself looks like:

town map

Data

With a little research, I was able to find quite a lot of GIS data on the NJ Department of Environmental Protection GIS site. While the GIS viewer software by ESRI seems to be the usual choice, I found that the GPL’ed Quantum GIS project (available in the OpenSuSE Application:Geo repository) displayed the data quite nicely. The only major issue was with street names – there was no way to label lines with two fields from the metadata (the TIGER/Line files have separate fields for the street name and the st/rd/ln suffix). More importantly, I needed something that both looked nice and included overlays (specifically of the fire department’s hydrant map).

SVG

A little research led me to the shptosvg perl script that converts a shapefile to SVG. As the streets within our town won’t change any time soon, I figured it was the most logical solution, when producing a map for print where I would need to re-scale and edit overlay layers – to just get the data I needed into SVG and do the rest there. I was able to export both the county roads shapefile and the state municipal boundaries shapefile to an SVG drawing, and then open that in Inkscape. To export them, I used:

perl shptosvg.pl -x3300 -y5100 -p1 -d0.5 berrds00.shp muni_boundaries/nj_munis.shp > test2.svg

where berrds00.shp is the TIGER/Line roads shapefile for our county (from the 2000 census) and muni_boundaries/nj_munis.shp is the shapefile for the NJ municipal boundaries. The x and y sizes (3300px and 5100px, respectively) were based on an 11×17″ sheet printed at 300dpi.

Initial Work

The initial work was a real pain. I moved each group of objects (the municipal boundaries and the county road lines) to a separate layer and then ungrouped them. Next, I began the painstaking process of deleting all of the objects outside of our town boundary, except the roads directly around our town. Once this was done, I used File -> Document Properties -> Fit to Page Selection to “crop” the canvas to the remaining objects. Thanks to the nature of SVG, I was able to crop the page down and then scale it up again to 11×17″ without any loss of data or quality. I then moved the roads outside of our town (luckily, most of the roads from the TIGER data ended up being made up of a series of line segments, with most of them having a break at the town boundary) to another layer, so that they could be easily given a light gray color. I also gave the down boundary a nice red color. Finally, as I neglected to include a railroad shapefile when I did the original conversion to SVG, and adding one would obviously not jive with the massive deletion and re-scaling I’d done, I drew in the one railroad line running through town by hand, and gave it a nice dashed line type.

At this point, I ended up with something that looked like:

inkscape work version 1

Cleaning Up

I now had the following tasks to perform:

  1. Find a nicer way to show the street lines. The ideal would be a line made up of 1-2px lines on either side, with a white center. Second best would just be thinner lines.
  2. Cleanup the roads around the town boundary – make sure they’re black within the town and gray outside. If need be. delete some lines and re-draw them to split at the town boundary.
  3. Add labels for the bordering towns.
  4. The big one – add street name labels.
  5. Perhaps add in icons/labels/boxes for churches, schools, municipal buildings, etc.
  6. Add in, once I get a copy of the map, the fire department hydrant locations as another layer.

And the added bonuses that I’d like to do:

  1. Add house numbering on a block level for each street.
  2. Add a grid overlay, with an index of streets by grid square on the back.

As of right now (about 9AM on November 25, 2009) this is where I stand. I’ll update a bit more when I get farther along.

Tech HowTos , , , ,

Android links – maps, dial a phone number

November 22nd, 2009

If you’ve used Google search from an Android device to search for a business, you’ve probably noticed the two interesting “buttons” to the right of the search listing – “Get Directions” and a button for the phone number. It turns out, these are pretty easy to implement.

The “Get Directions” link is a simple link to Google Maps like This One. The links are actually pretty simple:

<a href="http://maps.google.com/maps?daddr=42+Pierce+Ave%2C+Midland+Park%2C+NJ+07432">Get Directions</a>

It just uses a regular Google Maps URL, with the destination address encoded. When the link is clicked in the Android browser, a dialog pops up asking the user whether he wants to open it with the browser or the Maps application. If Maps is selected, it automatically opens with the address from the URL in the destination input box, the phone’s current location as the start input, and gives easy access to directions and navigation.

The telephone links are a bit more interesting. Apparently, the Android browser uses the Phone app to handle the “tel” scheme, as defined by RFC 3966.Therefore, clicking a link like:

<a href="tel:2015555555">201-555-5555</a>

on Android will bring up the Phone app and pre-enter the digits for 2015555555. Luckily, it doesn’t automatically dial the number. If you want to give it a try and are using Android: 201-555-5555.

The final step is how to implement this. I don’t know if most mobile browsers (Blackberry? iPhone?) also support the “tel” URI scheme, or how they’ll handle Google Maps links. But if you’re looking to include Android-specific content, the user agent string from my Motorola Droid (Android 2.0) looks like:

Mozilla/5.0 (Linux; U;Android 2.0; en-us; Droid Build/ESD20) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17

I know that there are a number of PHP classes out there to detect browsers (like Chris Schuld’s browser.php) and some things to detect mobile device capabilities (like WURFL or Tera WURFL, both using the WURFL data). However, if you just need to know whether your user is on Android or not, I’d personally recommend just checking the user agent string for “Linux”, “Android” and “WebKit” until a better browser identification system is found, as these are not likely to change in the near future.

Uncategorized , ,

root on a Cyclades ACS console server

November 18th, 2009

At work we have a Cyclades ACS16 console server (running Cyclades-ACS16-Linux V_3.2.0 (Jan/04/08)). While the docs claim all sorts of LDAP features, there’s nothing (either in the web GUI or the CLI configuration tool) to setup LDAP with TLS or required group membership. I tried modifying the /etc/ldap.conf and /etc/nsswitch.conf files, running saveconf and runconf and even rebooting, but no luck. It was apparent that I needed root on the box. Unfortunately, they don’t give you root, and their sudo command is locked down. But, I figured, if sudo would let me and chown and cat and mv (enough to switch out the ldap.conf and nsswitch.conf files), root should be pretty easy.

The failing of Cyclades’ sudo lockdown is that it allows sudo execution of a few random shell scripts, and also allows `mv`.

The /etc/sudoers:

# sudoers file.
#
# This file MUST be edited with the 'visudo' command as root.
#
# See the sudoers man page for the details on how to write a sudoers file.
#
 
# User alias specification
 
# Runas alias specification
 
# Host alias specification
 
# Cmnd alias specification
Cmnd_Alias     SH_CMDS = /bin/cp,\
                         /bin/chown,\
                         /bin/egrep,\
                         /bin/grep,\
                         /bin/cat,\
                         /bin/tar,\
                         /bin/kill,\
                         /bin/mkdir,\
                         /bin/mv,\
                         /bin/rm,\
                         /bin/sed,\
                         /bin/touch,\
                         /sbin/reboot,\
                         /usr/bin/killall,\
                         /usr/bin/w,\
                         /bin/w_cas,\
                         /bin/sess_mngt,\
                         /sbin/route,\
                         /bin/what
 
Cmnd_Alias     CONF_FILES = /bin/vi /etc/network/st_routes,\
                            /bin/vi /etc/portslave/pslave.conf,\
                            /bin/vi /etc/resolv.conf
 
Cmnd_Alias     APPLICATIONS = /bin/pmCommand,\
                              /bin/saveconf,\
                              /bin/restoreconf,\
                              /bin/runconf,\
                              /bin/daemon.sh,\
                              /bin/manageService.sh,\
                              /bin/dsviewKillAdmin, \
                              /bin/pmfwupgrade, \
                              /bin/adsap2_clear, \
                              /bin/upgrade_power.sh, \
                              /bin/signal_ras
 
# User privilege specification
# root can run any command on any host as any user.
root    ALL = (ALL) ALL
 
# admin user group command specification.
%admin      ALL = NOPASSWD: SH_CMDS, CONF_FILES, APPLICATIONS

So, /bin/upgrade_power.sh doesn’t look like we’re using it too much. Here’s our root procedure. Before doing this, create the /home/admin/foo.sh script.

sudo cp /bin/upgrade_power.sh /bin/upgrade_power.sh.SAVE
sudo chown root:root /home/admin/foo.sh
sudo mv /home/admin/foo.sh /bin/upgrade_power.sh
sudo /bin/upgrade_power.sh
sudo cat /etc/sudoers # just to verify that it worked
sudo mv /bin/upgrade_power.sh.SAVE /bin/upgrade_power.sh # set things back to the way they were

And the key to all of it is the simple /home/admin/foo.sh script:

#!/bin/bash
 
chmod u+w /etc/sudoers
echo "%admin      ALL = NOPASSWD: ALL" >> /etc/sudoers
chmod u-w /etc/sudoers

That’s it!

Tech HowTos , ,

Droid Camera problem solved

November 18th, 2009

Gizmodo – The Real Reason the Droid’s Camera Fixed Itself.

Well, it’s definitely good news to know that the problem with the camera on my beautiful new Droid is only a software issue. However it’s not too reassuring to know that Google (or could it have been Motorola devs?) let code out which obviously has a bit of an issue with a… rather predictable… value.

android , ,

Motorola Droid – Volume way too low

November 17th, 2009

I’m not sure how I did it, but I’ve had my Droid for a few hours under a week – the phone’s uptime is about 187 hours – and I’ve already got a major problem. Sometime this weekend, somehow, the volume for everything got set way too low. Incoming call ringer, notifications, alarms, Google Maps Navigation, everything seems to be playing through the speaker at the regular in-call volume – i.e. the volume that it should be at if the handset is up to my ear.

I happened by one blog post mentioning this issue. The two resolutions mentioned were a soft reset and a replacement of the phone. Hoping for the former, I performed a soft reset – using the good ‘ol Ctrl + Alt + Del sequence – and this seems to have fixed it. Now I just have to hope that it stays fixed…

My personal theory is that some application – whether a code problem or a crash – left the speaker in a low-volume state. Most likely was my poking around in the hidden menus which, at one point, killed the Phone app process.

Tech HowTos ,

Weekend of Code (Android)

November 12th, 2009

The Droid is here (literally, sitting in my pocket), and I have the next two days off of work – plus the weekend. Minus personal commitments, that’s about two full (call it 16 hour) days to get some work done. While I have lots of things that could use my attention – a number of neglected projects, my big new PHPsa project, and some server consolidation at home – I’ve decided to dedicate the time to Android development.

I’ve got the ADK installed and running, and the emulator is wonderful (especially with the Droid skin). And I know it’s wrong, but I think I’m going to be developing the first app for Android 2.0 (especially given the new ContactsContract API in 5).

I’m having a few issues with Subclipse, even on the latest OpenSuSE 11.1, and still have a few things I want to do on the phone… but hopefully I’ll have a beta build of the app by the end of the weekend. I’ve already done most of the data modeling and sketched out the storyboard.

I’m not going to say much about what the app is until it’s ready, but it’s something targeted at people like me – SysAdmins with way too many things on their plate for their number of waking hours.

android ,

Running a script on USB drive insertion

November 11th, 2009

Before I even get into how to do this, be warned: this is a really bad idea unless you can ensure total physical access control to the machine. About the only place I’d ever use it is in a non-networked embedded system in a secure location. Its original intent is to handle loading of pictures onto a Linux-based digital photo frame.

So, you want to run a specific script on insertion of a USB drive. Here’s how to use udev to do it:

  1. Create /etc/udev/rules.d/99-usbhook.rules:
    ACTION=="add",KERNEL=="sd*", SUBSYSTEMS=="usb", ATTRS{product}=="Mass Storage", RUN+="/root/bin/usbhook %k"

    This will run “/root/bin/usbook”, passing it the device name as an argument, every time a USB Mass Storage device is plugged in.

  2. run udevcontrol reload_rules
  3. Create your usbhook script.
  4. Enjoy

Here is my usbhook script to copy all files from a USB mass storage disk to a specific location. It includes quite a bit of debugging, and also checks for the presence of a file called “foobarbaz.txt” on the device before copying the files over.

#!/bin/bash
 
# script to move over all files from a USB key
# when it is inserted into the system.
 
# should be called from a udev rule like:
#ACTION=="add",KERNEL=="sd*", SUBSYSTEMS=="usb", ATTRS{product}=="Mass Storage", RUN+="/root/bin/usbhook %k"
 
# Copyright 2009 Jason Antman. <jason@jasonantman.com> <http://www.jasonantman.com>
# <http://blog.jasonantman.com/2009/11/running-a-script-on-usb-drive-insertion/>
 
# CONFIGURATION
DEBUG=1 # set to 1 for debugging output
DEST="/home/foo/" # destination for files
 
 
DEVICE="$1" # the device name
LOGFACILITY="kernel.info" # for debugging output
 
 
if [ ${DEBUG:=0} == 1 ]; then logger "$LOGFACILITY" usbhook called with arguments: "$DEVICE"; fi
 
sleep 5 # delay 5 seconds to wait for mount
 
mount | grep "$DEVICE"
FOO="$?"
 
if [ $FOO == 0 ];
then
    if [ ${DEBUG:=0} == 1 ]; then logger "$LOGFACILITY" usbhook device mounted: "$DEVICE"; fi
else
    if [ ${DEBUG:=0} == 1 ]; then logger "$LOGFACILITY" usbhook device NOT mounted: "$DEVICE" - exiting; fi
    exit 0
fi
 
BAR=`mount | grep "$DEVICE" | awk '{ print $3 }'`
 
if [ -e "$BAR/foobarbaz.txt" ]
then
    if [ ${DEBUG:=0} == 1 ]; then logger "$LOGFACILITY" usbhook "$BAR"/foobarbaz.txt found; fi
else
    if [ ${DEBUG:=0} == 1 ]; then logger "$LOGFACILITY" usbhook "$BAR"/foobarbaz.txt NOT found - exiting; fi
    exit 0
fi
 
cp -R "$DEVICE"/* "$DEST"

This was tested on OpenSuSE 10.3.

Tech HowTos , , ,

Droid!

November 10th, 2009

I don’t like writing posts with a low useful content quotient, but here goes.

After having only one new (i.e. not used) phone in eight years – and the one new one was a Treo 700p, obsolete when I bought it – I decided to bite the bullet. I bought a Droid! While I was almost dead-set on it before I even held it in the store, my feelings of love at first sight were even more clear when I started to play around with it.

So, here’s a little overview of what I did first, what my plans/questions are, and what’s next.

First minutes/day:

  1. Unpack everything and start to figure things out. Test phone, SMS, data.
  2. Setup IMAP email for my personal account (need to look into IMAP-IDLE).
  3. Go through the entire Settings menu and try to set things up. Find out that the default apps can’t be removed. The app screen, by default, is pretty full…
  4. Export my contacts from my Palm (no sync cable, had to use php-pdb to export a CSV, then manually edit ALL of them in Gmail.

So after having the phone for about 12 hours, here’s what I’ve installed on it:

  • Listen (Google Labs) – Great podcatcher app. The speaker is a bit too quiet for easy listening on the drive to work, so I’ll need to get one of those FM radio interfaces.
  • AnyCut – allows creation of arbitrary shortcuts on the desktop, including direct dial.
  • ConnectBot – full-featured SSH client including key-based auth and storage of multiple user/host settings.
  • Meebo IM – IM client. It does AIM, which is nice, but doesn’t do IRC.
  • Android Battery Dog – App that graphs battery voltage, temperature, capacity over time and also stores a simple CSV log (which I intend to parse out later for historical data).
  • Bookmarking for Delicious – Allows saving of bookmarks to del.icio.us (but not retrieval).
  • To Do List – A very simple To Do list app, until I find something that works with Google Tasks. No syncing.
  • VoiceMemo (JavaCodeLand.com) – A really simple voice memo app.
  • WiFinder (PGMsoft) – Pretty much useless. Shows a scan of WiFi networks, but only shows encryption, channel number, and signal strength in bars.

The few problems I’ve noticed so far:

  • The touch-sensitive buttons along the bottom row (specifically the search button) seem to be right where my thumb wants to rest when holding the phone in landscape mode.
  • As others have mentioned, the camera quality isn’t great, but it’s much better than my Treo 700p.

My list for future research/development:

  • WAP pages for my web-based personal finance app, fuel log, etc.
  • IMAP IDLE
  • Tasks/to do app that syncs with Google Tasks.
  • A Cycle System app.
  • How to quickly mute all sounds on the phone.
  • How to do tones by person or group for not only ringtones (phone) but also SMS, Email, etc. Also, a way to set certain hours of the day when audible alerts will be disabled, other than a specified whitelist (email, SMS, etc.)
  • Verizon Visual Voicemail
  • Do some development with the geolocation JS API.
  • Console on the phone?
  • SCP/SFTP program.
  • TV listings (perhaps a WAP version of my script that pulls from SchedulesDirect (unfortunately, due to their redistribution policy, this is a private, authenticated page).
  • Nagios checker/notifier
  • RSS reader
  • WAP page for PHP EMS Tools callin.
  • How to handle IMAP folders?
  • Script to backup Gmail contacts, other data stored with Google.
  • Thunderbird Gmail contact sync.
  • A wifi scanner/survey software that shows all of the important stuff like signal strength in dbm, noise floor, etc.
  • Something like kismet that integrates the GPS and wifi scanning.

android , ,

Nagios and check plugins run as root

November 5th, 2009

No matter how much we may not like it, and no matter how insecure it can potentially be, we occasionally have to run Nagios check scripts (written in scripting languages) as root. (On a side note, this method is also used for my MultiBindAdmin project’s DNS file push). Here’s how to do it:

  1. Write your check script in the language of your choice and test as root.
  2. Grab setuid-prog.c.
  3. uncomment the DEFINE for FULL_PATH, change the string to the full path to your script.
  4. Be sure your script is owned by root, and is chmod at most 755.
  5. Compile setuid-prog.c:
    gcc -o {check_script_name}-wrapper setuid-prog.c
  6. Put the resulting binary in your plugin directory.
  7. Assuming your checks run as user nagios and group nagios, chown the binary to root:nagios and chmod 4755.

This allows the use of the SUID bit with scripts.

Use at your own risk. I only recommend this on systems where the Nagios account is strongly authenticated, and where ALL users are trusted.

Tech HowTos