Absolute beginners guide to Google Maps JavaScript v3

Since I first published my HowTo and the subsequent follow up for novices to get a Google Map on a web page it’s been the most popular post on my site by quite a margin.  Sadly it’s been resting on its laurels, and is now quite out of date and indeed broken.  So spurred on by my recent server replacement and attempt to revitalise this blog I present the new, improved, and generally working… Beginners Guide To Google Maps JavaScript v3.

The premise is simple; you’ve got a requirement to put a map on your site.  You don’t have the first clue how to do it.  You follow these instructions and you get you map.  Hopefully you’ll pick up enough to tweak the map to your requirements, if not – please ask in the comments and I’ll try and help you.  I’m assuming that you’ve got a bit of HTML experience, and that you’ve got a JavaScript debugger available to you (either Firebug for Firefox or Developer Tools built in to Chrome).

I’ve based a lot of this on the official Google tutorial here:  https://developers.google.com/maps/documentation/javascript/tutorial.  (I’m pretty sure they borrowed that from me in the first place, so it’s only fair ;) ).

Part 1.  Getting the map on the page

Get yourself an API key for Google Maps from here:  https://developers.google.com/maps/documentation/javascript/tutorial#api_key

Let’s start from the end and work back to the beginning.  Save this as an HTML document, change the API key, open it in your browser and you’ll have a map.  I’ve saved you a bit of time by already centring it on Barrow-in-Furness bus depot.

[js]
<!DOCTYPE html>
<html>
<head>
<title>My first Google Map</title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<style type="text/css">
html { height: 100% }
body { height: 100%; margin: 0; padding: 0 }
#map-canvas { height: 100% }
</style>
<script type="text/javascript"
src="https://maps.googleapis.com/maps/api/js?key=XXXXXXXXXXXXXXXX&sensor=false">
</script>
<script type="text/javascript">
function initialize() {
var myLatLng = new google.maps.LatLng(54.124634, -3.237029)
var mapOptions = {
center: myLatLng,
zoom: 17,
mapTypeId: google.maps.MapTypeId.SATELLITE
};

var map = new google.maps.Map(document.getElementById("map-canvas"),
mapOptions);

var myMarker = new google.maps.Marker({
position: myLatLng,
map: map,
title: "A place on Earth",
draggable: true,
})
}

google.maps.event.addDomListener(window, ‘load’, initialize);
</script>
</head>
<body>
<div id="map-canvas"/>
</body>
</html>
[/js]

Copy and paste that in to a text editor, replace XXXXXXXXXXXXXXXX with your own API key, save it somewhere and the load it up in your browser.  You should see a satellite style map with a marker in the middle. You’re done.  Simple eh?  Read on learn a bit about how it works, and what you can do to change the appearance.

Part 1.1 Understanding the basic HTML

In order to try and guarantee a consistent layout across browsers you need to make sure that your page is rendered in ‘Standards Compliant’ mode as opposed to ‘Quirks’ mode. To do this you need to specify a DOCTYPE at the top of your HTML file.  We’re using a very simple “html” DOCTYPE which tells the browser that we’re HTML5.  In HTML4.x there were a plethora of variations – thankfully we don’t need to care about them anymore.  HTML5 is the way to go, and so the only DOCTYPE we care about is “html”.

We set the title of the page, and then we set some initial viewport settings to help mobile browsers render the page correctly.  This is widely regarded as a good thing, and you can learn more about it from here: http://webdesign.tutsplus.com/tutorials/htmlcss-tutorials/quick-tip-dont-forget-the-viewport-meta-tag/

Skipping over the style and scripts for a moment, we create the main body of the page with a single div element in it.  We give it the id “map-canvas”, and then we close off the bottom of the body and mark the end of the HTML.  You won’t be surprised to read that the div we’ve just created will be where the map will soon appear.

Part 1.2 All about style

In standard HTML5 (remember the DOCTYPE from above) there are a few specifics you need to know about CSS.  If an element specifies a size as a percentage, then that percentage is calculated from the parent objects size.  Imagine you have a nested DIV, called DIV2.  It lives inside DIV1.  Where DIV1 has a fixed size of 500px by 500px, then DIV2 knows that 100% high equals 500px, but what if DIV1 didn’t have a size specified?  In that case, in standards mode, DIV2 would decide that 100% high equals zero px – because it doesn’t know any better.  This has caught people out a few times.  In order to make sure that all our DIVs can inherit a size correctly we set the height of the entire HTML page and the BODY to be 100%.  This is calculated by the browser when the page loads, and then can flow down to the elements within the page correctly.

