Garmin.DeviceControl.js Module

Provides callback functionality that takes care of polling the plugin for read, write and download operations. It also provides helper functionality that will remove the dependency of manipulating the xml returned.

API

The Garmin.DeviceControl provides:

  • Methods for starting read, write, and download processes
  • Polling of the device to determine process completion and progress
  • Helper objects for easy access to plug-in and device data (progress data, device data)
  • Track data can be retrieved in a number of formats:
    • XML String
    • XML DOM Object
    • Track Object (Garmin.DeviceDataStructures.js)

API Demo

The API demo allows live interactive experimentation with the JavaScript code.

Run API demo

Usage

  1. Verify Garmin Communicator presence
  2. Unlock the Plugin
  3. Connect to GPS Devices
  4. Upload a waypoint to a GPS device

Verify Garmin Communicator presence

This example just verifies that you have the Garmin Communicator ActiveX Plugin installed and that you can communicate with it using JavaScript.

The bare minimums are:

  1. The prototype, plugin and control script elements must be referenced with valid URLs.
  2. The GarminActiveXControl object must be present in the HTML body.

Step-By-Step

  1. Create a web page and name it plugin.html. Then paste in the following code:
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
    <title>Check for Garmin Communicator Plugin</title>
    </head>
    <script type="text/javascript" src="http://developer.garmin.com/web/communicator-api-1.4.2/prototype/prototype.js">&#160;</script>
    <script type="text/javascript" src="http://developer.garmin.com/web/communicator-api-1.4.2/garmin/util/Util-Broadcaster.js">&#160;</script>
    <script type="text/javascript" src="http://developer.garmin.com/web/communicator-api-1.4.2/garmin/util/Util-BrowserDetect.js">&#160;</script>
    <script type="text/javascript" src="http://developer.garmin.com/web/communicator-api-1.4.2/garmin/util/Util-DateTimeFormat.js">&#160;</script>
    <script type="text/javascript" src="http://developer.garmin.com/web/communicator-api-1.4.2/garmin/util/Util-PluginDetect.js">&#160;</script>
    <script type="text/javascript" src="http://developer.garmin.com/web/communicator-api-1.4.2/garmin/util/Util-XmlConverter.js">&#160;</script>
    <script type="text/javascript" src="http://developer.garmin.com/web/communicator-api-1.4.2/garmin/device/GarminObjectGenerator.js">&#160;</script>
    <script type="text/javascript" src="http://developer.garmin.com/web/communicator-api-1.4.2/garmin/device/GarminPluginUtils.js">&#160;</script>
    <script type="text/javascript" src="http://developer.garmin.com/web/communicator-api-1.4.2/garmin/device/GarminDevice.js">&#160;</script>
    <script type="text/javascript" src="http://developer.garmin.com/web/communicator-api-1.4.2/garmin/device/GarminDevicePlugin.js">&#160;</script>
    <script type="text/javascript" src="http://developer.garmin.com/web/communicator-api-1.4.2/garmin/device/GarminDeviceControl.js">&#160;</script> 
    <script type="text/javascript">
        var control;    
        function load() {
            try {
                control = new Garmin.DeviceControl();
                if(control.isPluginInitialized()) {
                        $('message').innerHTML = "<h2>Garmin Communicator plugin version "+control.getPluginVersionString()+" found!</h2>";
                    }
            } catch(e) {
                    $('message').innerHTML = "<h2>" + e.message + "</h2>";
            }
        }
    </script>
    <body onload="load()">
        <h1>Check for Garmin Communicator Plugin</h1>
        <div id="message"></div>
    </body></html>
    
  2. Load it into IE or FireFox.
  3. Verify the you get the 'Communicator Found' message.

Unlock the Plugin

The next example adds a call to unlock the plugin. This call is required before calling any other communicator methods. Normally you pass the base URL of your host site and the key obtained from Garmin, however for development on your localhost you don't need to pass any parameters. The important point about the key is that it must be verified against the exact same URL that was used to generate it. So if the key was generated using 'http://mydomain.com/', none of the following will successfully unlock the plugin:

  1. http://mydomain.com
  2. http://myDomain.com/
  3. http://www.mydomain.com/

