static void read_ADC(void) { u16 *buf = adc_buffer[adc_buffer_pos]; u8 dead; ADC_NEWVAL(0); ADC_NEWVAL(1); ADC_NEWVAL(2); adc_battery_last = ADC_DB3R; adc_buffer_pos++; adc_buffer_pos &= 3; BRES(ADC_CSR, 7); // remove EOC flag BSET(ADC_CR1, 0); // start new conversion // average battery voltage and check battery low // ignore very low, which means that it is supplied from SWIM connector adc_battery_filt = adc_battery_filt * (ADC_BAT_FILT - 1); // splitted - compiler hack adc_battery_filt = (adc_battery_filt + (ADC_BAT_FILT / 2)) / ADC_BAT_FILT + adc_battery_last; adc_battery = (u16)((adc_battery_filt + (ADC_BAT_FILT / 2)) / ADC_BAT_FILT); // start checking battery after 5s from power on if (time_sec >= 5) { // wakeup task only when something changed if (adc_battery > 50 && adc_battery < battery_low_raw) { // bat low if (!menu_battery_low) { menu_battery_low = 1; awake(MENU); } } else { // bat OK, but apply some hysteresis to not switch quickly ON/OFF if (menu_battery_low && adc_battery > battery_low_raw + 100) { menu_battery_low = 0; awake(MENU); } } } // wakeup MENU task when showing battery or at calibrate if (menu_wants_adc) awake(MENU); // reset inactivity timer when some steering or throttle applied dead = cg.steering_dead_zone; if (dead < 20) dead = 20; // use some minimal dead zone for this check if (adc_steering_last < (cg.calib_steering_mid - dead) || adc_steering_last > (cg.calib_steering_mid + dead)) reset_inactivity_timer(); else { dead = cg.throttle_dead_zone; if (dead < 20) dead = 20; // use some minimal dead zone for this check if (adc_throttle_last < (cg.calib_throttle_mid - dead) || adc_throttle_last > (cg.calib_throttle_mid + dead)) reset_inactivity_timer(); } }
// Timer event when status update operation times out void status_change_timeout(void *data) { reset_inactivity_timer(); status_change_timeout_timer = NULL; s_device_status_target = DSNone; cancel_status_check(); show_device_status(s_device_status, s_status_changed); show_msg("Operation timed out", false, 5); }
bool Server::register_business_client( QString const & client_name ) { QMutexLocker lock( &mutex_ ); auto it = business_clients_.insert( BusinessClientsCt::value_type( client_name.toStdString(), BusinessUsersCt() ) ); reset_inactivity_timer(); return it.second; }
// Callback for when Device ID list has been fetched void device_list_fetched() { reset_inactivity_timer(); if (g_device_count == 0) { show_msg("No devices found!", false, 0); hide_mainwin(); } else { if (!showing_mainwin()) show_mainwin(); hide_msg(); g_device_selected = 0; device_details_fetch(g_device_id_list[g_device_selected]); } }
void Server::incomingConnection( qintptr handle ) { cout << "server: incomingConnection " << endl; Connection * c = new Connection(); c->setAutoDelete(true); c->set_descriptor( handle ); QMutexLocker lock( &mutex_ ); threadpool_->start( c ); reset_inactivity_timer(); }
bool Server::register_business_userid( QString const & client_name, int user_id ) { auto it = business_clients_.find( client_name.toStdString() ); if( it == business_clients_.end() ) return false; QMutexLocker lock( &mutex_ ); auto it_u = it->second.insert( BusinessUsersCt::value_type( user_id ) ); reset_inactivity_timer(); return it_u.second; }
// Callback for when the phone JS indicates the status change was sent to the MyQ server void device_status_change_sent(int device_id) { reset_inactivity_timer(); if (s_device_status_target != DSNone && g_device_id_list[g_device_selected] == device_id) { APP_LOG(APP_LOG_LEVEL_DEBUG, "Status change sent. Checking for status updates..."); // Start checking for the status reaching the target // (For garage doors, wait 10 seconds before first check due to how long it take) int first_check = (s_device_type == DTLightSwitch) ? 3000 : 10000; if (status_change_check_timer != NULL) app_timer_reschedule(status_change_check_timer, first_check); else status_change_check_timer = app_timer_register(first_check, status_change_check, NULL); } }
// Callback for when user switches between devices void device_switched() { reset_inactivity_timer(); cancel_status_check(); cancel_timeout(); if (status_fetch_delay_timer != NULL) { app_timer_cancel(status_fetch_delay_timer); status_fetch_delay_timer = NULL; } // Fetch device details after a brief delay to avoid busy comms error if (details_fetch_delay_timer == NULL) details_fetch_delay_timer = app_timer_register(500, device_details_fetch_delayed, NULL); else app_timer_reschedule(details_fetch_delay_timer, 500); }
// Callback to show any error received from the phone JS or MyQ servers void comms_error(char *error_message) { cancel_status_check(); cancel_timeout(); show_msg(error_message, false, 0); if (g_device_count == 0) { if (inactivity_timer != NULL) { app_timer_cancel(inactivity_timer); inactivity_timer = NULL; } // If there are no devices, hide main win so the app closes when the error message is closed hide_mainwin(); } else { reset_inactivity_timer(); } }
void handle_init(void) { g_device_id_list = NULL; show_mainwin(); show_msg("HomeP\n\nLogging In...", true, 0); comms_register_errorhandler(comms_error); comms_register_devicelist(device_list_fetched); comms_register_devicedetails(device_details_fetched); comms_register_devicestatus(device_status_fetched); comms_register_devicestatusset(device_status_change_sent); ui_register_deviceswitch(device_switched); ui_register_statuschange(device_status_change); reset_inactivity_timer(); // Initializing comms will trigger phone JS to fetch device list init_comms(); }
// Callback for when device details have been fetched void device_details_fetched(int device_id, char *location, char *name, DeviceType device_type) { APP_LOG(APP_LOG_LEVEL_DEBUG, "Details fetched - ID: %d, Location: %s, Name: %s, DeviceType: %d", device_id, location, name, device_type); reset_inactivity_timer(); if (g_device_id_list[g_device_selected] == device_id) { show_device_details(location, name, device_type); s_device_type = device_type; s_device_status = DSUpdating; show_device_status(DSUpdating, ""); // Fetch device status after a brief delay to avoid busy comms error if (status_fetch_delay_timer == NULL) status_fetch_delay_timer = app_timer_register(100, status_fetch_delayed, NULL); else app_timer_reschedule(status_fetch_delay_timer, 100); } }
static void gs_inactivity_alarm(u8 change) { if (change == 0xff) { lcd_set(L7SEG, LB_EMPTY); return; } if (change) { cg.inactivity_alarm = (u8)menu_change_val(cg.inactivity_alarm, 0, 10, 1, 1); reset_inactivity_timer(); } lcd_7seg(L7_A); if (!cg.inactivity_alarm) lcd_chars("OFF"); else { bl_num2(cg.inactivity_alarm); lcd_char(LCHR3, 'M'); } }
// Callbck for when the device status has been fetched void device_status_fetched(int device_id, DeviceStatus status, char *status_changed) { APP_LOG(APP_LOG_LEVEL_DEBUG, "Status fetched - ID: %d, Status: %d, Selected ID: %d", device_id, status, g_device_id_list[g_device_selected]); reset_inactivity_timer(); if (g_device_id_list[g_device_selected] == device_id) { if (s_device_status_target != DSNone) { // If expecting the device status to change (e.g. Garage door opening/closing) cancel_status_check(); if (((status == DSVGDOOpen) ? DSOnOpen : status) != s_device_status_target) { APP_LOG(APP_LOG_LEVEL_DEBUG, "Status still not reached target, checking again in 2 seconds..."); // Still not reached target status, so check again after 2 seconds status_change_check_timer = app_timer_register(2000, status_change_check, NULL); } else { APP_LOG(APP_LOG_LEVEL_DEBUG, "Status has reached target"); // Status changed, so stop checking cancel_timeout(); s_device_status_target = DSNone; s_device_status = status; strncpy(s_status_changed, status_changed, sizeof(s_status_changed)); s_status_changed[sizeof(s_status_changed)-1] = '\0'; show_device_status(status, status_changed); light_enable_interaction(); vibes_short_pulse(); } } else { // Not expecting status to change, so just update the display cancel_status_check(); if (status != s_device_status) { s_device_status = status; light_enable_interaction(); } strncpy(s_status_changed, status_changed, sizeof(s_status_changed)); s_status_changed[sizeof(s_status_changed)-1] = '\0'; show_device_status(status, status_changed); } } }
// Callback when user indicates status should be changed void device_status_change() { reset_inactivity_timer(); switch (s_device_status) { case DSOnOpen: switch (s_device_type) { case DTLightSwitch: s_device_status_target = DSOff; show_device_status(DSTurningOff, ""); break; default: s_device_status_target = DSClosed; show_device_status(DSClosing, ""); break; } break; case DSVGDOOpen: case DSOpening: s_device_status_target = DSClosed; show_device_status(DSClosing, ""); break; case DSOff: s_device_status_target = DSOnOpen; show_device_status(DSTurningOn, ""); break; case DSClosed: case DSClosing: s_device_status_target = DSOnOpen; show_device_status(DSOpening, ""); break; default: // Do nothing return; break; } // Send request to MyQ servers to change the status device_status_set(g_device_id_list[g_device_selected], s_device_status_target); status_change_timeout_timer = app_timer_register(60000, status_change_timeout, NULL); }
// Timer event to update the device status periodically when it is changing void status_change_check(void *data) { reset_inactivity_timer(); status_change_check_timer = NULL; device_status_fetch(g_device_id_list[g_device_selected]); }
// read all keys static void read_keys(void) { u16 buttons_state_last = buttons_state; u16 buttons_last = buttons; u16 bit; u8 i, lbs, bs; // rotate last buttons buttons3 = buttons2; buttons2 = buttons1; // read actual keys status buttons1 = read_key_matrix(); // add CH3 button if (adc_ch3_last < 50) buttons1 |= BTN_CH3; // combine last 3 readed buttons buttons_state |= buttons1 & buttons2 & buttons3; buttons_state &= buttons1 | buttons2 | buttons3; // do autorepeat/long_press only when some keys were pressed if (buttons_state_last || buttons_state) { // key pressed or released, activate backlight backlight_on(); // handle autorepeat for first 8 keys (TRIMs and D/R) if (buttons_autorepeat) { for (i = 0, bit = 1; i < 8; i++, bit <<= 1) { if (!(bit & buttons_autorepeat)) continue; // not autorepeated lbs = (u8)(buttons_state_last & bit ? 1 : 0); bs = (u8)(buttons_state & bit ? 1 : 0); if (!lbs) { // last not pressed if (bs) { // now pressed, set it pressed and set autorepeat delay buttons |= bit; buttons_timer[i] = BTN_AUTOREPEAT_DELAY; } // do nothing for now not pressed } else { // last was pressed if (bs) { // now pressed if (--buttons_timer[i]) continue; // not expired yet // timer expired, set it pressed and set autorepeat rate buttons |= bit; buttons_timer[i] = BTN_AUTOREPEAT_RATE; } // do nothing for now not pressed } } } // handle long presses for first 12 keys // exclude keys with autorepeat ON for (i = 0, bit = 1; i < 12; i++, bit <<= 1) { if (bit & buttons_autorepeat) continue; // handled in autorepeat lbs = (u8)(buttons_state_last & bit ? 1 : 0); bs = (u8)(buttons_state & bit ? 1 : 0); if (!lbs) { // last not pressed if (bs) { // now pressed, set long press delay buttons_timer[i] = cg.long_press_delay; } // do nothing for now not pressed } else { // last was pressed if (bs) { // now pressed, check long press delay // if already long or not long enought, skip if (!buttons_timer[i] || --buttons_timer[i]) continue; // set as pressed and long pressed buttons |= bit; buttons_long |= bit; } else { // now not pressed, set as pressed when no long press was applied if (!buttons_timer[i]) continue; // was long before buttons |= bit; } } } } // add rotate encoder if (encoder_timer) encoder_timer--; if (TIM1_CNTRL) { // encoder changed if ((s8)TIM1_CNTRL >= 0) { // left buttons |= BTN_ROT_L; if (encoder_timer) buttons_long |= BTN_ROT_L; } else { // right buttons |= BTN_ROT_R; if (encoder_timer) buttons_long |= BTN_ROT_R; } // set it back to default value TIM1_CNTRL = 0; // init timer encoder_timer = ENCODER_FAST_THRESHOLD; backlight_on(); } // if some of the keys changed, wakeup MENU task and reset inactivity timer if (buttons_last != buttons || buttons_state_last != buttons_state) { awake(MENU); reset_inactivity_timer(); } }