Line data Source code
1 : #include "AP_BattMonitor_config.h" 2 : 3 : #if AP_BATTERY_SCRIPTING_ENABLED 4 : 5 : #include "AP_BattMonitor_Scripting.h" 6 : 7 : #define AP_BATT_MONITOR_SCRIPTING_TIMEOUT_US 5000000 8 : 9 0 : bool AP_BattMonitor_Scripting::capacity_remaining_pct(uint8_t &percentage) const 10 : { 11 0 : if (internal_state.capacity_remaining_pct != UINT8_MAX) { 12 0 : percentage = internal_state.capacity_remaining_pct; 13 0 : return true; 14 : } 15 : // Fall back to default implementation 16 0 : return AP_BattMonitor_Backend::capacity_remaining_pct(percentage); 17 : } 18 : 19 0 : bool AP_BattMonitor_Scripting::get_cycle_count(uint16_t &cycles) const 20 : { 21 0 : if (internal_state.cycle_count == UINT16_MAX) { 22 0 : return false; 23 : } 24 0 : cycles = internal_state.cycle_count; 25 0 : return true; 26 : } 27 : 28 : // Called by frontend to update the state. Called at 10Hz 29 0 : void AP_BattMonitor_Scripting::read() 30 : { 31 0 : WITH_SEMAPHORE(sem); 32 : 33 : // Check for timeout, to prevent a faulty script from appearing healthy 34 0 : if (last_update_us == 0 || AP_HAL::micros() - last_update_us > AP_BATT_MONITOR_SCRIPTING_TIMEOUT_US) { 35 0 : _state.healthy = false; 36 0 : return; 37 : } 38 : 39 0 : if (_state.last_time_micros == last_update_us) { 40 : // No new data 41 0 : return; 42 : } 43 : 44 : /* 45 : the script can fill in voltages up to 32 cells, for mavlink reporting 46 : the extra cell voltages get distributed over the max of 14 for mavlink 47 : */ 48 0 : for (uint8_t i = 0; i < MIN(AP_BATT_MONITOR_CELLS_MAX,internal_state.cell_count); i++) { 49 0 : _state.cell_voltages.cells[i] = internal_state.cell_voltages[i]; 50 : } 51 0 : _state.voltage = internal_state.voltage; 52 0 : if (!isnan(internal_state.current_amps)) { 53 0 : _state.current_amps = internal_state.current_amps; 54 : } 55 0 : if (!isnan(internal_state.consumed_mah)) { 56 0 : _state.consumed_mah = internal_state.consumed_mah; 57 : } 58 : // Overide integrated consumed energy with script value if it has been set 59 0 : if (!isnan(internal_state.consumed_wh)) { 60 0 : _state.consumed_wh = internal_state.consumed_wh; 61 : } 62 0 : if (!isnan(internal_state.temperature)) { 63 0 : _state.temperature = internal_state.temperature; 64 : } 65 : 66 : // Set state of health if provided 67 0 : _state.has_state_of_health_pct = internal_state.state_of_health_pct != UINT8_MAX; 68 0 : if (_state.has_state_of_health_pct) { 69 0 : _state.state_of_health_pct = internal_state.state_of_health_pct; 70 : } 71 : 72 0 : _state.healthy = internal_state.healthy; 73 : 74 : // Update the timestamp (has to be done after the consumed_mah calculation) 75 0 : _state.last_time_micros = last_update_us; 76 0 : } 77 : 78 0 : bool AP_BattMonitor_Scripting::handle_scripting(const BattMonitorScript_State &battmon_state) 79 : { 80 0 : WITH_SEMAPHORE(sem); 81 0 : internal_state = battmon_state; 82 0 : const uint32_t now_us = AP_HAL::micros(); 83 0 : uint32_t dt_us = now_us - last_update_us; 84 0 : if (last_update_us != 0 && !isnan(internal_state.current_amps) && isnan(internal_state.consumed_mah)) { 85 0 : AP_BattMonitor_Backend::update_consumed(_state, dt_us); 86 : } 87 0 : last_update_us = now_us; 88 0 : return true; 89 0 : } 90 : 91 : #endif // AP_BATTERY_SCRIPTING_ENABLED