Only 'http://mydomain.com/' will work!

Follow the steps in the last example to run this example.

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>Unlock the Plugin</title>
</head>
<script type="text/javascript" src="http://developer.garmin.com/web/communicator-api-1.4.2/prototype/prototype.js">&#160;</script>
<script type="text/javascript" src="http://developer.garmin.com/web/communicator-api-1.4.2/garmin/util/Util-Broadcaster.js">&#160;</script>
<script type="text/javascript" src="http://developer.garmin.com/web/communicator-api-1.4.2/garmin/util/Util-BrowserDetect.js">&#160;</script>
<script type="text/javascript" src="http://developer.garmin.com/web/communicator-api-1.4.2/garmin/util/Util-DateTimeFormat.js">&#160;</script>
<script type="text/javascript" src="http://developer.garmin.com/web/communicator-api-1.4.2/garmin/util/Util-PluginDetect.js">&#160;</script>
<script type="text/javascript" src="http://developer.garmin.com/web/communicator-api-1.4.2/garmin/util/Util-XmlConverter.js">&#160;</script>
<script type="text/javascript" src="http://developer.garmin.com/web/communicator-api-1.4.2/garmin/device/GarminObjectGenerator.js">&#160;</script>
<script type="text/javascript" src="http://developer.garmin.com/web/communicator-api-1.4.2/garmin/device/GarminPluginUtils.js">&#160;</script>
<script type="text/javascript" src="http://developer.garmin.com/web/communicator-api-1.4.2/garmin/device/GarminDevice.js">&#160;</script>
<script type="text/javascript" src="http://developer.garmin.com/web/communicator-api-1.4.2/garmin/device/GarminDevicePlugin.js">&#160;</script>
<script type="text/javascript" src="http://developer.garmin.com/web/communicator-api-1.4.2/garmin/device/GarminDeviceControl.js">&#160;</script> 
<script type="text/javascript">
    var control;    
    function load() {
        try {
            control = new Garmin.DeviceControl();
            if(control.isPluginInitialized()) {
                    $('message').innerHTML = "<h2>Garmin Communicator plugin version "+control.getPluginVersionString()+" found!</h2>";
                }
                
                if(control.unlock( ["http://mydomain.com","pasteYourKeyInHere"] )) {
                $('status').innerHTML = "The plug-in has been unlocked successfully";
                        } else {
                                $('status').innerHTML = "The plug-in was not unlocked successfully";
                        }
        } catch(e) {
                $('message').innerHTML = "<h2>" + e.message + "</h2>";
        }
    }
</script>
<body onload="load()">
    <h1>Unlock the Plugin</h1>
    <div id="message"></div>
    <div id="status"></div>
</body></html>

Connect to GPS Devices

This example starts getting more interesting and demonstrates how to get a list of connected devices. The key point in this example is the use of call-back method to handle the plugin responses. The two steps typical of handling call-back communication with the plugin are:

  1. Create a listener class with call-back methods of interest. Note all call-back methods are prefixed with on, in this case the method is onFinishFindDevices:
    var listener = Class.create();
    listener.prototype = { 
        onFinishFindDevices: function(json) { 
        ... }}
    
  2. Register an instance of the listener class with the control:
    control.register( new listener() );
    

