Documentation for wearable native Ambient weather reference application.
authorRadek Kintop <r.kintop@samsung.com>
Mon, 16 Nov 2015 12:53:04 +0000 (13:53 +0100)
committerRadek Kintop <r.kintop@samsung.com>
Mon, 16 Nov 2015 12:53:04 +0000 (13:53 +0100)
Change-Id: Ie7d766ef41b59b3e6c33427d76838dab337696b0
Signed-off-by: Radek Kintop <r.kintop@samsung.com>
org.tizen.sampledescriptions/html/images/ambientweather_wn0.png [new file with mode: 0644]
org.tizen.sampledescriptions/html/images/ambientweather_wn1.png [new file with mode: 0644]
org.tizen.sampledescriptions/html/images/ambientweather_wn2.png [new file with mode: 0644]
org.tizen.sampledescriptions/html/images/ambientweather_wn3.png [new file with mode: 0644]
org.tizen.sampledescriptions/html/wearable_n/ambientweather_wn.htm [new file with mode: 0644]
org.tizen.sampledescriptions/html/wearable_n/sd_wn.htm

diff --git a/org.tizen.sampledescriptions/html/images/ambientweather_wn0.png b/org.tizen.sampledescriptions/html/images/ambientweather_wn0.png
new file mode 100644 (file)
index 0000000..b68a37f
Binary files /dev/null and b/org.tizen.sampledescriptions/html/images/ambientweather_wn0.png differ
diff --git a/org.tizen.sampledescriptions/html/images/ambientweather_wn1.png b/org.tizen.sampledescriptions/html/images/ambientweather_wn1.png
new file mode 100644 (file)
index 0000000..5d46583
Binary files /dev/null and b/org.tizen.sampledescriptions/html/images/ambientweather_wn1.png differ
diff --git a/org.tizen.sampledescriptions/html/images/ambientweather_wn2.png b/org.tizen.sampledescriptions/html/images/ambientweather_wn2.png
new file mode 100644 (file)
index 0000000..9e09d72
Binary files /dev/null and b/org.tizen.sampledescriptions/html/images/ambientweather_wn2.png differ
diff --git a/org.tizen.sampledescriptions/html/images/ambientweather_wn3.png b/org.tizen.sampledescriptions/html/images/ambientweather_wn3.png
new file mode 100644 (file)
index 0000000..bed2f4d
Binary files /dev/null and b/org.tizen.sampledescriptions/html/images/ambientweather_wn3.png differ
diff --git a/org.tizen.sampledescriptions/html/wearable_n/ambientweather_wn.htm b/org.tizen.sampledescriptions/html/wearable_n/ambientweather_wn.htm
new file mode 100644 (file)
index 0000000..1508423
--- /dev/null
@@ -0,0 +1,371 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+       <meta http-equiv="content-type" content="text/html; charset=utf-8" />
+       <meta http-equiv="X-UA-Compatible" content="IE=9" />
+       <link rel="stylesheet" type="text/css" href="../css/styles.css" />
+       <link rel="stylesheet" type="text/css" href="../css/snippet.css" />
+       <script type="text/javascript" src="../scripts/snippet.js"></script>
+       <script type="text/javascript" src="../scripts/jquery.util.js" charset="utf-8"></script>
+       <script type="text/javascript" src="../scripts/common.js" charset="utf-8"></script>
+       <script type="text/javascript" src="../scripts/core.js" charset="utf-8"></script>
+       <script type="text/javascript" src="../scripts/search.js" charset="utf-8"></script>
+
+       <title>The Ambient Weather Sample Overview</title>
+</head>
+
+<body class="no-toc" onload="prettyPrint()" style="overflow: auto;">
+
+<div id="toc-navigation">
+</div>
+
+<div id="container"><div id="contents"><div class="content">
+       <div id="profile">
+               <p><img alt="Wearable native" src="../images/wearable_s_n.png"/></p>
+       </div>
+
+  <h1>Ambient Weather Sample Overview</h1>
+
+<p>The Ambient Weather sample application demonstrates how to implement a simple watch with current weather display in ambient mode.</p>
+
+<p>The following figure illustrates two screens of the (Circle) Ambient Weather sample application: the normal mode digital watch view and the ambient mode view with weather data.</p>
+
+<p class="figure">Figure 1: Ambient Weather views</p>
+  <p align="center">
+         <img alt="Ambient Weather views" src="../images/ambientweather_wn0.png" height="240" width="240"/>
+         <img alt="Ambient Weather views" src="../images/ambientweather_wn1.png" height="240" width="240"/>
+  </p>
+
+<p class="figure">Figure 2: Ambient Weather widgets structure</p>
+<p align="center">
+ <img alt="(Circle) Sensors widgets structure" src="../images/ambientweather_wn3.png" height="274" width="284"/>
+</p>
+
+<p>It is worth mentioning that this application is multithreaded. The time consuming task of requesting the weather data has been moved to a separate thread to avoid UI lockups.
+It is demonstarted in Fig. 3.</p>
+
+<p class="figure">Figure 3: Weather data request diagram</p>
+<p align="center">
+ <img alt="(Circle) Sensors widgets structure" src="../images/ambientweather_wn2.png" height="438" width="839"/>
+</p>
+
+<h2>Prerequisites</h2>
+<p>To ensure proper application execution, the following privileges must be set:
+<ul>
+<li><span style="font-family: Courier New,Courier,monospace">http://tizen.org/privilege/network.get</span></li>
+<li><span style="font-family: Courier New,Courier,monospace">http://tizen.org/privilege/keymanager</span></li>
+<li><span style="font-family: Courier New,Courier,monospace">http://tizen.org/privilege/internet</span></li>
+<li><span style="font-family: Courier New,Courier,monospace">http://tizen.org/privilege/alarm.set</span></li>
+</ul>
+</p>
+
+<h2>Implementation</h2>
+
+<h3>Main module</h3>
+<p>The <span style="font-family: Courier New,Courier,monospace">main()</span> function of the sample application is show below. The application loop
+is started when the <span style="font-family: Courier New,Courier,monospace">watch_app_main()</span>
+function is invoked. An object of <span style="font-family: Courier New,Courier,monospace">watch_app_lifecycle_callback_s</span> type can be passed to it.
+Notice how it differs from <span style="font-family: Courier New,Courier,monospace">ui_app_lifecycle_callback_s</span> type used in the standard application type.
+The <span style="font-family: Courier New,Courier,monospace">watch_app_lifecycle_callback_s</span> structure introduces three new pointers to the following callback functions:
+</p>
+<ul>
+ <li><span style="font-family: Courier New,Courier,monospace">watch_app_time_tick_cb</span> - called every second when the application is in normal mode, giving the application a chance to refresh the time indicator,</li>
+ <li><span style="font-family: Courier New,Courier,monospace">watch_app_ambient_tick_cb</span> - called every minute when the application is in ambient mode, giving the application a chance to refresh the time indicator,</li>
+ <li><span style="font-family: Courier New,Courier,monospace">watch_app_ambient_changed_cb</span> - called whenever the application enters normal or ambient mode.</li>
+</ul>
+
+<pre class="prettyprint">
+int main(int argc, char *argv[])
+{
+&nbsp;&nbsp;int ret = 0;
+
+&nbsp;&nbsp;watch_app_lifecycle_callback_s event_callback = {0,};
+
+&nbsp;&nbsp;event_callback.create = app_create;
+&nbsp;&nbsp;event_callback.resume = app_resume;
+&nbsp;&nbsp;event_callback.pause = app_pause;
+&nbsp;&nbsp;event_callback.terminate = app_terminate;
+&nbsp;&nbsp;event_callback.time_tick = app_time_tick;
+&nbsp;&nbsp;event_callback.ambient_tick = app_time_tick;
+&nbsp;&nbsp;event_callback.ambient_changed = app_ambient_changed;
+
+&nbsp;&nbsp;ret = watch_app_main(argc, argv, &event_callback, NULL);
+&nbsp;&nbsp;// Error handling ...
+
+&nbsp;&nbsp;return ret;
+}
+</pre>
+
+<pre class="prettyprint">
+static void app_time_tick(watch_time_h watch_time, void *data)
+{
+&nbsp;&nbsp;// Variables definitions and error handling ...
+&nbsp;&nbsp;__get_date_from_watch_time(watch_time,
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&year, &month, &day, &day_of_week,
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&hours, &minutes, &seconds);
+
+&nbsp;&nbsp;controller_tick(hours, minutes, seconds, year, month, day, day_of_week);
+}
+</pre>
+
+<pre class="prettyprint">
+static void app_ambient_changed(bool ambient_mode, void *data)
+{
+&nbsp;&nbsp;controller_set_ambient_mode(ambient_mode);
+}
+</pre>
+
+<pre class="prettyprint">
+static void __get_date_from_watch_time(const watch_time_h watch_time,
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int *year, int *month, int *day, int *day_of_week,
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int *hours, int *minutes, int *seconds)
+{
+&nbsp;&nbsp;watch_time_get_hour24(watch_time, hours);
+&nbsp;&nbsp;watch_time_get_minute(watch_time, minutes);
+&nbsp;&nbsp;watch_time_get_second(watch_time, seconds);
+&nbsp;&nbsp;watch_time_get_year(watch_time, year);
+&nbsp;&nbsp;watch_time_get_month(watch_time, month);
+&nbsp;&nbsp;watch_time_get_day(watch_time, day);
+&nbsp;&nbsp;watch_time_get_day_of_week(watch_time, day_of_week);
+}
+</pre>
+
+<h3>Main controller module</h3>
+<p>Four important functions of this module are presented below. The <span style="font-family: Courier New,Courier,monospace">controller_start_application()</span>
+function is called at the application's startup. It sets up the view and initiates the
+<span style="font-family: Courier New,Courier,monospace">weather_poll_thread</span>
+module by passing the <span style="font-family: Courier New,Courier,monospace">__weather_poll_data_ready_cb()</span> callback function to it. It also sets the current time on the watch view.</p>
+
+<pre class="prettyprint">
+bool controller_start_application(int width, int height,
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int hour, int min, int sec,
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int year, int month, int day, int week_day)
+{
+&nbsp;&nbsp;if (!view_create_gui(width, height))
+&nbsp;&nbsp;&nbsp;&nbsp;return false;
+
+&nbsp;&nbsp;if (!weather_poll_thread_init(__weather_poll_data_ready_cb))
+&nbsp;&nbsp;&nbsp;&nbsp;return false;
+
+&nbsp;&nbsp;view_set_time(hour, min, sec, year, month, day, week_day);
+
+&nbsp;&nbsp;return true;
+}
+</pre>
+
+<p>The <span style="font-family: Courier New,Courier,monospace">controller_set_ambient_mode()</span> function is called from
+<span style="font-family: Courier New,Courier,monospace">app_ambient_changed()</span>
+callback, defined in the main module. This way, the application can track whether it is in ambient or normal mode.
+It is recommended to stop any power consuming operations in the ambient mode. For example, you can change the display state to one that has most of its pixels dark.</p>
+
+<pre class="prettyprint">
+void controller_set_ambient_mode(bool ambient_mode)
+{
+&nbsp;&nbsp;cdata.ambient_mode = ambient_mode;
+&nbsp;&nbsp;view_set_ambient(cdata.ambient_mode);
+&nbsp;&nbsp;if (cdata.ambient_mode) {
+&nbsp;&nbsp;&nbsp;&nbsp;wifi_monitor_stop_measure();
+&nbsp;&nbsp;} else {
+&nbsp;&nbsp;&nbsp;&nbsp;wifi_monitor_start_measure(__wifi_rssi_level_changed_cb);
+&nbsp;&nbsp;}
+}
+</pre>
+<p>The <span style="font-family: Courier New,Courier,monospace">controller_tick()</span>
+is called with one second interval when the application is in normal mode
+and with one minute interval when it is in ambient mode. It updates the time view display.</p>
+
+<pre class="prettyprint">
+void controller_tick(int hour, int min, int sec,
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int year, int month, int day, int week_day)
+{
+&nbsp;&nbsp;view_set_time(hour, min, sec, year, month, day, week_day);
+}
+</pre>
+
+<p>The <span style="font-family: Courier New,Courier,monospace">__weather_poll_data_ready_cb()</span>
+callback is called in the main thread context whenever the weather polling thread ends its work successfully.
+This function updates the UI in ambient mode by displaying the data received from the server.</p>
+
+<pre class="prettyprint">
+static void __weather_poll_data_ready_cb(xml_weather_t *weather, const void *icon_data, int icon_data_len)
+{
+&nbsp;&nbsp;if (weather) {
+&nbsp;&nbsp;&nbsp;&nbsp;view_set_temperature(weather->temperature.value, weather->temperature.unit);
+&nbsp;&nbsp;&nbsp;&nbsp;view_set_city(weather->city.name, weather->city.country);
+&nbsp;&nbsp;&nbsp;&nbsp;view_set_humidity(weather->humidity.value, weather->humidity.unit);
+&nbsp;&nbsp;&nbsp;&nbsp;view_set_pressure(weather->pressure.value, weather->pressure.unit);
+&nbsp;&nbsp;&nbsp;&nbsp;view_set_wind(weather->wind.name, weather->wind.speed_value, weather->wind.direction_name);
+&nbsp;&nbsp;&nbsp;&nbsp;view_set_clouds(weather->clouds.name);
+&nbsp;&nbsp;&nbsp;&nbsp;view_set_percipitation(weather->precipitation.value);
+&nbsp;&nbsp;&nbsp;&nbsp;view_set_last_update(asctime(&weather->last_update));
+&nbsp;&nbsp;}
+
+&nbsp;&nbsp;if (icon_data && icon_data_len > 0) {
+&nbsp;&nbsp;&nbsp;&nbsp;view_set_icon(icon_data, icon_data_len);
+&nbsp;&nbsp;}
+}
+</pre>
+
+<h3>Weather poll thread controller module</h3>
+
+<p>This module introduces a single <span style="font-family: Courier New,Courier,monospace">ecore timer</span> and its callback launched periodically to execute server data poll function in a separate thread.
+Initialization code is shown below.</p>
+
+<pre class="prettyprint">
+bool weather_poll_thread_init(weather_poll_data_ready_cb cb)
+{
+&nbsp;&nbsp;// Variables definitions and error handling ...
+
+&nbsp;&nbsp;wpt.tim = ecore_timer_add(1.0, __weather_poll_timer_cb, NULL);
+
+&nbsp;&nbsp;// Error handling ...
+
+&nbsp;&nbsp;&nbsp;&nbsp;ecore_timer_freeze(wpt.tim);
+
+&nbsp;&nbsp;return true;
+}
+</pre>
+
+<pre class="prettyprint">
+static Eina_Bool __weather_poll_timer_cb(void *data)
+{
+&nbsp;&nbsp;ecore_timer_interval_set(wpt.tim, WEATHER_POLL_INTERVAL_SEC);
+
+&nbsp;&nbsp;if (!wpt.thread_h) {
+&nbsp;&nbsp;&nbsp;&nbsp;wpt.thread_h = ecore_thread_run(__thread_function, __thread_end_cb, __thread_cancelled_cb, NULL);
+
+&nbsp;&nbsp;&nbsp;&nbsp;// Error handling ...
+&nbsp;&nbsp;}
+
+&nbsp;&nbsp;return EINA_TRUE;
+}
+</pre>
+
+<p>Both <span style="font-family: Courier New,Courier,monospace">__thread_function()</span>
+and <span style="font-family: Courier New,Courier,monospace">__weather_data_read_cb()</span> functions are executed
+on behalf of a separate thread. Since <span style="font-family: Courier New,Courier,monospace">weather_query()</span>
+is a blocking function, its execution from main thread would lock up the UI.
+</p>
+<pre class="prettyprint">
+static void __thread_function(void *data, Ecore_Thread *thread)
+{
+&nbsp;&nbsp;if (!weather_query(__weather_data_read_cb))
+&nbsp;&nbsp;&nbsp;&nbsp;dlog_print(DLOG_ERROR, LOG_TAG, "Failed to make a query");
+}
+</pre>
+
+<p>Any UI update function calls from <span style="font-family: Courier New,Courier,monospace">__weather_data_read_cb()</span>
+are prohibited. So this callback only stores pointers to received data in common memory area.</p>
+
+<pre class="prettyprint">
+static void __weather_data_read_cb(xml_weather_t *weather, image_buffer_t *image_buffer)
+{
+&nbsp;&nbsp;wpt.weather = weather;
+&nbsp;&nbsp;wpt.image_buffer = image_buffer;
+}
+</pre>
+
+<p>The <span style="font-family: Courier New,Courier,monospace">__thread_end_cb()</span> however is called automatically when the
+<span style="font-family: Courier New,Courier,monospace">__thread_function()</span> finishes successfully.
+It is called on behalf of the main thread and this is why it can call a callback from the main controller (updating the UI).
+Server data pointers, previously stored by the <span style="font-family: Courier New,Courier,monospace">__weather_data_read_cb()</span>
+function, are used.
+</p>
+
+<pre class="prettyprint">
+static void __thread_end_cb(void *data, Ecore_Thread *thread)
+{
+&nbsp;&nbsp;char *buffer = NULL;
+&nbsp;&nbsp;int buffer_size = 0;
+
+&nbsp;&nbsp;if (wpt.image_buffer) {
+&nbsp;&nbsp;&nbsp;&nbsp;buffer = wpt.image_buffer->buffer;
+&nbsp;&nbsp;&nbsp;&nbsp;buffer_size = wpt.image_buffer->size;
+&nbsp;&nbsp;}
+
+&nbsp;&nbsp;if (wpt.cb)
+&nbsp;&nbsp;&nbsp;&nbsp;wpt.cb(wpt.weather, buffer, buffer_size);
+
+&nbsp;&nbsp;xml_weather_dispose(wpt.weather);
+&nbsp;&nbsp;weather_free_image_buffer(wpt.image_buffer);
+&nbsp;&nbsp;wpt.weather = NULL;
+&nbsp;&nbsp;wpt.image_buffer = NULL;
+&nbsp;&nbsp;wpt.thread_h = NULL;
+}
+</pre>
+
+<h3>Main view module</h3>
+
+<p>The <span style="font-family: Courier New,Courier,monospace">watch_app_get_elm_win()</span>
+function is used to obtain a special watch type window. This way the application can receive ambient/normal mode switch events properly.</p>
+
+<pre class="prettyprint">
+bool view_create_gui(int width, int height)
+{
+&nbsp;&nbsp;watch_app_get_elm_win(&vd.win);
+
+&nbsp;&nbsp;// Error handling ...
+
+&nbsp;&nbsp;evas_object_resize(vd.win, width, height);
+
+&nbsp;&nbsp;vd.digital_clock = digital_clock_create(vd.win, width, height);
+&nbsp;&nbsp;evas_object_show(vd.digital_clock);
+
+&nbsp;&nbsp;vd.weather = weather_create(vd.win, width, height);
+
+&nbsp;&nbsp;// Common code ...
+}
+</pre>
+
+<p>Each time a time tick occurs, the controller module calls <span style="font-family: Courier New,Courier,monospace">view_set_time()</span>
+function. It updates the digital clock available in the normal application mode.</p>
+
+<pre class="prettyprint">
+void view_set_time(int hours, int minutes, int seconds,
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int year, int month, int day, int week_day)
+{
+&nbsp;&nbsp;digital_clock_set_time(vd.digital_clock, hours, minutes);
+}
+</pre>
+
+<p>The function below is called each time the application mode change occurs. Notice that in ambient mode only the
+weather view is shown, whereas in normal mode only the digital clock is visible.</p>
+
+<pre class="prettyprint">
+void view_set_ambient(bool on_off)
+{
+&nbsp;&nbsp;vd.ambient = on_off;
+
+&nbsp;&nbsp;if (on_off) {
+&nbsp;&nbsp;&nbsp;&nbsp;evas_object_show(vd.weather);
+&nbsp;&nbsp;&nbsp;&nbsp;evas_object_hide(vd.digital_clock);
+&nbsp;&nbsp;} else {
+&nbsp;&nbsp;&nbsp;&nbsp;evas_object_show(vd.digital_clock);
+&nbsp;&nbsp;&nbsp;&nbsp;evas_object_hide(vd.weather);
+&nbsp;&nbsp;}
+}
+</pre>
+
+<script type="text/javascript" src="../scripts/jquery.zclip.min.js"></script>
+<script type="text/javascript" src="../scripts/showhide.js"></script>
+</div></div></div>
+
+<a class="top sms" href="#"><img src="../images/btn_top.gif" alt="Go to top" /></a>
+
+<div id="footer">
+<p class="footer">Except as noted, this content - excluding the Code Examples - is licensed under <a href="http://creativecommons.org/licenses/by/3.0/legalcode" target="_blank">Creative Commons Attribution 3.0</a> and all of the Code Examples contained herein are licensed under <a href="https://www.tizen.org/bsd-3-clause-license" target="_blank">BSD-3-Clause</a>.<br/>For details, see the <a href="https://www.tizen.org/content-license" target="_blank">Content License</a>.</p>
+</div>
+
+<script type="text/javascript">
+var _gaq = _gaq || [];
+_gaq.push(['_setAccount', 'UA-25976949-1']);
+_gaq.push(['_trackPageview']);
+(function() {
+var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
+ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
+})();
+</script>
+
+</body>
+</html>
index f093923..8230b61 100644 (file)
@@ -64,7 +64,7 @@
        <tr> 
      <td><a href="cairo_evasgl_sd_wn.htm">(Circle) Cairo EvasGL</a></td> 
      <td>Demonstrates how you can implement the Cairo GL backend with the Evas_GL surface.</td>
-    </tr>      
+    </tr>
     <tr>
      <td><a href="circlecircular_camera_sd_wn.htm">(Circle) Circular Camera</a></td>
      <td>Demonstrates how you can handle camera features, such as start a camera preview and capture images.</td>
        <tr> 
      <td><a href="rectuidialer_sd_wn.htm">(Rectangle) UI Dialer</a></td> 
      <td>Demonstrates how you can implement a rectangular dialer view.</td>
-    </tr>      
+    </tr>
        <tr>
         <td><a href="rectwidgetviewer_sd_wn.htm">(Rectangle) Widget Viewer</a></td>
         <td>Demonstrates how you can use the widget service and viewer.</td>
        </tr>
+       <tr>
+     <td><a href="ambientweather_wn.htm">Ambient weather</a></td>
+     <td>Demonstrates how you can implement a simple watch with current weather display in ambient mode.</td>
+    </tr>
        <tr> 
      <td><a href="analog_watch_sd_wn.htm">Analog Watch</a></td> 
      <td>Demonstrates how you can implement an analog watch application.</td>