Once we have the parent elements size set correctly (the page, and the body) we can style our map DIV to be 100% high safe in the knowledge that it has enough information to render and the correct size and not 0 px high.

Part 1.3 The Meat Section

Now we’re going to look at the actual JavaScript and understand what it’s doing and in which order.

First of all, we have the scripts in the HEAD tag.  The browser will load the head part of the HTML first and your scripts will be loaded before the page is fully rendered.  Any functionality that you make available in your scripts should be available to the rest of the page when it comes to need it.  This is generally the right way to do it.

The first SCRIPT tag takes care of loading the Google Maps code.  We tell the browser that the content of the script is text/javascript and then where to find it.  There are a couple of parameters we pass  in to the script through the URL.  The first one is “key” – this is your simple API key for access Google Maps (see above for details of where to get this key).  The second parameter is “sensor”.  This is required and must be “false” if you’re not using a GPS (or similar) to work out where you are.  In our case, we’re just picking a point on and saying “centre the map here” – so we use false.  If were using a GPS to centre the map on our current location, then this would be “true”.

This script gets loaded by the browser and now we can start to make use of the Google Maps JavaScript APIs in the rest of our page.

The second script is a bit more complex, but should be easy to understand:

We create a new function called “initialize”.
Inside that function we create an object called myLatLng.  We use the Google provided API google.maps.LatLng() to create an object which can be understood by the rest of the Google Maps API and pass in the co-ordinates of Barrow-in-Furness bus depot.  We use “var” to limit that object’s “scope” to within the “initialize” function – that is to say, we won’t be able to get access to that particular myLatLng from other functions on the page.
Next we create another thing called mapOptions.  The format of this is as per the spec here: https://developers.google.com/maps/documentation/javascript/reference?hl=en#MapOptions

There are loads of options, most of which we don’t need to worry about, so we’re just setting a few key options:  where the map is centered, how much it is zoomed in, and the type of map we see.  The map types are provided by Google as a set of constants, which are identifiable by being all in upper case.  In our case we’re using SATELLITE, but we could also use HYBRID, ROADMAP or TERRAIN.

Once we’ve set up the various mapOptions we create a new var called “map” which is an instance of a Map object as provided by the Google APIs.  We pass in to it the id of the HTML object where we want the map to appear, as we created in section 1.2, and we pass in the options var which we just created.  This is enough information for the Google APIs to set up the map as we want it and put it on the page.

The last thing we do in our example is add a marker.  A marker is the indicator which you use to highlight a point on the map.  Google provide a lot of icons and colours for us to use, but the default is the red tear-drop one, so we’ll stick with that for now.

To create a marker we create a new instance of google.Maps.Marker and set up some of the options as we did for the map itself.  We tell it the position for the marker to appear.  We use the “myLatLng” object we created earlier.  You might notice that we are using the myLatLng object twice in our example.  Once as the centre point for the map, and once for the position of the marker.  You can probably deduce from this that the marker will appear in the centre of the map.  We also tell the marker which map it should be added to.  We only have one map on our page, but if we had many this is how you’d add a marker to the correct map.  We give it a title, which is simply a string and we make it draggable by setting the draggable option to “true”.  You can read more about the marker options here: https://developers.google.com/maps/documentation/javascript/reference?hl=en#MarkerOptions

That’s very nearly it for our first simple map.  The last thing to do is use a DOM listener to trigger the above JavaScript when the page loads, and so make our map and marker appear.

google.maps.event.addDomListener is provided via the Google APIs and we pass in three pieces of information.  window is the object provided by the browser.  The ‘load’ event is actually is separate from the “onload” event you might have read about.  The load event signifies that the page is fully rendered and any JavaScript which wants to manipulate the DOM can begin work, and that’s what we want to do.  We want to swap the empty div with the id of “map” with the actual map.  So once the page is indeed loaded the command will execute the “initialize” function and all the magic will happen.

And that’s it.  We’re done.  We’ve got a map on the page centred at our chosen location, and there is a little marker to show a specific part of the map.

If you compare this to the original Beginners Guide I think you’ll say that this new version of the API is even easier to use.  I will try and find time of the next few months to jot down a few notes on doing more interesting things with the map but I hope that this will get you started.

Combining MythTV and Asterisk