Step-By-Step

  1. Paste thoe following code into an html file called devices.html
  2. Load it into your browser
  3. Plugin a GPS device using a USB cable and turn it on
  4. Click on the Load Devices button (it may take a few seconds to find them)
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
    <title>Connect to Garmin GPS Devices</title>
    </head>
    <script type="text/javascript" src="http://developer.garmin.com/web/communicator-api-1.4.2/prototype/prototype.js">&#160;</script>
    <script type="text/javascript" src="http://developer.garmin.com/web/communicator-api-1.4.2/garmin/util/Util-Broadcaster.js">&#160;</script>
    <script type="text/javascript" src="http://developer.garmin.com/web/communicator-api-1.4.2/garmin/util/Util-BrowserDetect.js">&#160;</script>
    <script type="text/javascript" src="http://developer.garmin.com/web/communicator-api-1.4.2/garmin/util/Util-DateTimeFormat.js">&#160;</script>
    <script type="text/javascript" src="http://developer.garmin.com/web/communicator-api-1.4.2/garmin/util/Util-PluginDetect.js">&#160;</script>
    <script type="text/javascript" src="http://developer.garmin.com/web/communicator-api-1.4.2/garmin/util/Util-XmlConverter.js">&#160;</script>
    <script type="text/javascript" src="http://developer.garmin.com/web/communicator-api-1.4.2/garmin/device/GarminObjectGenerator.js">&#160;</script>
    <script type="text/javascript" src="http://developer.garmin.com/web/communicator-api-1.4.2/garmin/device/GarminPluginUtils.js">&#160;</script>
    <script type="text/javascript" src="http://developer.garmin.com/web/communicator-api-1.4.2/garmin/device/GarminDevice.js">&#160;</script>
    <script type="text/javascript" src="http://developer.garmin.com/web/communicator-api-1.4.2/garmin/device/GarminDevicePlugin.js">&#160;</script>
    <script type="text/javascript" src="http://developer.garmin.com/web/communicator-api-1.4.2/garmin/device/GarminDeviceControl.js">&#160;</script> 
    <script type="text/javascript">
        var control;
        //create a call-back listener class
        var listener = Class.create();
        listener.prototype = { 
            initialize: function() { },
            onFinishFindDevices: function(json) { 
                var devices = json.controller.getDevices();
                var str = "<b>Devices Found: "+devices.length+"</b><ol>";
                if (json.controller.numDevices > 0) {
                    for( var i=0; i < devices.length; i++ ) {
                        str += "<li>"+devices[i].getDisplayName()+"</li>";
                    }
                    str += "</ol>";
                }
                $('devices').innerHTML = str;
            }
        }
    
        function load() {
            try {
                control = new Garmin.DeviceControl();
                control.register(new listener());
                var unlocked = control.unlock( ["http://mydomain.com","pasteYourKeyInHere"] );
                $('msg').innerHTML = "<h2>Found Plugin, unlocked="+unlocked+"</h2>";
            } catch(e) { alert(e); }
        }
    
        function findDevices() {
            try {
                control.findDevices();
            } catch(e) { alert(e); }
        }
    </script>
    
    <body onload="load()">
        <h1>Auto Load Plugin</h1>
        <div id="msg"></div>
        <div id="devices"></div>
        <input type="button" value="Find Devices" onclick="findDevices()">
    </body></html>
    

Upload a waypoint to a GPS device

