Browse code

updates2022

Louis Jonget authored on05/01/2026 20:27:28
Showing8 changed files
... ...
@@ -1,8 +1,8 @@
1
-# Ignore everything
2
-build/*
3
-build/.*
4
-build/.lock-waf_linux2_build
5
-.lock-waf_linux2_build
6
-
7
-# but pbw built
8
-!build/Pebble-Watchface-Day-and-Night-Earth-Connection-master.pbw
1
+# Ignore everything
2
+build/*
3
+build/.*
4
+build/.lock-waf_linux2_build
5
+.lock-waf_linux2_build
6
+
7
+# but pbw built
8
+!build/Pebble-Watchface-Day-and-Night-Earth-Connection-master.pbw
... ...
@@ -1,3 +1,3 @@
1
-{
2
-    "C_Cpp.errorSquiggles": "Disabled"
1
+{
2
+    "C_Cpp.errorSquiggles": "Disabled"
3 3
 }
4 4
\ No newline at end of file
... ...
@@ -1,21 +1,21 @@
1
-MIT License
2
-
3
-Copyright (c) 2016 ljonget
4
-
5
-Permission is hereby granted, free of charge, to any person obtaining a copy
6
-of this software and associated documentation files (the "Software"), to deal
7
-in the Software without restriction, including without limitation the rights
8
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
-copies of the Software, and to permit persons to whom the Software is
10
-furnished to do so, subject to the following conditions:
11
-
12
-The above copyright notice and this permission notice shall be included in all
13
-copies or substantial portions of the Software.
14
-
15
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
-SOFTWARE.
1
+MIT License
2
+
3
+Copyright (c) 2016 ljonget
4
+
5
+Permission is hereby granted, free of charge, to any person obtaining a copy
6
+of this software and associated documentation files (the "Software"), to deal
7
+in the Software without restriction, including without limitation the rights
8
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+copies of the Software, and to permit persons to whom the Software is
10
+furnished to do so, subject to the following conditions:
11
+
12
+The above copyright notice and this permission notice shall be included in all
13
+copies or substantial portions of the Software.
14
+
15
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+SOFTWARE.
... ...
@@ -1,49 +1,49 @@
1
-{
2
-    "author": "Louis Jonget",
3
-    "dependencies": {},
4
-    "keywords": [],
5
-    "name": "day-night-bt",
6
-    "pebble": {
7
-        "displayName": "Day and Night Earth improved Watchface",
8
-        "enableMultiJS": true,
9
-        "messageKeys": [],
10
-        "projectType": "native",
11
-        "resources": {
12
-            "media": [{
13
-                    "file": "images/menu_icon.png",
14
-                    "menuIcon": true,
15
-                    "name": "IMAGE_MENU_ICON",
16
-                    "targetPlatforms": null,
17
-                    "type": "png"
18
-                },
19
-                {
20
-                    "file": "images/WORLD_MONO",
21
-                    "name": "WORLD_MONO",
22
-                    "targetPlatforms": null,
23
-                    "type": "pbi"
24
-                },
25
-                {
26
-                    "file": "images/BT_ko_icon.png",
27
-                    "name": "BT_ko_icon",
28
-                    "targetPlatforms": null,
29
-                    "type": "bitmap"
30
-                },
31
-                {
32
-                    "file": "images/BATTERY",
33
-                    "name": "BATTERY",
34
-                    "targetPlatforms": null,
35
-                    "type": "bitmap"
36
-                }
37
-            ]
38
-        },
39
-        "sdkVersion": "3",
40
-        "targetPlatforms": [
41
-            "aplite"
42
-        ],
43
-        "uuid": "892e12bc-7a3e-411c-ba97-daa492f91088",
44
-        "watchapp": {
45
-            "watchface": true
46
-        }
47
-    },
48
-    "version": "2.1.0"
1
+{
2
+    "author": "Louis Jonget",
3
+    "dependencies": {},
4
+    "keywords": [],
5
+    "name": "day-night-bt",
6
+    "pebble": {
7
+        "displayName": "Day and Night Earth improved Watchface",
8
+        "enableMultiJS": true,
9
+        "messageKeys": [],
10
+        "projectType": "native",
11
+        "resources": {
12
+            "media": [{
13
+                    "file": "images/menu_icon.png",
14
+                    "menuIcon": true,
15
+                    "name": "IMAGE_MENU_ICON",
16
+                    "targetPlatforms": null,
17
+                    "type": "png"
18
+                },
19
+                {
20
+                    "file": "images/WORLD_MONO",
21
+                    "name": "WORLD_MONO",
22
+                    "targetPlatforms": null,
23
+                    "type": "pbi"
24
+                },
25
+                {
26
+                    "file": "images/BT_ko_icon.png",
27
+                    "name": "BT_ko_icon",
28
+                    "targetPlatforms": null,
29
+                    "type": "bitmap"
30
+                },
31
+                {
32
+                    "file": "images/BATTERY",
33
+                    "name": "BATTERY",
34
+                    "targetPlatforms": null,
35
+                    "type": "bitmap"
36
+                }
37
+            ]
38
+        },
39
+        "sdkVersion": "3",
40
+        "targetPlatforms": [
41
+            "aplite"
42
+        ],
43
+        "uuid": "892e12bc-7a3e-411c-ba97-daa492f91088",
44
+        "watchapp": {
45
+            "watchface": true
46
+        }
47
+    },
48
+    "version": "2.1.0"
49 49
 }
50 50
\ No newline at end of file
... ...
@@ -1,3 +1,3 @@
1
-
2
-// Comment or uncomment to invert the text
3
-//#define BLACK_ON_WHITE
1
+
2
+// Comment or uncomment to invert the text
3
+//#define BLACK_ON_WHITE
... ...
@@ -1,266 +1,266 @@
1
-#include <pebble.h>
2
-#include "config.h"
3
-
4
-#define STR_SIZE 20
5
-#define REDRAW_INTERVAL 1
6
-#define WIDTH 144
7
-#define HEIGHT 72
8
-
9
-static Window *window;
10
-static TextLayer *time_text_layer;
11
-static TextLayer *date_text_layer;
12
-static TextLayer *s_battery_layer;
13
-
14
-static GBitmap *world_bitmap;
15
-
16
-static Layer *canvas;
17
-static GBitmap *image;
18
-static int redraw_counter;
19
-// BT connection & Battery icon declare
20
-static BitmapLayer *s_bt_icon_layer; //*s_battery_icon_layer
21
-static GBitmap *s_bt_icon_bitmap; //*s_battery_icon_bitmap
22
-static bool low_battery;
23
-static int i_battery_level;
24
-// s is set to memory of size STR_SIZE, and temporarily stores strings
25
-char *s;
26
-
27
-
28
-static void draw_earth() {
29
-  // ##### calculate the time
30
-  int now = (int)time(NULL);
31
-
32
-  float day_of_year; // value from 0 to 1 of progress through a year
33
-  float time_of_day; // value from 0 to 1 of progress through a day
34
-  // approx number of leap years since epoch
35
-  // = now / SECONDS_IN_YEAR * .24; (.24 = average rate of leap years)
36
-  int leap_years = (int)((float)now / 131487192.0);
37
-  // day_of_year is an estimate, but should be correct to within one day
38
-  day_of_year = now - (((int)((float)now / 31556926.0) * 365 + leap_years) * 86400);
39
-  day_of_year = day_of_year / 86400.0;
40
-  time_of_day = day_of_year - (int)day_of_year;
41
-  day_of_year = day_of_year / 365.0;
42
-  // ##### calculate the position of the sun
43
-  // left to right of world goes from 0 to 65536
44
-  int sun_x = (int)((float)TRIG_MAX_ANGLE * (1.0 - time_of_day));
45
-  // bottom to top of world goes from -32768 to 32768
46
-  // 0.2164 is march 20, the 79th day of the year, the march equinox
47
-  // Earth's inclination is 23.4 degrees, so sun should vary 23.4/90=.26 up and down
48
-  int sun_y = -sin_lookup((day_of_year - 0.2164) * TRIG_MAX_ANGLE) * .26 * .25;
49
-  // ##### draw the bitmap
50
-  int x, y;
51
-  for(x = 0; x < WIDTH; x++) {
52
-    int x_angle = (int)((float)TRIG_MAX_ANGLE * (float)x / (float)(WIDTH));
53
-    for(y = 0; y < HEIGHT; y++) {
54
-      int y_angle = (int)((float)TRIG_MAX_ANGLE * (float)y / (float)(HEIGHT * 2)) - TRIG_MAX_ANGLE/4;
55
-      // spherical law of cosines
56
-      float angle = ((float)sin_lookup(sun_y)/(float)TRIG_MAX_RATIO) * ((float)sin_lookup(y_angle)/(float)TRIG_MAX_RATIO);
57
-      angle = angle + ((float)cos_lookup(sun_y)/(float)TRIG_MAX_RATIO) * ((float)cos_lookup(y_angle)/(float)TRIG_MAX_RATIO) * ((float)cos_lookup(sun_x - x_angle)/(float)TRIG_MAX_RATIO);
58
-      int byte = y * gbitmap_get_bytes_per_row(image) + (int)(x / 8);
59
-      //if ((angle < 0) ^ (0x1 & (((char *)gbitmap_get_data(world_bitmap))[byte] >> (x % 8)))) {
60
-      if ( (angle < 0) ^ (0x1 & (((char *)gbitmap_get_data(world_bitmap))[byte] >> (x % 8)))) {
61
-        // white pixel
62
-        ((char *)gbitmap_get_data(image))[byte] = ((char *)gbitmap_get_data(image))[byte] | (0x1 << (x % 8));
63
-     } else {
64
-        // black pixel
65
-        ((char *)gbitmap_get_data(image))[byte] = ((char *)gbitmap_get_data(image))[byte] & ~(0x1 << (x % 8));
66
-      }
67
-    }
68
-  }
69
-  layer_mark_dirty(canvas);
70
-}
71
-
72
-static void draw_watch(struct Layer *layer, GContext *ctx) {
73
-  graphics_draw_bitmap_in_rect(ctx, image, gbitmap_get_bounds(image));
74
-}
75
-
76
-static void handle_minute_tick(struct tm *tick_time, TimeUnits units_changed) {
77
-  static char time_text[] = "00:00";
78
-  static char date_text[] = "Xxx, Xxx 00";
79
-
80
-  strftime(date_text, sizeof(date_text), "%a, %b %e", tick_time);
81
-  text_layer_set_text(date_text_layer, date_text);
82
-
83
-  if (clock_is_24h_style()) {
84
-    strftime(time_text, sizeof(time_text), "%R", tick_time);
85
-  } else {
86
-    strftime(time_text, sizeof(time_text), "%I:%M", tick_time);
87
-  }
88
-  if (!clock_is_24h_style() && (time_text[0] == '0')) {
89
-    memmove(time_text, &time_text[1], sizeof(time_text) - 1);
90
-  }
91
-  text_layer_set_text(time_text_layer, time_text);
92
- 
93
-  redraw_counter++;
94
-  if (redraw_counter >= REDRAW_INTERVAL) {
95
-    draw_earth();
96
-    redraw_counter = 0;
97
-  }
98
-}
99
-
100
-
101
-static void bluetooth_callback(bool connected) {
102
-  // Show ko icon if disconnected
103
-  layer_set_hidden(bitmap_layer_get_layer(s_bt_icon_layer), connected);
104
-
105
-  if(!connected && !quiet_time_is_active ()) {
106
-    // Issue a vibrating alert
107
-    vibes_double_pulse();
108
-  } 
109
-}
110
-
111
-static void battery_callback(BatteryChargeState state) {
112
-  static char buff[4] = {};
113
-  int i = 0,temp_num = state.charge_percent, length = 0;
114
-
115
-  // Record the new battery level
116
-  i_battery_level=state.charge_percent;
117
-  // count how many characters in the number
118
-    while(temp_num) {
119
-      temp_num /= 10;
120
-      length++;
121
-    }
122
-  for(i = 0; i < length; i++) {
123
-    buff[(length-1)-i] = '0' + (i_battery_level % 10);
124
-    i_battery_level /= 10;
125
-  }
126
-  buff[i] = '\0'; // can't forget the null byte to properly end our string
127
-  
128
-  text_layer_set_text(s_battery_layer, buff);
129
-  
130
-  // display --icon and-- vibrate if low battery and not charging
131
-  
132
-  if( state.charge_percent < 11 && !low_battery && !state.is_charging ) {
133
-    vibes_double_pulse();
134
-    low_battery = true;
135
-  }else if (state.is_charging){
136
-    low_battery = false;
137
-  }
138
-  // Batterie is now displayed as integer, no need to display icon below
139
-  // layer_set_hidden(bitmap_layer_get_layer(s_battery_icon_layer), !low_battery);
140
-
141
-}
142
-
143
-static void window_load(Window *window) {
144
-#ifdef BLACK_ON_WHITE
145
-  GColor background_color = GColorWhite;
146
-  GColor foreground_color = GColorBlack;
147
-#else
148
-  GColor background_color = GColorBlack;
149
-  GColor foreground_color = GColorWhite;
150
-#endif
151
-  window_set_background_color(window, background_color);
152
-  Layer *window_layer = window_get_root_layer(window);
153
-  GRect bounds = layer_get_bounds(window_layer);
154
-
155
-  time_text_layer = text_layer_create(GRect(0, 72, 144-0, 49));
156
-  text_layer_set_background_color(time_text_layer, background_color);
157
-  text_layer_set_text_color(time_text_layer, foreground_color);
158
-  text_layer_set_font(time_text_layer, fonts_get_system_font(FONT_KEY_ROBOTO_BOLD_SUBSET_49));
159
-  text_layer_set_text(time_text_layer, "--");
160
-  text_layer_set_text_alignment(time_text_layer, GTextAlignmentCenter);
161
-  layer_add_child(window_layer, text_layer_get_layer(time_text_layer));
162
-
163
-  date_text_layer = text_layer_create(GRect(0, 121, 144-0, 21));
164
-  text_layer_set_background_color(date_text_layer, background_color);
165
-  text_layer_set_text_color(date_text_layer, foreground_color);
166
-  text_layer_set_font(date_text_layer, fonts_get_system_font(FONT_KEY_ROBOTO_CONDENSED_21));
167
-  text_layer_set_text(date_text_layer, "--");
168
-  text_layer_set_text_alignment(date_text_layer, GTextAlignmentCenter);
169
-  layer_add_child(window_layer, text_layer_get_layer(date_text_layer));
170
-  
171
-  s_battery_layer = text_layer_create(GRect(102, 147, 42, 20));
172
-  text_layer_set_background_color(s_battery_layer, background_color);
173
-  text_layer_set_text_color(s_battery_layer, foreground_color);
174
-  text_layer_set_font(s_battery_layer, fonts_get_system_font(FONT_KEY_LECO_20_BOLD_NUMBERS));
175
-  text_layer_set_text(s_battery_layer, "---");
176
-  text_layer_set_text_alignment(s_battery_layer, GTextAlignmentRight);
177
-  layer_add_child(window_layer, text_layer_get_layer(s_battery_layer));
178
-
179
-  canvas = layer_create(GRect(0, 0, bounds.size.w, bounds.size.h));
180
-  layer_set_update_proc(canvas, draw_watch);
181
-  layer_add_child(window_layer, canvas);
182
-
183
-  image = gbitmap_create_blank(GSize(WIDTH, HEIGHT), GBitmapFormat1Bit);
184
-
185
-  draw_earth();
186
-  //----------------
187
-  
188
-  // Create the Battery icon GBitmap
189
-  //s_battery_icon_bitmap = gbitmap_create_with_resource(RESOURCE_ID_BATTERY );
190
-  
191
-  // Create the BitmapLayer to display the GBitmap
192
-  /*
193
-  s_battery_icon_layer = bitmap_layer_create(GRect( 127, 143, 14, 22));
194
-  bitmap_layer_set_bitmap(s_battery_icon_layer, s_battery_icon_bitmap);
195
-  layer_add_child(window_layer, bitmap_layer_get_layer(s_battery_icon_layer));
196
-  */
197
-  //----------------
198
-  
199
-  // Create the Bluetooth icon GBitmap
200
-  s_bt_icon_bitmap = gbitmap_create_with_resource(RESOURCE_ID_BT_ko_icon );
201
-  
202
-  // Create the BitmapLayer to display the GBitmap
203
-  s_bt_icon_layer = bitmap_layer_create(GRect( 3, 143, 14, 22));
204
-  bitmap_layer_set_bitmap(s_bt_icon_layer, s_bt_icon_bitmap);
205
-  layer_add_child(window_layer, bitmap_layer_get_layer(s_bt_icon_layer));
206
-  
207
-  // show correct state of battery from start
208
-  battery_callback(battery_state_service_peek());
209
-  // Show the correct state of the BT connection from the start
210
-  bluetooth_callback(connection_service_peek_pebble_app_connection());
211
-}
212
-
213
-static void window_unload(Window *window) {
214
-  text_layer_destroy(time_text_layer);
215
-  text_layer_destroy(date_text_layer);
216
-  layer_destroy(canvas);
217
-  gbitmap_destroy(image);
218
-  gbitmap_destroy(s_bt_icon_bitmap);
219
-  bitmap_layer_destroy(s_bt_icon_layer);
220
-  //gbitmap_destroy(s_battery_icon_bitmap);
221
-  text_layer_destroy(s_battery_layer);
222
-}
223
-
224
-static void init(void) {
225
-  redraw_counter = 0;
226
-
227
-
228
-  world_bitmap = gbitmap_create_with_resource(RESOURCE_ID_WORLD_MONO);
229
-
230
-  window = window_create();
231
-  window_set_window_handlers(window, (WindowHandlers) {
232
-    .load = window_load,
233
-    .unload = window_unload,
234
-  });
235
-  
236
-  const bool animated = true;
237
-  window_stack_push(window, animated);
238
-
239
-  s = malloc(STR_SIZE);
240
-  tick_timer_service_subscribe(MINUTE_UNIT, handle_minute_tick);
241
-  
242
-  // Subscribe to battery info
243
-  battery_state_service_subscribe(battery_callback);
244
-  
245
-  // Register for Bluetooth connection updates
246
-  connection_service_subscribe((ConnectionHandlers) {
247
-    .pebble_app_connection_handler = bluetooth_callback
248
-  });  
249
-}
250
-
251
-static void deinit(void) {
252
-  tick_timer_service_unsubscribe();
253
-  free(s);
254
-  window_destroy(window);
255
-  gbitmap_destroy(world_bitmap);
256
-
257
-}
258
-
259
-int main(void) {
260
-  init();
261
-
262
-  APP_LOG(APP_LOG_LEVEL_DEBUG, "Done initializing, pushed window: %p", window);
263
-
264
-  app_event_loop();
265
-  deinit();
266
-}
1
+#include <pebble.h>
2
+#include "config.h"
3
+
4
+#define STR_SIZE 20
5
+#define REDRAW_INTERVAL 1
6
+#define WIDTH 144
7
+#define HEIGHT 72
8
+
9
+static Window *window;
10
+static TextLayer *time_text_layer;
11
+static TextLayer *date_text_layer;
12
+static TextLayer *s_battery_layer;
13
+
14
+static GBitmap *world_bitmap;
15
+
16
+static Layer *canvas;
17
+static GBitmap *image;
18
+static int redraw_counter;
19
+// BT connection & Battery icon declare
20
+static BitmapLayer *s_bt_icon_layer; //*s_battery_icon_layer
21
+static GBitmap *s_bt_icon_bitmap; //*s_battery_icon_bitmap
22
+static bool low_battery;
23
+static int i_battery_level;
24
+// s is set to memory of size STR_SIZE, and temporarily stores strings
25
+char *s;
26
+
27
+
28
+static void draw_earth() {
29
+  // ##### calculate the time
30
+  int now = (int)time(NULL);
31
+
32
+  float day_of_year; // value from 0 to 1 of progress through a year
33
+  float time_of_day; // value from 0 to 1 of progress through a day
34
+  // approx number of leap years since epoch
35
+  // = now / SECONDS_IN_YEAR * .24; (.24 = average rate of leap years)
36
+  int leap_years = (int)((float)now / 131487192.0);
37
+  // day_of_year is an estimate, but should be correct to within one day
38
+  day_of_year = now - (((int)((float)now / 31556926.0) * 365 + leap_years) * 86400);
39
+  day_of_year = day_of_year / 86400.0;
40
+  time_of_day = day_of_year - (int)day_of_year;
41
+  day_of_year = day_of_year / 365.0;
42
+  // ##### calculate the position of the sun
43
+  // left to right of world goes from 0 to 65536
44
+  int sun_x = (int)((float)TRIG_MAX_ANGLE * (1.0 - time_of_day));
45
+  // bottom to top of world goes from -32768 to 32768
46
+  // 0.2164 is march 20, the 79th day of the year, the march equinox
47
+  // Earth's inclination is 23.4 degrees, so sun should vary 23.4/90=.26 up and down
48
+  int sun_y = -sin_lookup((day_of_year - 0.2164) * TRIG_MAX_ANGLE) * .26 * .25;
49
+  // ##### draw the bitmap
50
+  int x, y;
51
+  for(x = 0; x < WIDTH; x++) {
52
+    int x_angle = (int)((float)TRIG_MAX_ANGLE * (float)x / (float)(WIDTH));
53
+    for(y = 0; y < HEIGHT; y++) {
54
+      int y_angle = (int)((float)TRIG_MAX_ANGLE * (float)y / (float)(HEIGHT * 2)) - TRIG_MAX_ANGLE/4;
55
+      // spherical law of cosines
56
+      float angle = ((float)sin_lookup(sun_y)/(float)TRIG_MAX_RATIO) * ((float)sin_lookup(y_angle)/(float)TRIG_MAX_RATIO);
57
+      angle = angle + ((float)cos_lookup(sun_y)/(float)TRIG_MAX_RATIO) * ((float)cos_lookup(y_angle)/(float)TRIG_MAX_RATIO) * ((float)cos_lookup(sun_x - x_angle)/(float)TRIG_MAX_RATIO);
58
+      int byte = y * gbitmap_get_bytes_per_row(image) + (int)(x / 8);
59
+      //if ((angle < 0) ^ (0x1 & (((char *)gbitmap_get_data(world_bitmap))[byte] >> (x % 8)))) {
60
+      if ( (angle < 0) ^ (0x1 & (((char *)gbitmap_get_data(world_bitmap))[byte] >> (x % 8)))) {
61
+        // white pixel
62
+        ((char *)gbitmap_get_data(image))[byte] = ((char *)gbitmap_get_data(image))[byte] | (0x1 << (x % 8));
63
+     } else {
64
+        // black pixel
65
+        ((char *)gbitmap_get_data(image))[byte] = ((char *)gbitmap_get_data(image))[byte] & ~(0x1 << (x % 8));
66
+      }
67
+    }
68
+  }
69
+  layer_mark_dirty(canvas);
70
+}
71
+
72
+static void draw_watch(struct Layer *layer, GContext *ctx) {
73
+  graphics_draw_bitmap_in_rect(ctx, image, gbitmap_get_bounds(image));
74
+}
75
+
76
+static void handle_minute_tick(struct tm *tick_time, TimeUnits units_changed) {
77
+  static char time_text[] = "00:00";
78
+  static char date_text[] = "Xxx, Xxx 00";
79
+
80
+  strftime(date_text, sizeof(date_text), "%a, %b %e", tick_time);
81
+  text_layer_set_text(date_text_layer, date_text);
82
+
83
+  if (clock_is_24h_style()) {
84
+    strftime(time_text, sizeof(time_text), "%R", tick_time);
85
+  } else {
86
+    strftime(time_text, sizeof(time_text), "%I:%M", tick_time);
87
+  }
88
+  if (!clock_is_24h_style() && (time_text[0] == '0')) {
89
+    memmove(time_text, &time_text[1], sizeof(time_text) - 1);
90
+  }
91
+  text_layer_set_text(time_text_layer, time_text);
92
+ 
93
+  redraw_counter++;
94
+  if (redraw_counter >= REDRAW_INTERVAL) {
95
+    draw_earth();
96
+    redraw_counter = 0;
97
+  }
98
+}
99
+
100
+
101
+static void bluetooth_callback(bool connected) {
102
+  // Show ko icon if disconnected
103
+  layer_set_hidden(bitmap_layer_get_layer(s_bt_icon_layer), connected);
104
+
105
+  if(!connected && !quiet_time_is_active ()) {
106
+    // Issue a vibrating alert
107
+    vibes_double_pulse();
108
+  } 
109
+}
110
+
111
+static void battery_callback(BatteryChargeState state) {
112
+  static char buff[4] = {};
113
+  int i = 0,temp_num = state.charge_percent, length = 0;
114
+
115
+  // Record the new battery level
116
+  i_battery_level=state.charge_percent;
117
+  // count how many characters in the number
118
+    while(temp_num) {
119
+      temp_num /= 10;
120
+      length++;
121
+    }
122
+  for(i = 0; i < length; i++) {
123
+    buff[(length-1)-i] = '0' + (i_battery_level % 10);
124
+    i_battery_level /= 10;
125
+  }
126
+  buff[i] = '\0'; // can't forget the null byte to properly end our string
127
+  
128
+  text_layer_set_text(s_battery_layer, buff);
129
+  
130
+  // display --icon and-- vibrate if low battery and not charging
131
+  
132
+  if( state.charge_percent < 11 && !low_battery && !state.is_charging ) {
133
+    vibes_double_pulse();
134
+    low_battery = true;
135
+  }else if (state.is_charging){
136
+    low_battery = false;
137
+  }
138
+  // Batterie is now displayed as integer, no need to display icon below
139
+  // layer_set_hidden(bitmap_layer_get_layer(s_battery_icon_layer), !low_battery);
140
+
141
+}
142
+
143
+static void window_load(Window *window) {
144
+#ifdef BLACK_ON_WHITE
145
+  GColor background_color = GColorWhite;
146
+  GColor foreground_color = GColorBlack;
147
+#else
148
+  GColor background_color = GColorBlack;
149
+  GColor foreground_color = GColorWhite;
150
+#endif
151
+  window_set_background_color(window, background_color);
152
+  Layer *window_layer = window_get_root_layer(window);
153
+  GRect bounds = layer_get_bounds(window_layer);
154
+
155
+  time_text_layer = text_layer_create(GRect(0, 72, 144-0, 49));
156
+  text_layer_set_background_color(time_text_layer, background_color);
157
+  text_layer_set_text_color(time_text_layer, foreground_color);
158
+  text_layer_set_font(time_text_layer, fonts_get_system_font(FONT_KEY_ROBOTO_BOLD_SUBSET_49));
159
+  text_layer_set_text(time_text_layer, "--");
160
+  text_layer_set_text_alignment(time_text_layer, GTextAlignmentCenter);
161
+  layer_add_child(window_layer, text_layer_get_layer(time_text_layer));
162
+
163
+  date_text_layer = text_layer_create(GRect(0, 121, 144-0, 21));
164
+  text_layer_set_background_color(date_text_layer, background_color);
165
+  text_layer_set_text_color(date_text_layer, foreground_color);
166
+  text_layer_set_font(date_text_layer, fonts_get_system_font(FONT_KEY_ROBOTO_CONDENSED_21));
167
+  text_layer_set_text(date_text_layer, "--");
168
+  text_layer_set_text_alignment(date_text_layer, GTextAlignmentCenter);
169
+  layer_add_child(window_layer, text_layer_get_layer(date_text_layer));
170
+  
171
+  s_battery_layer = text_layer_create(GRect(102, 147, 42, 20));
172
+  text_layer_set_background_color(s_battery_layer, background_color);
173
+  text_layer_set_text_color(s_battery_layer, foreground_color);
174
+  text_layer_set_font(s_battery_layer, fonts_get_system_font(FONT_KEY_LECO_20_BOLD_NUMBERS));
175
+  text_layer_set_text(s_battery_layer, "---");
176
+  text_layer_set_text_alignment(s_battery_layer, GTextAlignmentRight);
177
+  layer_add_child(window_layer, text_layer_get_layer(s_battery_layer));
178
+
179
+  canvas = layer_create(GRect(0, 0, bounds.size.w, bounds.size.h));
180
+  layer_set_update_proc(canvas, draw_watch);
181
+  layer_add_child(window_layer, canvas);
182
+
183
+  image = gbitmap_create_blank(GSize(WIDTH, HEIGHT), GBitmapFormat1Bit);
184
+
185
+  draw_earth();
186
+  //----------------
187
+  
188
+  // Create the Battery icon GBitmap
189
+  //s_battery_icon_bitmap = gbitmap_create_with_resource(RESOURCE_ID_BATTERY );
190
+  
191
+  // Create the BitmapLayer to display the GBitmap
192
+  /*
193
+  s_battery_icon_layer = bitmap_layer_create(GRect( 127, 143, 14, 22));
194
+  bitmap_layer_set_bitmap(s_battery_icon_layer, s_battery_icon_bitmap);
195
+  layer_add_child(window_layer, bitmap_layer_get_layer(s_battery_icon_layer));
196
+  */
197
+  //----------------
198
+  
199
+  // Create the Bluetooth icon GBitmap
200
+  s_bt_icon_bitmap = gbitmap_create_with_resource(RESOURCE_ID_BT_ko_icon );
201
+  
202
+  // Create the BitmapLayer to display the GBitmap
203
+  s_bt_icon_layer = bitmap_layer_create(GRect( 3, 143, 14, 22));
204
+  bitmap_layer_set_bitmap(s_bt_icon_layer, s_bt_icon_bitmap);
205
+  layer_add_child(window_layer, bitmap_layer_get_layer(s_bt_icon_layer));
206
+  
207
+  // show correct state of battery from start
208
+  battery_callback(battery_state_service_peek());
209
+  // Show the correct state of the BT connection from the start
210
+  bluetooth_callback(connection_service_peek_pebble_app_connection());
211
+}
212
+
213
+static void window_unload(Window *window) {
214
+  text_layer_destroy(time_text_layer);
215
+  text_layer_destroy(date_text_layer);
216
+  layer_destroy(canvas);
217
+  gbitmap_destroy(image);
218
+  gbitmap_destroy(s_bt_icon_bitmap);
219
+  bitmap_layer_destroy(s_bt_icon_layer);
220
+  //gbitmap_destroy(s_battery_icon_bitmap);
221
+  text_layer_destroy(s_battery_layer);
222
+}
223
+
224
+static void init(void) {
225
+  redraw_counter = 0;
226
+
227
+
228
+  world_bitmap = gbitmap_create_with_resource(RESOURCE_ID_WORLD_MONO);
229
+
230
+  window = window_create();
231
+  window_set_window_handlers(window, (WindowHandlers) {
232
+    .load = window_load,
233
+    .unload = window_unload,
234
+  });
235
+  
236
+  const bool animated = true;
237
+  window_stack_push(window, animated);
238
+
239
+  s = malloc(STR_SIZE);
240
+  tick_timer_service_subscribe(MINUTE_UNIT, handle_minute_tick);
241
+  
242
+  // Subscribe to battery info
243
+  battery_state_service_subscribe(battery_callback);
244
+  
245
+  // Register for Bluetooth connection updates
246
+  connection_service_subscribe((ConnectionHandlers) {
247
+    .pebble_app_connection_handler = bluetooth_callback
248
+  });  
249
+}
250
+
251
+static void deinit(void) {
252
+  tick_timer_service_unsubscribe();
253
+  free(s);
254
+  window_destroy(window);
255
+  gbitmap_destroy(world_bitmap);
256
+
257
+}
258
+
259
+int main(void) {
260
+  init();
261
+
262
+  APP_LOG(APP_LOG_LEVEL_DEBUG, "Done initializing, pushed window: %p", window);
263
+
264
+  app_event_loop();
265
+  deinit();
266
+}
... ...
@@ -1,6 +1,6 @@
1
-Pebble.addEventListener("ready",
2
-  function(e) {
3
-    var time = Math.round((new Date()).getTime() / 1000);
4
-    Pebble.sendAppMessage({"0": time});
5
-  }
6
-);
1
+Pebble.addEventListener("ready",
2
+  function(e) {
3
+    var time = Math.round((new Date()).getTime() / 1000);
4
+    Pebble.sendAppMessage({"0": time});
5
+  }
6
+);
... ...
@@ -1,52 +1,52 @@
1
-#
2
-# This file is the default set of rules to compile a Pebble project.
3
-#
4
-# Feel free to customize this to your needs.
5
-#
6
-
7
-import os.path
8
-try:
9
-    from sh import CommandNotFound, jshint, cat, ErrorReturnCode_2
10
-    hint = jshint
11
-except (ImportError, CommandNotFound):
12
-    hint = None
13
-
14
-top = '.'
15
-out = 'build'
16
-
17
-
18
-def options(ctx):
19
-    ctx.load('pebble_sdk')
20
-
21
-
22
-def configure(ctx):
23
-    ctx.load('pebble_sdk')
24
-
25
-
26
-def build(ctx):
27
-    if False and hint is not None:
28
-        try:
29
-            hint([node.abspath() for node in ctx.path.ant_glob("src/**/*.js")], _tty_out=False) # no tty because there are none in the cloudpebble sandbox.
30
-        except ErrorReturnCode_2 as e:
31
-            ctx.fatal("\nJavaScript linting failed (you can disable this in Project Settings):\n" + e.stdout)
32
-
33
-    ctx.load('pebble_sdk')
34
-
35
-    build_worker = os.path.exists('worker_src')
36
-    binaries = []
37
-
38
-    for p in ctx.env.TARGET_PLATFORMS:
39
-        ctx.set_env(ctx.all_envs[p])
40
-        ctx.set_group(ctx.env.PLATFORM_NAME)
41
-        app_elf = '{}/pebble-app.elf'.format(ctx.env.BUILD_DIR)
42
-        ctx.pbl_program(source=ctx.path.ant_glob('src/c/**/*.c'), target=app_elf)
43
-
44
-        if build_worker:
45
-            worker_elf = '{}/pebble-worker.elf'.format(ctx.env.BUILD_DIR)
46
-            binaries.append({'platform': p, 'app_elf': app_elf, 'worker_elf': worker_elf})
47
-            ctx.pbl_worker(source=ctx.path.ant_glob('worker_src/c/**/*.c'), target=worker_elf)
48
-        else:
49
-            binaries.append({'platform': p, 'app_elf': app_elf})
50
-
51
-    ctx.set_group('bundle')
52
-    ctx.pbl_bundle(binaries=binaries, js=ctx.path.ant_glob(['src/pkjs/**/*.js', 'src/pkjs/**/*.json']), js_entry_file='src/pkjs/app.js')
1
+#
2
+# This file is the default set of rules to compile a Pebble project.
3
+#
4
+# Feel free to customize this to your needs.
5
+#
6
+
7
+import os.path
8
+try:
9
+    from sh import CommandNotFound, jshint, cat, ErrorReturnCode_2
10
+    hint = jshint
11
+except (ImportError, CommandNotFound):
12
+    hint = None
13
+
14
+top = '.'
15
+out = 'build'
16
+
17
+
18
+def options(ctx):
19
+    ctx.load('pebble_sdk')
20
+
21
+
22
+def configure(ctx):
23
+    ctx.load('pebble_sdk')
24
+
25
+
26
+def build(ctx):
27
+    if False and hint is not None:
28
+        try:
29
+            hint([node.abspath() for node in ctx.path.ant_glob("src/**/*.js")], _tty_out=False) # no tty because there are none in the cloudpebble sandbox.
30
+        except ErrorReturnCode_2 as e:
31
+            ctx.fatal("\nJavaScript linting failed (you can disable this in Project Settings):\n" + e.stdout)
32
+
33
+    ctx.load('pebble_sdk')
34
+
35
+    build_worker = os.path.exists('worker_src')
36
+    binaries = []
37
+
38
+    for p in ctx.env.TARGET_PLATFORMS:
39
+        ctx.set_env(ctx.all_envs[p])
40
+        ctx.set_group(ctx.env.PLATFORM_NAME)
41
+        app_elf = '{}/pebble-app.elf'.format(ctx.env.BUILD_DIR)
42
+        ctx.pbl_program(source=ctx.path.ant_glob('src/c/**/*.c'), target=app_elf)
43
+
44
+        if build_worker:
45
+            worker_elf = '{}/pebble-worker.elf'.format(ctx.env.BUILD_DIR)
46
+            binaries.append({'platform': p, 'app_elf': app_elf, 'worker_elf': worker_elf})
47
+            ctx.pbl_worker(source=ctx.path.ant_glob('worker_src/c/**/*.c'), target=worker_elf)
48
+        else:
49
+            binaries.append({'platform': p, 'app_elf': app_elf})
50
+
51
+    ctx.set_group('bundle')
52
+    ctx.pbl_bundle(binaries=binaries, js=ctx.path.ant_glob(['src/pkjs/**/*.js', 'src/pkjs/**/*.json']), js_entry_file='src/pkjs/app.js')