Browse code

Add basic code, that sends the first available HealthMinuteData record

Natasha Kerensikova authored on08/03/2016 23:38:24
Showing2 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,24 @@
1
+/*
2
+ * Copyright (c) 2016, Natacha Porté
3
+ *
4
+ * Permission to use, copy, modify, and distribute this software for any
5
+ * purpose with or without fee is hereby granted, provided that the above
6
+ * copyright notice and this permission notice appear in all copies.
7
+ *
8
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15
+ */
16
+
17
+Pebble.addEventListener("ready", function() {
18
+   console.log("Classic-Lite PebbleKit JS ready!");
19
+   Pebble.sendAppMessage({ "iGot": 0 });
20
+});
21
+
22
+Pebble.addEventListener("appmessage", function(e) {
23
+   console.log('Received message: ' + JSON.stringify(e.payload));
24
+});
0 25
new file mode 100644
... ...
@@ -0,0 +1,185 @@
1
+#include <inttypes.h>
2
+#include <pebble.h>
3
+
4
+#define MSG_KEY_LAST_SENT	110
5
+#define MSG_KEY_DATA_KEY	210
6
+#define MSG_KEY_DATA_LINE	220
7
+
8
+static Window *window;
9
+static TextLayer *text_layer;
10
+static char buffer[256];
11
+static HealthMinuteData minute_data[1440];
12
+static time_t minute_first;
13
+static char global_buffer[1024];
14
+
15
+static void
16
+window_load(Window *window) {
17
+	Layer *window_layer = window_get_root_layer(window);
18
+	GRect bounds = layer_get_bounds(window_layer);
19
+
20
+	text_layer = text_layer_create((GRect) { .origin = { 0, bounds.size.h / 3 }, .size = { bounds.size.w, bounds.size.h / 3 } });
21
+	text_layer_set_text(text_layer, buffer);
22
+	text_layer_set_text_alignment(text_layer, GTextAlignmentCenter);
23
+	layer_add_child(window_layer, text_layer_get_layer(text_layer));
24
+}
25
+
26
+static void
27
+window_unload(Window *window) {
28
+	text_layer_destroy(text_layer);
29
+}
30
+
31
+/* minute_data_image - fill a buffer with CSV data without line terminator */
32
+/*    format: RFC-3339 time, step count, yaw, pitch, vmc, ambient light */
33
+static uint16_t
34
+minute_data_image(char *buffer, size_t size,
35
+    HealthMinuteData *data, time_t key) {
36
+	struct tm *tm;
37
+	size_t ret;
38
+	if (!buffer || !data) return 0;
39
+
40
+	tm = gmtime(&key);
41
+	if (!tm) {
42
+		APP_LOG(APP_LOG_LEVEL_ERROR,
43
+		    "Unable to get UTC time for %" PRIi32, key);
44
+		return 0;
45
+	}
46
+
47
+	ret = strftime(buffer, size, "%FT%TZ", tm);
48
+	if (!ret) {
49
+		APP_LOG(APP_LOG_LEVEL_ERROR,
50
+		    "Unable to build RFC-3339 representation of %" PRIi32,
51
+		    key);
52
+		return 0;
53
+	}
54
+
55
+	if (ret >= size) {
56
+		APP_LOG(APP_LOG_LEVEL_ERROR,
57
+		    "Unexpected return value %zu of strftime on buffer %zu",
58
+		    ret, size);
59
+		return 0;
60
+	}
61
+
62
+	uint16_t yaw = data->orientation & 0xF;
63
+	uint16_t pitch = data->orientation >> 4;
64
+
65
+	int i = snprintf(buffer + ret, size - ret,
66
+	    ",%" PRIu8 ",%" PRIu16 ",%" PRIu16 ",%" PRIu16 ",%d",
67
+	    data->steps,
68
+	    yaw,
69
+	    pitch,
70
+	    data->vmc,
71
+	    (int)data->light);
72
+
73
+	if (i <= 0) {
74
+		APP_LOG(APP_LOG_LEVEL_ERROR, "minute_data_image: "
75
+		    "Unexpected return value %d of snprintf", i);
76
+		return 0;
77
+	}
78
+
79
+	return ret + i;
80
+}
81
+
82
+/* send_minute_data - use AppMessage to send the given minute data to phone */
83
+static void
84
+send_minute_data(HealthMinuteData *data, time_t key) {
85
+	int i;
86
+	int32_t int_key = key / 60;
87
+
88
+	if (key % 60 != 0) {
89
+		APP_LOG(APP_LOG_LEVEL_WARNING,
90
+		    "Discarding %" PRIi32 " second from time key %" PRIi32,
91
+		    key % 60, int_key);
92
+	}
93
+
94
+	uint16_t size = minute_data_image(global_buffer, sizeof global_buffer,
95
+	    data, key);
96
+	if (!size) return;
97
+
98
+	AppMessageResult msg_result;
99
+	DictionaryIterator *iter;
100
+	msg_result = app_message_outbox_begin(&iter);
101
+
102
+	if (msg_result) {
103
+		APP_LOG(APP_LOG_LEVEL_ERROR,
104
+		    "send_minute_data: app_message_outbox_begin returned %d",
105
+		    (int)msg_result);
106
+		return;
107
+	}
108
+
109
+	DictionaryResult dict_result;
110
+	dict_result = dict_write_int(iter, MSG_KEY_DATA_KEY,
111
+	    &int_key, sizeof int_key, true);
112
+	if (dict_result != DICT_OK) {
113
+		APP_LOG(APP_LOG_LEVEL_ERROR,
114
+		    "send_minute_data: [%d] unable to add data key %" PRIi32,
115
+		    (int)dict_result, int_key);
116
+	}
117
+
118
+	dict_result = dict_write_cstring(iter,
119
+	    MSG_KEY_DATA_LINE, global_buffer);
120
+	if (dict_result != DICT_OK) {
121
+		APP_LOG(APP_LOG_LEVEL_ERROR,
122
+		    "send_minute_data: [%d] unable to add data line \"%s\"",
123
+		    (int)dict_result, global_buffer);
124
+	}
125
+
126
+	msg_result = app_message_outbox_send();
127
+	if (msg_result) {
128
+		APP_LOG(APP_LOG_LEVEL_ERROR,
129
+		    "send_minute_data: app_message_outbox_send returned %d",
130
+		    (int)msg_result);
131
+	}
132
+}
133
+
134
+static void
135
+inbox_received_handler(DictionaryIterator *iterator, void *context) {
136
+	(void)iterator;
137
+	(void)context;
138
+	APP_LOG(APP_LOG_LEVEL_INFO, "inbox_received_handler called");
139
+
140
+	if (minute_data->is_invalid) return;
141
+	send_minute_data(minute_data, minute_first);
142
+	APP_LOG(APP_LOG_LEVEL_INFO, "message sent");
143
+}
144
+
145
+static time_t
146
+get_first_health_minute(void) {
147
+	time_t start = 0, end = time(0);
148
+	uint32_t ret;
149
+
150
+	ret = health_service_get_minute_history(minute_data, 1, &start, &end);
151
+	return ret ? start : 0;
152
+}
153
+
154
+static void
155
+init_text(void) {
156
+	time_t t = get_first_health_minute();
157
+	struct tm *tm = localtime(&t);
158
+	strftime(buffer, sizeof buffer, "First health minute: %FT%T%z", tm);
159
+	minute_first = t;
160
+}
161
+
162
+static void
163
+init(void) {
164
+	app_message_register_inbox_received(inbox_received_handler);
165
+	app_message_open(256, 2048);
166
+
167
+	init_text();
168
+	window = window_create();
169
+	window_set_window_handlers(window, (WindowHandlers) {
170
+	    .load = window_load,
171
+	    .unload = window_unload,
172
+	});
173
+	window_stack_push(window, true);
174
+}
175
+
176
+static void deinit(void) {
177
+	window_destroy(window);
178
+}
179
+
180
+int
181
+main(void) {
182
+	init();
183
+	app_event_loop();
184
+	deinit();
185
+}