Next-up, sending data back to a GPS device. This example consists of a text box that contains an example GPX file and a Write To Device button. As long as the text is valid GPX it will be accepted by the device so feel free to put your own data here. You can try this functionality out first on the API Demo page. The code is very similar to the last example and we'll leave it to you to read through it. Enjoy...

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>Write GPX Data to Garmin GPS</title>
</head>
<style type="text/css" media="all">@import "apidemo/garminGpsControlAPIDemo.css";</style>
<script type="text/javascript" src="http://developer.garmin.com/web/communicator-api-1.4.2/prototype/prototype.js">&#160;</script>
<script type="text/javascript" src="http://developer.garmin.com/web/communicator-api-1.4.2/garmin/util/Util-Broadcaster.js">&#160;</script>
<script type="text/javascript" src="http://developer.garmin.com/web/communicator-api-1.4.2/garmin/util/Util-BrowserDetect.js">&#160;</script>
<script type="text/javascript" src="http://developer.garmin.com/web/communicator-api-1.4.2/garmin/util/Util-DateTimeFormat.js">&#160;</script>
<script type="text/javascript" src="http://developer.garmin.com/web/communicator-api-1.4.2/garmin/util/Util-PluginDetect.js">&#160;</script>
<script type="text/javascript" src="http://developer.garmin.com/web/communicator-api-1.4.2/garmin/util/Util-XmlConverter.js">&#160;</script>
<script type="text/javascript" src="http://developer.garmin.com/web/communicator-api-1.4.2/garmin/device/GarminObjectGenerator.js">&#160;</script>
<script type="text/javascript" src="http://developer.garmin.com/web/communicator-api-1.4.2/garmin/device/GarminGpsDataStructures.js">&#160;</script>
<script type="text/javascript" src="http://developer.garmin.com/web/communicator-api-1.4.2/garmin/device/GarminPluginUtils.js">&#160;</script>
<script type="text/javascript" src="http://developer.garmin.com/web/communicator-api-1.4.2/garmin/device/GarminDevice.js">&#160;</script>
<script type="text/javascript" src="http://developer.garmin.com/web/communicator-api-1.4.2/garmin/device/GarminDevicePlugin.js">&#160;</script>
<script type="text/javascript" src="http://developer.garmin.com/web/communicator-api-1.4.2/garmin/device/GarminDeviceControl.js">&#160;</script> 
<script type="text/javascript">
    var GarminDeviceControlDemo = Class.create();
    GarminDeviceControlDemo.prototype = {

        ////////////////////////////////////////////////////////////////////////
        //prototype constructor method:
        
        initialize: function(statusDiv, mapId) {        
            this.status = $(statusDiv);
            this.findDevicesButton = $("findDevicesButton");
            this.cancelFindDevicesButton = $("cancelFindDevicesButton");
            this.deviceSelect = $("deviceSelect");
            this.deviceInfo = $("deviceInfoText");
            this.writeDataButton = $("writeDataButton");
            this.cancelWriteDataButton = $("cancelWriteDataButton");
            this.writeDataText = $("writeDataText");
            this.writeDataFilename = $("writeDataFilename");
            this.progressBar = $("progressBar");
            this.progressBarDisplay = $("progressBarDisplay");
            this.garminController = null;
            this.tracks = null;
            this._intializeController();
            this._setStatus("Plug-in initialized.  Find some devices to get started.");
            this.findDevicesButton.disabled = false;
            this.findDevicesButton.onclick = function() {
                this.findDevicesButton.disabled = true;
                this.cancelFindDevicesButton.disabled = false;
                this.garminController.findDevices();
            }.bind(this)
        },
        
        ////////////////////////////////////////////////////////////////////////
        //Garmin.DeviceControl call-back methods:

        onFinishFindDevices: function(json) {
            this.findDevicesButton.disabled = false;
            this.cancelFindDevicesButton.disabled = true;

            if(json.controller.numDevices > 0) {
                var devices = json.controller.getDevices();
                this._setStatus("Found " + devices.length + " devices.");
                this._listDevices(devices);
                
                this.cancelWriteDataButton.onclick = function() {
                    this.writeDataButton.disabled = false;
                    this.cancelWriteDataButton.disabled = true;
                    this._hideProgressBar();
                    this.garminController.cancelWriteToDevice();
                }.bind(this)
    
                this.writeDataButton.disabled = false;            
                this.writeDataButton.onclick = function() {
                    this.writeDataButton.disabled = true;
                    this.cancelWriteDataButton.disabled = false;
                    this._showProgressBar();
                    this.garminController.writeToDevice(this.writeDataText.value, this.writeDataFilename.value);
                }.bind(this);
            } else {
                this._setStatus("No devices found.");
            }
        },

        onStartFindDevices: function(json) {
            this._setStatus("Looking for connected Garmin devices");
        },

        onCancelFindDevices: function(json) {
            this._setStatus("Find cancelled");
        },

        //The device already has a file with this name on it.  Do we want to override?  1 is yes, 2 is no 
        onWaitingWriteToDevice: function(json) {    
            if(confirm(json.message.getText())) {
                this._setStatus('Overwriting file');
                json.controller.respondToMessageBox(true);
            } else {
                this._setStatus('Will not be overwriting file');
                json.controller.respondToMessageBox(false);
            }
        },
    
        onProgressWriteToDevice: function(json) {
            this._updateProgressBar(json.progress.getPercentage());
            this._setStatus(json.progress);
        },
    
        onFinishWriteToDevice: function(json) {
            this._hideProgressBar();
            this._setStatus("Data written to the device.");
            this._hideProgressBar();
            this.writeDataButton.disabled = false;
            this.cancelWriteDataButton.disabled = true;
        },

    
        ////////////////////////////////////////////////////////////////////////
        //internal utility methods:

        _intializeController: function() {
            try {
                this.garminController = new Garmin.DeviceControl();
                this.garminController.unlock( ["http://mydomain.com","pasteYourKeyInHere"] );
                this.garminController.register(this);
            } catch (e) {
                if(e == "OutOfDatePluginException") {
                    alert("Plug-in out of date");
                } else if(e == "PluginNotInstalledException") { 
                    alert("Plug-in not installed");
                } else if(e == "BrowserNotSupportedException") { 
                    alert("Browser not supported");
                } else {
                    alert("Error initializing - " + e);
                }
            }
        },

        _showProgressBar: function() {
            Element.show(this.progressBar);
        },

        _hideProgressBar: function() {
            Element.hide(this.progressBar);
        },

        _updateProgressBar: function(value) {
            var percent = (value <= 100) ? value : 100;
            this.progressBarDisplay.style.width = percent + "%";
        },

        _listDevices: function(devices) {
            for( var i=0; i < devices.length; i++ ) {
                this.deviceSelect.options[i] = new Option(devices[i].getDisplayName(),devices[i].getNumber());
                if(devices[i].getNumber() == this.garminController.deviceNumber) {
                    this.deviceSelect.selectedIndex = i;
                    this._showDeviceInfo(devices[i]);
                }
            }
            this.deviceSelect.onchange = function() {
                var device = this.garminController.getDevices()[this.deviceSelect.value];
                this._showDeviceInfo(device);
                this.garminController.setDeviceNumber(this.deviceSelect.value);
            }.bind(this)
            this.deviceSelect.disabled = false;
        },

        _showDeviceInfo: function(device) {
            this.deviceInfo.innerHTML = "Part Number:\t\t" + device.getPartNumber() + "\n";
            this.deviceInfo.innerHTML += "Software Version:\t" + device.getSoftwareVersion() + "\n";
            this.deviceInfo.innerHTML += "Description:\t\t" + device.getDescription() + "\n";
            this.deviceInfo.innerHTML += "Id:\t\t\t" + device.getId();
        },
    
        _setStatus: function(statusText) {
            this.status.innerHTML = statusText;
        }
    };

    //display is created when HTML page is loaded
    var display;
        
    function load() {
        display = new GarminDeviceControlDemo("statusText", "readMap");
    }