I’ve had this idea for a while and with the discovery of the Google Text-to-speech and Voice Recognition AGI scripts from Zaf (http://zaf.github.io/asterisk-googletts/ & http://zaf.github.io/asterisk-speech-recog/) I’ve implemented a quick proof-of-concept.

You can see the results in this YouTube video:

Over the next few days I’ll tidy up the code and write up a blog post about how to do it.  It’s pretty straight forward though, using APIs provided by Google, MythTV and Asterisk and then just glueing them together.

 

Convincing MythTV to tune in to DVB-T2 MUXes

So that I remember for next time, and so I can start writing down some of the issues I’ve had to sort out since re-building my servers, here is what you have to do to tune to a DVB-T2 mux in MythTV (0.27 fixes).

This is the frequency for the PSB3 mux on Sandy Heath, I expect the encoding scheme will work pretty much where ever. At the very least it should get you started:

 

Frequency:  474200000
Bandwidth:  8 MHz
Inversion:  Auto
Constellation:  QAM 256
LP Coderate: 2/3
HO Coderate: Auto
Trans. Mode: 8K
Guard Interval: 1/32
Hierarchy:  None

If that doesn’t work, and you know it should (as in you are on the same transmitter) try setting the tuning timeouts higher. Also, just blindly re-trying because “WHY DOESN’T IT WORK” seemed to help.

And we’re back…

I’ve moved to another server, and in the process I’ve had a whole lot of problems.  For anyone that’s read any of my blog before that won’t come as a surprise.

Once I’ve got all the kinks worked out, I’ll tell you how I fixed it.  For now, this is just a test…

Asterisk UK Caller ID & SMS redux

Update 28 Dec 2013:  As far as caller ID goes, I might have been barking up completely the wrong tree here.  Have a look here: http://forums.digium.com/viewtopic.php?f=1&t=85028.  I’ve re-implemented that patch for Dahdi and I’m testing it now.  Get in touch if you want to test it as well.  Once I’m happy it’s actually working, I’ll post it here.

 

tl;dr: Scroll down to “How to fix Caller ID in the UK on Asterisk 11 and Dahdi 2.6.1″

I’ve been having some problems with Asterisk 1.6 for a while now, in that when I’m dialled in to conferences via SIP, or when I call someone via the work Asterisk server from my Asterisk server at home I get cut off every 15 minutes. My colleagues have all kind of accepted this now, it was starting to get annoying. It was a known problem in Asterisk 1.6, and so I was going to have to upgrade.

The Ubuntu Asterisk packages are fairly up-to-date but FreePBX isn’t packaged, and it’s a pain in the backside to get set up with the correct permissions, especially if you install Asterisk from packages. I had a spare machine anyway so I decided that I’d give FreePBX Distro a go and once I’d burnt the ISO to a CD (ya rly) I found the set up process to be simple and quick.

FreePBX Distro is a stripped down CentOS (2.6.32 kernel) which boots quick, has minimal footprint and bundles in loads and loads of FreePBX “apps” like conferences, voicemail, blacklisting and makes setting up extensions a breeze. It also includes things like kernel source for I sell settlement so building extra modules from source is pretty easy. Which is a good job, because it was about to get messy.

If you’ve found this page via Google then this will probably sound pretty familiar:

  • You got a TDM400p four port FXO/FXS interface card, or a clone from someone like OpenVox (which work perfectly by the way – as do those cheap daughter cards off eBay).
  • You’ve upgraded to Asterisk 11, or Asterisk 1.8 perhaps, or changed to the Dahdi 2.6.1 drivers and all of a sudden your ”UK Caller ID” has “stopped working” or at the very least become “intermittent“.
  • It was working fine before, so it’s not a hardware issue and your phone provided have NOT suddenly stopped sending caller ID information, regardless of what people of forums tell you. No, in fact this is clearly a bug which has crept in somewhere along the line.
  • You’ve searched and searched and tried things like setting rxgain=x.x and txgain=x.x or whatever. (Side note: setting txgain and rxgain in chan_dahdi_channels_custom.conf has no effect, the only place is seems to work is in chan_dahdi_groups.conf)
  • You might have even stumbled across a post hinting that cid_rxgain=x.x will solve your problems, only it didn’t

If that sounds like you, dear reader, then read on. I am your salvation.

  1. This page: http://downloads.openvox.cn/pub/drivers/callerid_patches/ (I can only attribute this discovery to divine intervention)
  2. Find a new wctdm.c driver here: http://downloads.openvox.cn/pub/drivers/callerid_patches/2.6.1-wctdm.c
  3. Download the 2.6.1 Dahdi source from here: http://downloads.asterisk.org/pub/telephony/dahdi-linux-complete/dahdi-linux-complete-2.6.1+2.6.1.tar.gz
  4. Replace dahdi-linux-complete-2.6.1+2.6.1/linux/drivers/dahdi/wctdm.c with the version downloaded from openvox
  5. Note it doesn’t compile, add the missing semicolon to line 333 (or thereabouts), successfully build and install the new driver
  6. You might need to change /etc/modprobe.d/dahdi.conf and add:
options wctdm opermode=UK fwringdetect=1 battthresh=4
  1. restart Dahdi and Asterisk and caller ID should now be fixed! Yay!

How to fix Caller ID in the UK on Asterisk 11 and Dahdi 2.6.1

Here is a patch against wctdm.c from stock Dahdi 2.6.1 with the fixes in: wctdm.c.patch

OR: Replace dahdi-linux-complete-2.6.1+2.6.1/linux/drivers/dahdi/wctdm.c with this one: wctdm.c

OR: If you’re running FreePBX distro 64 bit “BETA-3.211.63-5 Release Date-01-24-13″ (or close) here is a binary driver: wctdm.ko  Move it to /lib/modules/2.6.32-279.11.1.el6.x86_64/dahdi/wctdm.ko

It works for me. I have not had to increase the rxgain, or txgain or anything else. It just works.

Once that’s working, we can move on to…

How to send & receive SMS in the UK on FreePBX Distro Beta 3.211

I’ve talked about receiving and sending SMSes before, but that was quite a long time ago, and things have moved on a bit since then. I’ve also learnt a bit more about the Asterisk dial plan, and have a slightly cleaner way of doing it now.

You need to have working caller ID. Hint: see above.
You need to install smsq.
smsq doesn’t come built in FreePBX Distro so you have to build it yourself if you want to send SMS. This is pretty easy:

  1. Download the Asterisk 11.2.1 source from here: http://downloads.asterisk.org/pub/telephony/asterisk/asterisk-11.2.1.tar.gz
  2. Install popt: yum install popt-devel.i686 popt.i686 popt.x86_64 popt-devel.x86_64 (prerequisite for smsq)
  3. In the Asterisk source directory do “./configure”
  4. run “make menuselect”
  5. Scroll down to “Utilities”
  6. In the right hand pane, check “smsq”
  7. Save & Exit
  8. run “make”
  9. DO NOT run “make install” as this will trash your FreePBX config
  10. Once that’s done you should find an executable smsq in the utils directory

Just to be sure, create /var/spool/asterisk/sms/motx and /var/spool/asterisk/sms/mtrx
You can find more details on building Asterisk here: http://blogs.digium.com/2012/11/05/how-to-install-asterisk-11-on-centos-6/

You need to be able to send SMS in order to register with the BT SMS system, otherwise when you receive an SMS you will get a phone call from the BT robots who will read the text to you, badly.

To register with BT try this:

<path to smsq>/smsq –motx-channel=DAHDI/2/17094009 -d 00000 -m “test”

where DAHDI/2 is the channel number of your outgoing line.

If you look in the Asterisk logs you should see the message going out with some TX and RX hex dumps. If it works, a short while later you will receive a phone call from either the SMS system trying to talk modem at you, or the robot. Either way, this means your text went out. Great success!

Now we need to set up receive, which is pretty straight forward.

Edit /etc/asterisk/extensions_custom.conf and add the below. Note – I’ve added a lot of comments to explain what’s going on, it might improve readability if you take them out.

[from-internal-additional-custom]
;; This makes sure our new 'app' gets included in the FreePBX dial plan
include => app-rx-sms
[app-rx-sms]
;; This is the app to receive an SMS which will be called when we match
;; the caller ID of an incoming call to the BT computer
exten => s,1,Answer()
;; This wait seems to help
exten => s,n,Wait(0.5)
;; We simply use the built in SMS function
exten => s,n,SMS(default,a)
;; Hangup with code 16, normal termination.
exten => s,n,Hangup(16)
;; Done
;; We also extend the from-pstn context with a branch to the SMS app
;; if the caller ID matches, hence why it's necessary to get caller
;; id working first
[from-pstn-custom]
;; we add ourselves in to the end of the current dialplan
;; priority 7 gets us there...
exten => s,7,GotoIf($["${CALLERID(num)}" = "08005875290"]?app-rx-sms,s,1)
;; pretty simple - if the caller ID matches, go to the sms app
exten => s,n(dest-ext),Goto(ext-group,1100,1)
;; Note: 1100 is my "ring all" group. You will need to change 1100
;; to what ever you use. You should see this at the end of the
;; from-pstn context in extensions_additional.conf

Save that, and in asterisk do a “dialplan reload”. From smsq send an SMS to 00000 saying “register”· If everything works you should get a text file in /var/spool/asterisk/sms/mtrx.