static void inbox_received_callback(DictionaryIterator *iterator, void *context) { // Store incoming information static char icon_buffer[8]; static char temperature_buffer[8]; static int temperature; // Read tuples for data Tuple *weather_units_tuple = dict_find(iterator, MESSAGE_KEY_UNITS); Tuple *weather_on_tuple = dict_find(iterator, MESSAGE_KEY_WEATHER_ON); Tuple *weather_safemode_tuple = dict_find(iterator, MESSAGE_KEY_WEATHER_SAFEMODE); Tuple *temp_tuple = dict_find(iterator, MESSAGE_KEY_TEMPERATURE); Tuple *icon_tuple = dict_find(iterator, MESSAGE_KEY_ICON); Tuple *background_color_tuple = dict_find(iterator, MESSAGE_KEY_BACKGROUND_COLOR); Tuple *background_on_tuple = dict_find(iterator, MESSAGE_KEY_BACKGROUND_ON); // If we get weather option if ( weather_on_tuple ) { // Set weather flag weather_on_conf = (bool)weather_on_tuple->value->int16; persist_write_bool(MESSAGE_KEY_WEATHER_ON, weather_on_conf); } if ( weather_safemode_tuple ) { weather_safemode_conf = (bool)weather_safemode_tuple->value->int16; persist_write_bool(MESSAGE_KEY_WEATHER_SAFEMODE, weather_safemode_conf); } if ( weather_units_tuple ) { weather_units_conf = (bool)weather_units_tuple->value->int16; persist_write_bool(MESSAGE_KEY_UNITS, weather_units_conf); } // If all data is available, use it if ( temp_tuple && icon_tuple ) { // Assemble strings for temp and icon temperature = (float)temp_tuple->value->int32; if ( weather_units_conf ) { snprintf(temperature_buffer, sizeof(temperature_buffer), "%d F", temperature); } else { snprintf(temperature_buffer, sizeof(temperature_buffer), "%d C", temperature); } snprintf(icon_buffer, sizeof(icon_buffer), "%s", icon_tuple->value->cstring); // Set temp and icon to text layers text_layer_set_text(s_weather_layer, icon_buffer); text_layer_set_text(s_weathertext_layer, temperature_buffer); } // If weather disabled, clear weather layers if ( !weather_on_conf ) { text_layer_set_text(s_weather_layer, ""); text_layer_set_text(s_weathertext_layer, ""); } // If background color and enabled if ( background_color_tuple && background_on_tuple ) { // Set background on/off background_on_conf = (bool)background_on_tuple->value->int16; persist_write_bool(MESSAGE_KEY_BACKGROUND_ON, background_on_conf); // Set background color if enabled, otherwise we load the default one - red background_color = background_on_conf ? (int)background_color_tuple->value->int32 : 0xFF0000; persist_write_int(MESSAGE_KEY_BACKGROUND_COLOR, background_color); // Redraw if ( s_canvas_layer ) { layer_mark_dirty(s_canvas_layer); } } APP_LOG(APP_LOG_LEVEL_DEBUG, "weather_units_conf %d", weather_units_conf); APP_LOG(APP_LOG_LEVEL_DEBUG, "weather_on_conf %d", weather_on_conf); APP_LOG(APP_LOG_LEVEL_DEBUG, "background_on_conf %d", background_on_conf); APP_LOG(APP_LOG_LEVEL_DEBUG, "background_color %d", background_color); }
DEBUG_CODE(void print_value(char* value, uint16_t value_length) { \ char* v = calloc(value_length + 1, sizeof(char)); \ snprintf(v, value_length + 1, "%s", value); \ APP_LOG(APP_LOG_LEVEL_INFO, " Found value [%d] %s ", value_length, v); \ free(v); \ });
/* * Handle dropped messages from the AppMessage API. */ static void inbox_dropped_cb(AppMessageResult reason, void *context) { APP_LOG(APP_LOG_LEVEL_ERROR, "Message dropped."); }
static void select_click_handler(ClickRecognizerRef recognizer, void *context) { APP_LOG(APP_LOG_LEVEL_DEBUG, "SELECT" ); send_message(); data.queried = true; }
static void down_click_handler(ClickRecognizerRef recognizer, void *context) { APP_LOG(APP_LOG_LEVEL_DEBUG, "DOWN" ); }
static void in_dropped_handler(AppMessageResult reason, void *context) { APP_LOG(APP_LOG_LEVEL_DEBUG, "Incoming AppMessage from Pebble dropped, %d", reason); }
static void vibrate_hourly_pattern() { // values uint32_t VIBRATE_SEGMENTS[48]; u_short MAX_SEGMENTS = 48; // get hour from local time time_t temp = time(NULL); struct tm *tick_time = localtime(&temp); // create pattern for vibration int hours = tick_time->tm_hour; // adjust for non-24-hour time if(clock_is_24h_style() != true && hours > 12) { hours = hours - 12; } // need pattern count int pattern_count = hours * 2; int long_pulses = 0; // do math to abbreviate pulses if(ABBREVIATE_PULSES && hours > 5) { long_pulses = hours / 5; pattern_count = pattern_count - (long_pulses * 2 * 5) + 1; // eats 10 "spaces" or } // chop off remainder (last space is always silent/pause otherwise) pattern_count = pattern_count - 1; int vibrate_segment_count = pattern_count; // store value // fill array with pattern for(int i = 0; i < MAX_SEGMENTS; i += 2) { if(pattern_count > 0) { if(long_pulses > 0) { long_pulses--; VIBRATE_SEGMENTS[i] = VIBRATE_LONG_PULSE_MS; // longer pulse for abbreviation } else { VIBRATE_SEGMENTS[i] = VIBRATE_PULSE_MS; // pulse each hour } if(MAX_SEGMENTS > (i + 1)) { VIBRATE_SEGMENTS[i + 1] = VIBRATE_PAUSE_MS; // followed by a pause } pattern_count-=2; // subtract two because two pattern blocks } else { VIBRATE_SEGMENTS[i] = 0; if(MAX_SEGMENTS > (i + 1)) { VIBRATE_SEGMENTS[i + 1] = 0; } } } // enqueue APP_LOG(APP_LOG_LEVEL_DEBUG, "Enqueueing %d segments for hours %d", vibrate_segment_count, hours); // enqueue pattern VibePattern pat = { .durations = VIBRATE_SEGMENTS, .num_segments = vibrate_segment_count, }; vibes_enqueue_custom_pattern(pat); }
static void action_menu_callback(ActionMenu *action_menu, const ActionMenuItem *action, void *context) { ValveCmdCode i = (ValveCmdCode)action_menu_item_get_action_data(action); APP_LOG(APP_LOG_LEVEL_INFO, "Action menu triggered: %d", i); sendCmdRequest(selectedValve->guid, i); }
static void window_load(Window *window) { Layer *window_layer = window_get_root_layer(window); battery_layer = layer_create(GRect(0, 0, 144, 30)); outline_font = fonts_load_custom_font(resource_get_handle(RESOURCE_ID_LECO_16)); bluetooth_connection_service_subscribe(bluetooth_handler); upper_text_layer = text_layer_create(GRect(0, 36, 144, 44)); text_layer_set_font(upper_text_layer, fonts_get_system_font(FONT_KEY_LECO_42_NUMBERS)); text_layer_set_text_alignment(upper_text_layer, GTextAlignmentCenter); text_layer_set_background_color(upper_text_layer, GColorClear); outline_layer = text_layer_create(GRect(0, 36, 144, 168)); text_layer_set_font(outline_layer, outline_font); text_layer_set_text_alignment(outline_layer, GTextAlignmentCenter); text_layer_set_text_color(outline_layer, GColorWhite); text_layer_set_background_color(outline_layer, GColorClear); lower_text_layer = text_layer_create(GRect(0, 84, 144, 100)); text_layer_set_font(lower_text_layer, fonts_get_system_font(FONT_KEY_LECO_28_LIGHT_NUMBERS)); text_layer_set_text_alignment(lower_text_layer, GTextAlignmentCenter); text_layer_set_background_color(lower_text_layer, GColorClear); text_layer_set_text(lower_text_layer, ""); weekday_text = text_layer_create(GRect(0,144,144,25)); text_layer_set_text_alignment(weekday_text, GTextAlignmentCenter); text_layer_set_background_color(weekday_text, GColorClear); text_layer_set_text_color(weekday_text, GColorWhite); text_layer_set_font(weekday_text, outline_font); battery_text = text_layer_create(GRect(0,0,144,25)); text_layer_set_text_alignment(battery_text, GTextAlignmentCenter); text_layer_set_background_color(battery_text, GColorClear); text_layer_set_text_color(battery_text, GColorWhite); text_layer_set_font(battery_text, fonts_get_system_font(FONT_KEY_GOTHIC_18_BOLD)); layer_add_child(window_layer, battery_layer); layer_add_child(window_layer, text_layer_get_layer(lower_text_layer)); layer_add_child(window_layer, text_layer_get_layer(upper_text_layer)); layer_add_child(window_layer, text_layer_get_layer(outline_layer)); layer_add_child(battery_layer, text_layer_get_layer(battery_text)); layer_add_child(window_layer, text_layer_get_layer(weekday_text)); if (persist_read_int(KEY_TOP_COLOR)) { int top_color = persist_read_int(KEY_TOP_COLOR); set_background_and_text_color(top_color); } if (persist_read_int(KEY_BOTTOM_COLOR)) { int bottom_color = persist_read_int(KEY_BOTTOM_COLOR); set_layer1_color_and_text(bottom_color); } if (persist_read_bool(KEY_TWENTY_FOUR_HOUR_FORMAT)) { twenty_four_hour_format = persist_read_bool(KEY_TWENTY_FOUR_HOUR_FORMAT); } if (persist_read_int(KEY_TOP_TEXT_COLOR)) { int top_text_color = persist_read_int(KEY_TOP_TEXT_COLOR); set_top_text_color(top_text_color); } if(persist_read_int(KEY_BOTTOM_TEXT_COLOR)) { int bottom_text_color = persist_read_int(KEY_BOTTOM_TEXT_COLOR); set_bottom_text_color(bottom_text_color); } if(persist_exists(KEY_BLUETOOTH_VIBRATION)){ bluetooth_vibration = persist_read_int(KEY_BLUETOOTH_VIBRATION); APP_LOG(APP_LOG_LEVEL_INFO,"Bluetooth read"); } if(persist_exists(KEY_SHOW_BATTERY)){ show_battery = persist_read_int(KEY_SHOW_BATTERY); } if(persist_exists(KEY_SHOW_WEEKDAY)){ show_weekday = persist_read_int(KEY_SHOW_WEEKDAY); APP_LOG(APP_LOG_LEVEL_INFO,"Weekday read"); } if(persist_exists(KEY_DATE_FORMAT)){ change_date_format = persist_read_int(KEY_DATE_FORMAT); APP_LOG(APP_LOG_LEVEL_INFO,"Date format read"); } if(persist_read_int(KEY_WEEKDAY_COLOR)) { int weekday_color = persist_read_int(KEY_WEEKDAY_COLOR); set_weekday_color(weekday_color); } if(persist_read_int(KEY_BATTERY_COLOR)) { int battery_color = persist_read_int(KEY_BATTERY_COLOR); set_battery_color(battery_color); } if(persist_read_bool(KEY_HOUR_VIBRATE)) { hour_vibrate = persist_read_bool(KEY_HOUR_VIBRATE); } update_time(); update_layers(); battery_handler(battery_state_service_peek()); }
static void generate_world() { srand(time(NULL)); #ifdef BENCHMARK uint16_t start = time_ms(NULL, NULL); #endif // Bottom level grass for(int y = 0; y < GRID_HEIGHT; y++) { for(int x = 0; x < GRID_WIDTH; x++) { block_set_color(s_block_array[vec2i(Vec3(x, y, 0))], COLOR_GRASS); } } // Seed sand for(int y = 0; y < GRID_HEIGHT; y++) { for(int x = 0; x < GRID_WIDTH; x++) { if(rand() % 100 > SAND_SEED_BIAS) { block_set_color(s_block_array[vec2i(Vec3(x, y, 0))], COLOR_SAND); } } } // Clump sand for(int y = 0; y < GRID_HEIGHT; y++) { for(int x = 0; x < GRID_WIDTH; x++) { if(rand() % 100 > SAND_CLUMP_BIAS && is_near_color(GPoint(x, y), 0, COLOR_SAND)) { block_set_color(s_block_array[vec2i(Vec3(x, y, 0))], COLOR_SAND); } } } for(int y = 0; y < GRID_HEIGHT; y++) { for(int x = 0; x < GRID_WIDTH; x++) { if(near_this_many_of_color(GPoint(x, y), 0, COLOR_SAND, SAND_NEIGHBOURS)) { block_set_color(s_block_array[vec2i(Vec3(x, y, 0))], COLOR_SAND); } } } // Water in sand areas for(int y = 0; y < GRID_HEIGHT; y++) { for(int x = 0; x < GRID_WIDTH; x++) { if(near_this_many_of_color(GPoint(x, y), 0, COLOR_SAND, WATER_NEIGHBOURS)) { block_set_color(s_block_array[vec2i(Vec3(x, y, 0))], COLOR_WATER); } } } // Clump water for(int y = 0; y < GRID_HEIGHT; y++) { for(int x = 0; x < GRID_WIDTH; x++) { if(rand() % 100 > WATER_CLUMP_BIAS && is_near_color(GPoint(x, y), 0, COLOR_WATER)) { block_set_color(s_block_array[vec2i(Vec3(x, y, 0))], COLOR_WATER); } } } // Castle walls int x = 2; int y = 6; for(y = 6; y < 10; y++) { for(int z = 0; z < 6; z++) { block_set_color(s_block_array[vec2i(Vec3(x, y, z))], COLOR_STONE); } } y = 11; for(x = 2; x < 6; x++) { for(int z = 0; z < 6; z++) { block_set_color(s_block_array[vec2i(Vec3(x, y, z))], COLOR_STONE); } } y = 6; for(x = 2; x < 6; x++) { for(int z = 0; z < 6; z++) { block_set_color(s_block_array[vec2i(Vec3(x, y, z))], COLOR_STONE); } } x = 6; for(y = 6; y < 10; y++) { for(int z = 0; z < 6; z++) { block_set_color(s_block_array[vec2i(Vec3(x, y, z))], COLOR_STONE); } } int z = 6; for(y = 6; y < 10; y++) { for(x = 2; x < 7; x++) { block_set_color(s_block_array[vec2i(Vec3(x, y, z))], COLOR_STONE); } } #ifdef BENCHMARK uint16_t finish = time_ms(NULL, NULL); APP_LOG(APP_LOG_LEVEL_INFO, "Generation time: %d ms", (int)finish - start); #endif }
static void bt_client_btcm_cb(VMUINT evt, void * param, void * user_data) { APP_LOG("[BTC]bt_client_btcm_cb, evt = %d, client_status = %d", evt, g_clientContext.client_status); switch (evt) { case VM_SRV_BT_CM_EVENT_ACTIVATE: { // waiting for power on to process if (g_clientContext.client_status == BT_CLIENT_POWERING_ON) { VMINT ret = bt_client_init_spp(); if(ret<0) { *(g_clientContext.waiting_result_p) = false; g_clientContext.waiting_result_p = NULL; if(bt_client_end_spp()) { g_clientContext.ptr->post_signal(); } } else { *(g_clientContext.waiting_result_p) = true; g_clientContext.waiting_result_p = NULL; g_clientContext.ptr->post_signal(); } } else if (g_clientContext.client_status == BT_CLIENT_ENDING) { VMINT ret = vm_btcm_switch_off(); if(VM_SRV_BT_CM_RESULT_SUCCESS == ret) { g_clientContext.client_status = BT_CLIENT_POWERING_OFF; } else { if(g_clientContext.btcm_hdl >= 0) { vm_btcm_exit(g_clientContext.btcm_hdl); g_clientContext.btcm_hdl = -1; } g_clientContext.client_status = BT_CLIENT_IDLE; //LTask.post_signal(); g_clientContext.ptr->post_signal(); } } break; } case VM_SRV_BT_CM_EVENT_DEACTIVATE: { if (g_clientContext.client_status == BT_CLIENT_BEGINING) { VMINT ret = vm_btcm_switch_on(); if(VM_SRV_BT_CM_RESULT_SUCCESS == ret) { //wait for callback to process g_clientContext.client_status = BT_CLIENT_POWERING_ON; } else { *(g_clientContext.waiting_result_p) = false; g_clientContext.waiting_result_p = NULL; if(bt_client_end_spp()) { //LTask.post_signal(); g_clientContext.ptr->post_signal(); } } } else if(g_clientContext.client_status == BT_CLIENT_POWERING_OFF) { if(g_clientContext.btcm_hdl >= 0) { vm_btcm_exit(g_clientContext.btcm_hdl); g_clientContext.btcm_hdl = -1; } g_clientContext.client_status = BT_CLIENT_IDLE; //LTask.post_signal(); g_clientContext.ptr->post_signal(); } break; } case VM_SRV_BT_CM_EVENT_INQUIRY_IND: { vm_srv_bt_cm_inquiry_indication_struct *ind = (vm_srv_bt_cm_inquiry_indication_struct *)param; if (ind->discovered_dev_num > 0) { g_clientContext.scan_number = ind->discovered_dev_num; } APP_LOG("[BTC]bt_client_btcm_cb, scan_number = %d, discovered_dev_num = %d", g_clientContext.scan_number, ind->discovered_dev_num); vm_srv_bt_cm_dev_struct dev_info ; *(g_clientContext.scan_number_p) = g_clientContext.scan_number; for (int i = 0; i < ind->discovered_dev_num; i++) { if( VM_BT_CM_ERR_SUCCESS == vm_btcm_get_dev_info_by_index(i, VM_SRV_BT_CM_DISCOVERED_DEV, &dev_info) ) { LBTAddress addr; addr.nap[0] = (dev_info.bd_addr.nap & 0x00ff); addr.nap[1] = (dev_info.bd_addr.nap & 0xff00) >> 8; addr.uap = dev_info.bd_addr.uap; addr.lap[0] = (dev_info.bd_addr.lap & 0x0000ff); addr.lap[1] = (dev_info.bd_addr.lap & 0x00ff00) >> 8; addr.lap[2] = (dev_info.bd_addr.lap & 0xff0000) >> 16; APP_LOG("[BTC]VM_SRV_BT_CM_EVENT_INQUIRY_IND, name: %s", dev_info.name); APP_LOG("[BTC]VM_SRV_BT_CM_EVENT_INQUIRY_IND, address: %02x:%02x:%02x:%02x:%02x:%02x:", addr.nap[1], addr.nap[0], addr.uap, addr.lap[2], addr.lap[1], addr.lap[0]); } } break; } case VM_SRV_BT_CM_EVENT_INQUIRY_COMPLETE: { vm_srv_bt_cm_inquiry_complete_struct *cmpl = (vm_srv_bt_cm_inquiry_complete_struct *)param; *(g_clientContext.scan_number_p) = g_clientContext.scan_number; g_clientContext.ptr->post_signal(); break; } case VM_SRV_BT_CM_EVENT_PAIR_IND: { vm_srv_bt_cm_pair_ind_struct *event = (vm_srv_bt_cm_pair_ind_struct *)param; vm_bt_cm_send_passkey(&event->dev_addr, (VMUINT8*)LBTClient._pincode_buffer, VM_TRUE); break; } default: { break; } }
float calcSun(int year, int month, int day, float latitude, float longitude, int sunset, float zenith) { int N1 = my_floor(275 * month / 9); int N2 = my_floor((month + 9) / 12); int N3 = (1 + my_floor((year - 4 * my_floor(year / 4) + 2) / 3)); int N = N1 - (N2 * N3) + day - 30; float lngHour = longitude / 15; float t; if (!sunset) { //if rising time is desired: t = N + ((6 - lngHour) / 24); } else { //if setting time is desired: t = N + ((18 - lngHour) / 24); } float M = (0.9856 * t) - 3.289; //calculate the Sun's true longitude //L = M + (1.916 * sin(M)) + (0.020 * sin(2 * M)) + 282.634 float L = M + (1.916 * my_sin((M_PI/180.0f) * M)) + (0.020 * my_sin((M_PI/180.0f) * 2 * M)) + 282.634; if (L<0) L+=360.0f; if (L>360) L-=360.0f; //5a. calculate the Sun's right ascension //RA = atan(0.91764 * tan(L)) float RA = (180.0f/M_PI) * my_atan(0.91764 * my_tan((M_PI/180.0f) * L)); if (RA<0) RA+=360; if (RA>360) RA-=360; //5b. right ascension value needs to be in the same quadrant as L float Lquadrant = (my_floor( L/90)) * 90; float RAquadrant = (my_floor(RA/90)) * 90; RA = RA + (Lquadrant - RAquadrant); //5c. right ascension value needs to be converted into hours RA = RA / 15; //6. calculate the Sun's declination float sinDec = 0.39782 * my_sin((M_PI/180.0f) * L); float cosDec = my_cos(my_asin(sinDec)); //7a. calculate the Sun's local hour angle //cosH = (cos(zenith) - (sinDec * sin(latitude))) / (cosDec * cos(latitude)) float cosH = (my_cos((M_PI/180.0f) * zenith) - (sinDec * my_sin((M_PI/180.0f) * latitude))) / (cosDec * my_cos((M_PI/180.0f) * latitude)); if (cosH > 1) { return 0; } else if (cosH < -1) { return 0; } //7b. finish calculating H and convert into hours float H; if (!sunset) { //if rising time is desired: H = 360 - (180.0f/M_PI) * my_acos(cosH); } else { //if setting time is desired: H = (180.0f/M_PI) * my_acos(cosH); } H = H / 15; //8. calculate local mean time of rising/setting float T = H + RA - (0.06571 * t) - 6.622; //9. adjust back to UTC float UT = T - lngHour; if (UT<0) {UT+=24;} if (UT>24) {UT-=24;} time_t now = time(NULL); struct tm *tick_time = localtime(&now); struct tm *gm_time = gmtime(&now); int timezoneoffset = 60 * (60 * (24 * (tick_time->tm_wday - gm_time->tm_wday) + tick_time->tm_hour - gm_time->tm_hour) + tick_time->tm_min - gm_time->tm_min); // Correct for transitions at the end of the week. int SECONDS_IN_WEEK=604800; if (timezoneoffset > SECONDS_IN_WEEK/2) timezoneoffset -= SECONDS_IN_WEEK; if (timezoneoffset < -SECONDS_IN_WEEK/2) timezoneoffset += SECONDS_IN_WEEK; timezoneoffset /= 3600; APP_LOG(APP_LOG_LEVEL_DEBUG, "timezone offset %d", timezoneoffset); APP_LOG(APP_LOG_LEVEL_DEBUG, "other timezone offset %d", (tick_time-gm_time)); // return UT+(tick_time-gm_time); return UT; }
// Called when PebbleKitJS does not acknowledge receipt of a message static void out_failed_handler(DictionaryIterator *failed, AppMessageResult reason, void *context) { APP_LOG(APP_LOG_LEVEL_DEBUG, "**WATCH**: PebbleKit does not acknowledge receipt of message. Error: %d",reason); }
// Called when an incoming message from PebbleKitJS is dropped static void in_dropped_handler(AppMessageResult reason, void *context) { APP_LOG(APP_LOG_LEVEL_DEBUG, "**WATCH**: An incoming message from PebbleKitJS is dropped. Error: %d",reason); }
static void out_failed_handler(DictionaryIterator *failed, AppMessageResult reason, void *context) { APP_LOG(APP_LOG_LEVEL_DEBUG, "out_failed_handler: App Error Message : %d",reason); }
uint32_t get_weather_resource(int32_t cond) { switch (cond) { case 200: case 201: case 210: case 211: case 230: case 231: return RESOURCE_ID_COND_LIGHT_STORM; break; case 202: case 212: case 221: case 232: case 781: case 900: case 901: case 902: case 960: case 961: case 962: return RESOURCE_ID_COND_HEAVY_STORM; break; case 300: case 301: case 302: case 310: case 311: case 313: case 321: case 500: case 501: case 520: case 521: return RESOURCE_ID_COND_LIGHT_RAIN; break; case 312: case 314: case 502: case 503: case 504: case 522: case 531: return RESOURCE_ID_COND_HEAVY_RAIN; break; case 600: case 601: case 615: case 616: case 620: case 621: return RESOURCE_ID_COND_LIGHT_SNOW; break; case 602: case 622: return RESOURCE_ID_COND_HEAVY_SNOW; break; case 511: case 611: case 612: case 903: case 906: return RESOURCE_ID_COND_HAIL; break; case 701: case 711: case 721: case 731: case 741: case 751: case 761: return RESOURCE_ID_COND_FOG; break; case 771: case 905: case 952: case 953: case 954: case 955: case 956: case 957: case 958: case 959: return RESOURCE_ID_COND_WINDY; break; case 950: case 951: case 800: case 904: // check night/day return RESOURCE_ID_COND_CLEAR_DAY; break; case 801: case 802: case 803: return RESOURCE_ID_COND_LIGHT_CLOUD; break; case 804: return RESOURCE_ID_COND_HEAVY_CLOUD; break; default: APP_LOG(APP_LOG_LEVEL_DEBUG, "Weather Condition ID not assigned: %li", cond); return RESOURCE_ID_COND_NA; break; } }
static void outbox_sent_callback(DictionaryIterator *iterator, void *context) { APP_LOG(APP_LOG_LEVEL_INFO, "Outbox send success!"); }
void MiscModule_Impl::quitTheApplication() { ::PostQuitMessage(0); APP_LOG(LOG_INFO, _T("quitTheApplication...")); }
static void out_failed_handler(DictionaryIterator *failed, AppMessageResult reason, void *context) { APP_LOG(APP_LOG_LEVEL_DEBUG, "Failed to send AppMessage to Pebble"); }
// // Handle incoming messages from phone // void inbox_received_callback(DictionaryIterator *iterator, void *context) { // Store incoming information static char *layDecode[] = {"SPN", "SCB", "SMD",NULL,NULL,NULL,NULL,NULL,NULL,NULL,"PPN","PCB","PMD","PPN","PCB","PMD"}; static int tackLog[7] = {0,0,0,0,0,0,0}; static bool warnedLineBurn = false; static int currentState = -1; static int thisTack = 0, oldTack = 0; int angle; bool earlyWarnDone = false; bool weAreRacing = false; bool doScreenTransition; #ifdef PBL_COLOR bool redAWA, highVMG; #endif int j, tmp, ii; bool foundKey, negNum; #ifdef CONFIG_SUPPORT bool foundAKey = false; // Did we find any data keys in the message? #endif int startingScreen; // To remember which screen we were at when we arrived here so we don't loop forever looking for a screen with data on it int a; float b; static int flashFlag = 0; char *sa, *sb; bool fieldUpdated[6]; bool canDoVMG; int twd, bs, hdg; #ifdef CONFIG_SUPPORT bool receivedConfig = false; #endif if (doubleClick || messageClick) return; // Get out of here if we are displaying a message - note - we may miss a tack because of this, but unlikely!! startingScreen = currentScreen; #ifdef PBL_COLOR text_layer_set_background_color(flash, flashFlag == 0 ? GColorGreen : GColorClear); #else layer_set_bounds(inverter_layer_get_layer(flash), flashFlag == 0 ? GRectZero : GRect(0,0,7,7)); #endif flashFlag = 1 - flashFlag; if (holdThisScreen > 0) holdThisScreen--; weAreRacing = false; // Assume we're not racing unless we receive a mark name do { for (ii = 0; ii < screens[currentScreen].num_fields; ii++) { fieldUpdated[ii] = false; } canDoVMG = false; #ifdef PBL_COLOR redAWA = false; highVMG = false; #endif doScreenTransition = false; weAreRacing = false; // Read first item Tuple *t = dict_read_first(iterator); j = 0; while(t != NULL) { foundKey = true; char *bj; bj = buffer[j]; // Which key was received? //APP_LOG(APP_LOG_LEVEL_INFO, "Key %d Value %d", (int)t->key, (int)t->value->int32); switch(t->key) { case KEY_LINE_BURN: case KEY_LAY_TIME: case KEY_LINE_TIME: case KEY_SECS_TO_START: case KEY_LAY_BURN: case KEY_TIME_TO_MARK: negNum = false; tmp = abs((int)t->value->int32) ; negNum = ((int)t->value->int32 < 0); if (tmp >= 100) { if ((tmp < 6000 && isBigField(t->key)) || tmp < 600) // We have room for mins & seconds & always when mins < 10 { snprintf(bj, sizeof(buffer[0]),"%d:%02d", tmp / 60, tmp % 60); } else if (tmp < 3600) { snprintf(bj, sizeof(buffer[0]),"%dm", tmp / 60 + ((tmp % 60) >= 30 ? 1:0)); } else { snprintf(bj, sizeof(buffer[0]),"%dh", tmp / 3600 + ((tmp % 3600) >= 1800 ? 1:0)); } } else // (tmp < 100) { snprintf(bj, sizeof(buffer[0]),"%ds", tmp); } break; case KEY_LAST_TACK: oldTack = thisTack; // Remember the tack from the last message thisTack = (int)t->value->int32; negNum = false; // This definitely shouldn't happen! if (currentState != 1) bj[0] = '\0'; else snprintf(bj, sizeof(buffer[0]),"%d", abs((int)t->value->int32)); break; case KEY_TARGET_TACK: negNum = false; snprintf(bj, sizeof(buffer[0]),"%d", abs((int)t->value->int32)); case KEY_TWD: if (t->key == KEY_TWD) { canDoVMG = true; twd = t->value->int32; } case KEY_LAY_DIST: case KEY_LINE_DIST: case KEY_TARGET_ANGLE: case KEY_MARK_BEARING: case KEY_HEADING_COG: case KEY_HEADING: if (t->key == KEY_HEADING) hdg = t->value->int32; case KEY_AWS: case KEY_TWS: case KEY_DEPTH: case KEY_HEEL: case KEY_CURRENT_DIR: negNum = ((int)t->value->int32 < 0); snprintf(bj, sizeof(buffer[0]),"%d", abs((int)t->value->int32)); break; case KEY_TWA: case KEY_AWA: negNum = false; angle = (int)t->value->int32; #ifdef PBL_COLOR redAWA = angle > 180; if (colourAWA) { snprintf(bj, sizeof(buffer[0]),"%d", angle <= 180 ? angle : abs(angle - 360)); } else { snprintf(bj, sizeof(buffer[0]),"%d%s", angle <= 180 ? angle : abs(angle - 360), angle <= 180 ? "S":"P"); } #else snprintf(bj, sizeof(buffer[0]),"%d%s", angle <= 180 ? angle : abs(angle - 360), angle <= 180 ? "S":"P"); #endif break; case KEY_BOAT_SOG: case KEY_BOAT_SPEED: if (t->key == KEY_BOAT_SPEED) bs = t->value->int32; case KEY_TARGET_SPEED: case KEY_CURRENT_SPEED: snprintf(bj, sizeof(buffer[0]),"%d.%d", abs((int)t->value->int32)/10, abs((int)t->value->int32) % 10); negNum = ((int)t->value->int32 < 0); break; case KEY_LINE_ANGLE: // If this is negative, we will be over the line early - red burn time a = t->value->int32; #ifdef PBL_COLOR highVMG = (a < 0); #endif a = abs(a); negNum = false; snprintf(bj, sizeof(buffer[0]),"%d", a); break; case KEY_MARK_DIST: case KEY_MARK_LAY_DIST: negNum = false; if (currentState != 1 && t->key == KEY_MARK_LAY_DIST) bj[0] = '\000'; else { a = (int)t->value->int32; negNum = (a < 0); a = abs(a); b = a / 18.52; bool bf = isBigField((int)t->key); if (a < 1000) // Less than 1000m - just show m snprintf(bj, sizeof(buffer[0]), "%d", a); else if (b < 1000 || bf) // less than 100nm or it's a big field - show nm.n { int d1, d2, d3; d1 = (int)b/100; d2 = (((int)b % 100)/10); d3 = ((((int)b % 10) > 4) ? 1 : 0); if (d3 == 1) d2 += 1; if (d2 == 10) { d1 += 1; d2 = 0; } snprintf(bj, sizeof(buffer[0]), "%d.%d", d1, d2); } else { snprintf(bj, sizeof(buffer[0]), "%d", (int)b/10); } } break; case KEY_LAY_SEL: //APP_LOG(APP_LOG_LEVEL_INFO, "Key %d Value %d", (int)t->key, (int)t->value->int32); negNum = false; snprintf(bj, sizeof(buffer[0]),"%s", layDecode[(int)t->value->int32]); break; /* These are the turn style values - Rnn & Lnn */ case KEY_MARK_TURN: case KEY_TACK_HEADER: negNum = false; if (currentState != 1 && t-> key == KEY_TACK_HEADER) bj[0] = '\000'; else { // if (t->value->int32 >= 0) snprintf(bj, sizeof(buffer[0]), "%c%02d", t->value->int32 >= 0 ? 'R' : 'L', abs((int)t->value->int32)); // else // snprintf(buffer[j], sizeof(buffer[j]), "L%02d", -(int)(t->value->int32)); } break; case KEY_CURRENT_MARK: weAreRacing = true; //This data only arrives once the start is over, we must be racing negNum = false; sa = t->value->cstring; sb = tmpbuf; // APP_LOG(APP_LOG_LEVEL_ERROR, "Mark->%s", sa); while (*sa != '\000') { *sb = *sa; // Copy the current char if (*sb == ':' && *(sa+1) == ':') { // Found :: don't increment b so we ignore the extra : sa++; continue; } else if (*sb == ':' && *(sa+1) == '\000') { // End of string coming up & last char was : - don't increment b - it will be zapped sa++; continue; } else { sa++; sb++; } } *sb = '\000'; snprintf(bj, sizeof(buffer[0]), "%s", tmpbuf); break; case KEY_TACK_STATE: a = (int)t->value->int32; negNum = a < 0; snprintf(bj, sizeof(buffer[0]), "%d", abs((int)(t->value->int32))); if (currentState == 1 && a != 1) // Just detected a tack { tackLog[0] = oldTack; int i; for (i = 6; i > 0; i--) // Shuffle them all up one tackLog[i] = tackLog[i-1]; } currentState = a; // Now display the log int k = 1; // Start the log at 1 - 0 is the current tack ready to be shuffled up int i = 0; for (i=0; i < screens[currentScreen].num_fields; i++) // Go look for TACK LOG on the screen { if (keyTitles[screens[currentScreen].field_data_map[i]].key == KEY_TACK_LOG) // Tack Log is displayed { if (tackLog[k] == 0) tackLogBuffer[k][0] = '\000'; else snprintf(tackLogBuffer[k], sizeof(tackLogBuffer[0]), "%d", tackLog[k]); setField(i, false, tackLogBuffer[k]); fieldUpdated[i] = true; k++; // Step to the next tacklog entry } } break; #ifdef CONFIG_SUPPORT case KEY_CONFIG_BOLD: useBold = (t->value->int32 != 0); foundKey = false; receivedConfig = true; break; case KEY_CONFIG_RACEBOX: racebox = t->value->int32; foundKey = false; receivedConfig = true; break; case KEY_CONFIG_VIBEDISCONNECT: vibeDisconnect = t->value->int32; foundKey = false; receivedConfig = true; break; case KEY_CONFIG_COLOURAWA: #ifdef PBL_COLOR colourAWA = t->value->int32 != 0; #endif // PBL_COLOUR foundKey = false; receivedConfig = true; break; #endif //CONFIG_SUPPORT default: APP_LOG(APP_LOG_LEVEL_ERROR, "Key %d not recognized, value %d", (int)t->key, (int)t->value->int32); foundKey = false; break; } if (foundKey) // Now look through the fields on the current screen to see if it is displayed { #ifdef CONFIG_SUPPORT foundAKey = true; #endif if (t->key == KEY_LINE_BURN) // Do vibrate regardless of what is displayed { if (!earlyWarnDone && t->value->int32 < 10 && t->value->int32 >0) { vibes_double_pulse (); earlyWarnDone = true; } else if (t->value->int32 <= 0) { if (!warnedLineBurn) { vibes_long_pulse(); warnedLineBurn = true; } } else { warnedLineBurn = false; } } int i; for (i=0; i<screens[currentScreen].num_fields; i++) { if (weAreRacing && keyTitles[screens[currentScreen].field_data_map[i]].preStart) // We are racing & we have pre-start data displayed doScreenTransition = true; // Force a transition if we are racing with a screen displaying prestart data if (keyTitles[screens[currentScreen].field_data_map[i]].key == (int)t->key) // Did we find a match? { // To this point we have only decoded the message into the buffer setField(i, negNum, bj); // Display the data - we found a match fieldUpdated[i] = true; } } // Use next buffer - the buffer remains in use even after the data actually appears on the screen // So we need to use a different buffer for each message. j++; } t = dict_read_next(iterator); // Look for next item } #ifdef CONFIG_SUPPORT if (receivedConfig) { screenMessageTimer = 3; screenMessage("Configuration received"); } if (foundAKey) { // Messages are still arriving if (tickCounter >= 7 && vibeDisconnect) vibes_double_pulse(); tickCounter = 0; } #endif if (weAreRacing && doScreenTransition && holdThisScreen == 0) // We are racing, are showing some prestart data & don't need to hold this screen { do // Loop around looing for the next in use screen { currentScreen = (1 + currentScreen) % NUM_SCREENS; } while (screens[currentScreen].num_fields == 0); if (currentScreen == startingScreen) doScreenTransition = false; // Stop looking - we're back where we started! updatescreen(currentScreen, NULL); } } while (weAreRacing && doScreenTransition && holdThisScreen == 0); int VMGtoWind; if (canDoVMG) { VMGtoWind = mycos(M_PI * ((hdg - twd) / 180.0)) * (bs * 10); VMGtoWind = VMGtoWind / 10 + (VMGtoWind % 10 >=5 ? 1 : 0); snprintf(VMGtoWindBuffer, sizeof(VMGtoWindBuffer), "%d.%d", abs(VMGtoWind)/10, abs(VMGtoWind)%10); } // Post process screen fields - VMGWind, blank non-updated fields etc. for (ii = 0; ii < screens[currentScreen].num_fields; ii++) { int fieldKeyTitle = keyTitles[screens[currentScreen].field_data_map[ii]].key; if (canDoVMG) { if (fieldKeyTitle == KEY_VMG_WIND) { setField(ii, false, VMGtoWindBuffer); fieldUpdated[ii] = true; } } #ifdef PBL_COLOR if ((fieldKeyTitle == KEY_LINE_BURN && highVMG) || (colourAWA && (fieldKeyTitle == KEY_AWA || fieldKeyTitle == KEY_TWA) && redAWA)) { // APP_LOG(APP_LOG_LEVEL_ERROR, "High VMG/AWA Port in post process"); text_layer_set_text_color(s_data_layer[screens[currentScreen].field_layer_map[ii]], redTextColour); } else if (colourAWA && (fieldKeyTitle == KEY_AWA || fieldKeyTitle == KEY_TWA) && !redAWA) { // APP_LOG(APP_LOG_LEVEL_ERROR, "AWA Starboard in post process"); text_layer_set_text_color(s_data_layer[screens[currentScreen].field_layer_map[ii]], greenTextColour); } #endif if (!fieldUpdated[ii]) { setField(ii, false, ""); // If a field has not been updated, blank it out - it will be mapped to the wrong buffer[] element } } }
static void sync_error_callback(DictionaryResult dict_error, AppMessageResult app_message_error, void *context) { APP_LOG(APP_LOG_LEVEL_DEBUG, "App Message Sync Error: %d", app_message_error); }
void in_dropped_handler(AppMessageResult reason, void *context) { APP_LOG(APP_LOG_LEVEL_DEBUG, "incoming message from Pebble dropped"); }
static void up_click_handler(ClickRecognizerRef recognizer, void *context) { APP_LOG(APP_LOG_LEVEL_DEBUG, "UP" ); }
void alarm_buzz(void* nothing) { APP_LOG(APP_LOG_LEVEL_DEBUG, "alarm buzz"); vibes_double_pulse(); alarm_timer = app_timer_register(2000, alarm_buzz, NULL); }
bool check_appmessage_result(AppMessageResult result) { switch (result) { case APP_MSG_OK: return true; case APP_MSG_SEND_TIMEOUT: APP_LOG(APP_LOG_LEVEL_ERROR, "check_appmessage_result: APP_MSG_SEND_TIMEOUT"); return false; case APP_MSG_SEND_REJECTED: APP_LOG(APP_LOG_LEVEL_ERROR, "check_appmessage_result: APP_MSG_SEND_REJECTED"); return false; case APP_MSG_NOT_CONNECTED: APP_LOG(APP_LOG_LEVEL_ERROR, "check_appmessage_result: APP_MSG_NOT_CONNECTED"); return false; case APP_MSG_APP_NOT_RUNNING: APP_LOG(APP_LOG_LEVEL_ERROR, "check_appmessage_result: APP_MSG_APP_NOT_RUNNING"); return false; case APP_MSG_INVALID_ARGS: APP_LOG(APP_LOG_LEVEL_ERROR, "check_appmessage_result: APP_MSG_INVALID_ARGS"); return false; case APP_MSG_BUSY: APP_LOG(APP_LOG_LEVEL_ERROR, "check_appmessage_result: APP_MSG_BUSY"); return false; case APP_MSG_BUFFER_OVERFLOW: APP_LOG(APP_LOG_LEVEL_ERROR, "check_appmessage_result: APP_MSG_BUFFER_OVERFLOW"); return false; case APP_MSG_ALREADY_RELEASED: APP_LOG(APP_LOG_LEVEL_ERROR, "check_appmessage_result: APP_MSG_ALREADY_RELEASED"); return false; case APP_MSG_CALLBACK_ALREADY_REGISTERED: APP_LOG(APP_LOG_LEVEL_ERROR, "check_appmessage_result: APP_MSG_CALLBACK_ALREADY_REGISTERED"); return false; case APP_MSG_CALLBACK_NOT_REGISTERED: APP_LOG(APP_LOG_LEVEL_ERROR, "check_appmessage_result: APP_MSG_CALLBACK_NOT_REGISTERED"); return false; case APP_MSG_OUT_OF_MEMORY: APP_LOG(APP_LOG_LEVEL_ERROR, "check_appmessage_result: APP_MSG_OUT_OF_MEMORY"); return false; case APP_MSG_CLOSED: APP_LOG(APP_LOG_LEVEL_ERROR, "check_appmessage_result: APP_MSG_CLOSED"); return false; case APP_MSG_INTERNAL_ERROR: APP_LOG(APP_LOG_LEVEL_ERROR, "check_appmessage_result: APP_MSG_INTERNAL_ERROR"); return false; default: APP_LOG(APP_LOG_LEVEL_ERROR, "check_appmessage_result: UNKNOWN MESSAGING ERROR"); return false; } }
static void in_dropped_handler(AppMessageResult reason, void *context) { APP_LOG(APP_LOG_LEVEL_DEBUG, "in_dropped_handler: App Error Message : %d",reason); }
/* * Handle messages from the AppMessage API. This is responsible for * handling messages about weather and configuration. Configuration * values that persist on the watch are stored here. */ static void inbox_cb(DictionaryIterator *iterator, void *context) { static int theme; static bool need_wthr; static bool need_refresh; Tuple *t; t = dict_read_first(iterator); need_wthr = need_refresh = false; while(t != NULL) { switch(t->key) { /* * App Config */ case KEY_CONFIG_API: fetch_weather(); break; case KEY_CONFIG_API_KEY: fetch_weather(); break; case KEY_CONFIG_LOCATION: fetch_weather(); break; case KEY_CONFIG_TEMP_UNIT: strncpy(s_temp_unit, t->value->cstring, sizeof(s_temp_unit)); // TODO: validation (void) persist_write_string(KEY_CONFIG_TEMP_UNIT, s_temp_unit); need_wthr = true; break; case KEY_CONFIG_THEME: theme = atoi(t->value->cstring); if(theme < 0 || theme >= THEME_COUNT) break; s_theme = theme; (void) persist_write_int(KEY_CONFIG_THEME, s_theme); need_refresh = true; need_wthr = true; break; /* * App Data */ case KEY_CONDITIONS: strncpy(s_cond, t->value->cstring, sizeof(s_cond)); need_wthr = true; break; case KEY_TEMPERATURE: s_temp = (float)t->value->int32; need_wthr = true; break; /* * Errors, Exceptional Cases */ case KEY_WEATHER_FAIL: text_layer_set_text(s_wthr_layer, "API KEY?"); text_layer_set_text_color(s_wthr_layer, theme_error); break; default: APP_LOG(APP_LOG_LEVEL_ERROR, "Key %d not recognized!", (int)t->key); break; } t = dict_read_next(iterator); } if(need_refresh) { update_all(); } if(need_wthr) { update_wthr(); } }
static void out_sent_handler(DictionaryIterator *sent, void *context) { APP_LOG(APP_LOG_LEVEL_DEBUG, "out_sent_handler: App Message sent OK!"); }
/* * Handle failed sends. */ static void outbox_failed_cb(DictionaryIterator *iterator, AppMessageResult reason, void *context) { APP_LOG(APP_LOG_LEVEL_ERROR, "Outbox send failed."); }
void main_window_mark_dirty() { APP_LOG(APP_LOG_LEVEL_DEBUG, "Main Menu DIRTY!"); //if(s_menu_layer) layer_mark_dirty((Layer *)s_menu_layer); }