</script>

<body onload="load()">

<h2>Write GPX Data to Garmin GPS</h2>

<div id="actionStatus">
    <div id="statusText">Status Text</div>

    <div id="progressBar" style="display: none;" align="left">
        <div id="progressWrapper"><div id="progressBarDisplay">&#160;</div></div>
    </div>
</div>

<div id="deviceBox">
    <input type="button" value="Find Devices" id="findDevicesButton" disabled="true" />
    <input type="button" value="Cancel Find Devices" id="cancelFindDevicesButton" disabled="true" />

    <br />
    <select name="deviceSelect" id="deviceSelect" disabled="true">
        <option value="-1">No Devices Found</option>
    </select>
    <br />
    <textarea id="deviceInfoText" rows="3" cols="60"></textarea>
</div>

<div id="writeBox">
    <input type="button" value="Write To Device" id="writeDataButton" disabled="true" />
    <input type="button" value="Cancel Write To Device" id="cancelWriteDataButton" disabled="true" />
    <br />
    Filename: <input type="text" id="writeDataFilename" value="test.gpx"><br />
    Write Contents:<br /> 
    <textarea id="writeDataText" name="writeDataText" rows="21" cols="75">
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<gpx xmlns="http://www.topografix.com/GPX/1/1" version="1.1" creator="mymy">
        <metadata>
                <link href="http://www.garmin.com">
                        <text>Garmin International</text>
                </link>
                <time>2006-12-23T02:02:36Z</time>
        </metadata>
        <wpt lat="37.778721" lon="-122.414819">
                <name>Burger King</name>
                <desc>1200 Market St
San Francisco, CA 94102</desc>
                <sym>Fast Food</sym>
        </wpt>
        <wpt lat="37.867791" lon="-122.499298">
                <ele>19.35</ele>
                <name>Motionbased</name>
                <sym>Waypoint</sym>
        </wpt>
</gpx>
    </textarea>
</div>

</body>
</html>