Compare commits

...

16 commits

Author SHA1 Message Date
Carsten Schmiemann 8bbf09ffc5 Original project changes: Add Method to change voltage cell arrangement, preserving existing data 2022-11-01 15:03:25 +01:00
Carsten Schmiemann cf9242d798 Original project changes: BMS - Add Function to resize BMS Temperatures 2022-11-01 15:02:18 +01:00
Carsten Schmiemann 54ab5fa818 Original project changes: Vehicle - Use Enum for Bat/Temp status 2022-11-01 14:59:17 +01:00
Carsten Schmiemann ba1a0b10a3 Original project changes: Vehicle - Method to change voltage cell arrangement, preserving existing data 2022-11-01 14:58:14 +01:00
Carsten Schmiemann ef2f091267 Original project changes: Vehicle - Use Enum for Bat/Temp status 2022-11-01 14:56:56 +01:00
Carsten Schmiemann 631d3bbb2c Original project changes: Task stack size adjustments addressing issue 2022-11-01 14:54:22 +01:00
Carsten Schmiemann 1bbb754ff7 Original project changes: Config restore: shutdown SSH RSAKeyGen as necessary, fixes issue 2022-11-01 14:50:52 +01:00
Carsten Schmiemann 54edebfb5b Original project changes: Duktape: mark DuktapeConsoleCommand TODO, silence warning 2022-11-01 14:48:48 +01:00
Carsten Schmiemann d7944c8894 Original project changes: Zoe Ph2: include in standard build, fix tag warning 2022-11-01 14:47:28 +01:00
Carsten Schmiemann 337b736771 Original project changes: Bit/Byte Utils - Fixes and improvements 2022-11-01 14:29:18 +01:00
Carsten Schmiemann f6f72e8c16 Original project changes: Vehicle - Add buffer handling tools to ovms utils 2022-11-01 14:28:10 +01:00
Carsten Schmiemann 58402124dd Original project changes: Server V2 & V3: fix race condition on stopping 2022-11-01 14:24:57 +01:00
Carsten Schmiemann 5d3e4f4efa Original project changes: Boot: minor calculation optimization on 12V check 2022-11-01 14:22:57 +01:00
Carsten Schmiemann fa09dc8c71 Original project changes: fix negative integer DBC numbers having wrong values 2022-11-01 14:21:27 +01:00
Carsten Schmiemann 57e0666b47 Original project changes: fix small typos/re-formatting in documentation 2022-11-01 14:16:51 +01:00
Carsten Schmiemann a95e6e4fa2 Original project changes: Vehicle - Fix RestartCellTemperatures to resize the correct vector 2022-11-01 14:11:31 +01:00
23 changed files with 573 additions and 265 deletions

View file

@ -158,6 +158,7 @@ OvmsSSH::OvmsSSH()
using std::placeholders::_2;
MyEvents.RegisterEvent(tag,"network.mgr.init", std::bind(&OvmsSSH::NetManInit, this, _1, _2));
MyEvents.RegisterEvent(tag,"network.mgr.stop", std::bind(&OvmsSSH::NetManStop, this, _1, _2));
MyEvents.RegisterEvent(tag,"config.restore", std::bind(&OvmsSSH::ConfigRestore, this, _1, _2));
MyConfig.RegisterParam("ssh.server", "SSH server private key store", true, false);
MyConfig.RegisterParam("ssh.info", "SSH server information", false, true);
MyConfig.RegisterParam("ssh.keys", "SSH public key store", true, true);
@ -232,6 +233,14 @@ void OvmsSSH::NetManStop(std::string event, void* data)
}
}
void OvmsSSH::ConfigRestore(std::string event, void* data)
{
if (RSAKeyGenerator::KillInstance())
{
ESP_LOGW(tag, "RSAKeyGenerator killed by request");
}
}
int OvmsSSH::Authenticate(uint8_t type, WS_UserAuthData* data, void* ctx)
{
ConsoleSSH* cons = (ConsoleSSH*)ctx;
@ -1058,11 +1067,26 @@ int SendCallback(WOLFSSH* ssh, void* data, uint32_t size, void* ctx)
// Class RSAKeyGenerator
//-----------------------------------------------------------------------------
RSAKeyGenerator* RSAKeyGenerator::s_instance = NULL;
RSAKeyGenerator::RSAKeyGenerator() : TaskBase("RSAKeyGen", 7*1024, 0)
{
s_instance = this;
Instantiate();
}
RSAKeyGenerator::~RSAKeyGenerator()
{
s_instance = NULL;
}
bool RSAKeyGenerator::KillInstance()
{
if (!s_instance) return false;
s_instance->Kill();
return true;
}
void RSAKeyGenerator::Service()
{
// Generate a random 2048-bit SSH host key for the SSH server in DER format.

View file

@ -49,6 +49,7 @@ class OvmsSSH
void EventHandler(struct mg_connection *nc, int ev, void *p);
void NetManInit(std::string event, void* data);
void NetManStop(std::string event, void* data);
void ConfigRestore(std::string event, void* data);
static int Authenticate(uint8_t type, WS_UserAuthData* data, void* ctx);
WOLFSSH_CTX* ctx() { return m_ctx; }
@ -118,14 +119,18 @@ class ConsoleSSH : public OvmsConsole
class RSAKeyGenerator : public TaskBase
{
private:
static RSAKeyGenerator* s_instance;
public:
RSAKeyGenerator();
virtual ~RSAKeyGenerator() {}
virtual ~RSAKeyGenerator();
static bool KillInstance();
private:
void Service();
private:
byte m_der[1200]; // Big enough for 2048-bit private key
byte m_der[1200]; // Big enough for 2048-bit private key
};
#endif //#ifndef __CONSOLE_SSH_H__

View file

@ -19,6 +19,10 @@ COMPONENT_SRCDIRS:=src yacclex
COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive
COMPONENT_OBJS = src/dbc_app.o src/dbc_number.o src/dbc.o yacclex/dbc_tokeniser.o yacclex/dbc_parser.o
# silence warning about unused yy_flex_strncpy()
CFLAGS += -Wno-unused-function
CXXFLAGS += -Wno-unused-function
COMPONENT_EXTRA_CLEAN := $(COMPONENT_PATH)/yacclex/dbc_tokeniser.cpp \
$(COMPONENT_PATH)/yacclex/dbc_tokeniser.c \
$(COMPONENT_PATH)/yacclex/dbc_tokeniser.hpp \

View file

@ -830,8 +830,10 @@ dbcNumber dbcSignal::Decode(CAN_frame_t* msg)
if (m_value_type == DBC_VALUETYPE_UNSIGNED)
result.Cast((uint32_t)val, DBC_NUMBER_INTEGER_UNSIGNED);
else
result.Cast((uint32_t)val, DBC_NUMBER_INTEGER_SIGNED);
else {
int32_t signed_val = sign_extend<uint32_t, int32_t>((uint32_t)val, m_signal_size-1);
result.Cast(static_cast<uint32_t>(signed_val), DBC_NUMBER_INTEGER_SIGNED);
}
// Apply factor and offset
if (!(m_factor == 1))

View file

@ -1216,11 +1216,12 @@ void DukOvmsCommandRegisterRun(int verbosity, OvmsWriter* writer, OvmsCommand* c
ESP_LOGE(TAG, "Command '%s' cannot be found in registry",cmd->GetName());
return;
}
//else
// {
// DuktapeConsoleCommand* dcc = it->second;
// // Perform the callback
// }
else
{
// TODO
// DuktapeConsoleCommand* dcc = it->second;
// Perform the callback
}
}
bool OvmsDuktape::RegisterDuktapeConsoleCommand(

View file

@ -2194,8 +2194,13 @@ void ovmsv2_stop(int verbosity, OvmsWriter* writer, OvmsCommand* cmd, int argc,
if (MyOvmsServerV2 != NULL)
{
writer->puts("Stopping OVMS Server V2 connection (oscv2)");
delete MyOvmsServerV2;
OvmsServerV2 *instance = MyOvmsServerV2;
MyOvmsServerV2 = NULL;
delete instance;
}
else
{
writer->puts("OVMS v2 server has not been started");
}
}

View file

@ -282,133 +282,14 @@ void OvmsServerV3::TransmitModifiedMetrics()
if (!m_mgconn)
return;
if (StandardMetrics.ms_v_bat_soc->IsModifiedAndClear(MyOvmsServerV3Modifier))
OvmsMetric* metric = MyMetrics.m_first;
while (metric != NULL)
{
TransmitMetric(StandardMetrics.ms_v_bat_soc);
}
if (StandardMetrics.ms_v_charge_voltage->IsModifiedAndClear(MyOvmsServerV3Modifier))
{
TransmitMetric(StandardMetrics.ms_v_charge_voltage);
}
if (StandardMetrics.ms_v_charge_current->IsModifiedAndClear(MyOvmsServerV3Modifier))
{
TransmitMetric(StandardMetrics.ms_v_charge_current);
}
if (StandardMetrics.ms_v_charge_state->IsModifiedAndClear(MyOvmsServerV3Modifier))
{
TransmitMetric(StandardMetrics.ms_v_charge_state);
}
if (StandardMetrics.ms_v_charge_substate->IsModifiedAndClear(MyOvmsServerV3Modifier))
{
TransmitMetric(StandardMetrics.ms_v_charge_substate);
}
if (StandardMetrics.ms_v_charge_mode->IsModifiedAndClear(MyOvmsServerV3Modifier))
{
TransmitMetric(StandardMetrics.ms_v_charge_mode);
}
if (StandardMetrics.ms_v_bat_range_ideal->IsModifiedAndClear(MyOvmsServerV3Modifier))
{
TransmitMetric(StandardMetrics.ms_v_bat_range_ideal);
}
if (StandardMetrics.ms_v_bat_range_est->IsModifiedAndClear(MyOvmsServerV3Modifier))
{
TransmitMetric(StandardMetrics.ms_v_bat_range_est);
}
if (StandardMetrics.ms_v_charge_climit->IsModifiedAndClear(MyOvmsServerV3Modifier))
{
TransmitMetric(StandardMetrics.ms_v_charge_climit);
}
if (StandardMetrics.ms_v_charge_kwh->IsModifiedAndClear(MyOvmsServerV3Modifier))
{
TransmitMetric(StandardMetrics.ms_v_charge_kwh);
}
if (StandardMetrics.ms_v_charge_timermode->IsModifiedAndClear(MyOvmsServerV3Modifier))
{
TransmitMetric(StandardMetrics.ms_v_charge_timermode);
}
if (StandardMetrics.ms_v_charge_timerstart->IsModifiedAndClear(MyOvmsServerV3Modifier))
{
TransmitMetric(StandardMetrics.ms_v_charge_timerstart);
}
if (StandardMetrics.ms_v_bat_cac->IsModifiedAndClear(MyOvmsServerV3Modifier))
{
TransmitMetric(StandardMetrics.ms_v_bat_cac);
}
if (StandardMetrics.ms_v_charge_duration_full->IsModifiedAndClear(MyOvmsServerV3Modifier))
{
TransmitMetric(StandardMetrics.ms_v_charge_duration_full);
}
if (StandardMetrics.ms_v_charge_duration_range->IsModifiedAndClear(MyOvmsServerV3Modifier))
{
TransmitMetric(StandardMetrics.ms_v_charge_duration_range);
}
if (StandardMetrics.ms_v_charge_duration_soc->IsModifiedAndClear(MyOvmsServerV3Modifier))
{
TransmitMetric(StandardMetrics.ms_v_charge_duration_soc);
}
if (StandardMetrics.ms_v_charge_inprogress->IsModifiedAndClear(MyOvmsServerV3Modifier))
{
TransmitMetric(StandardMetrics.ms_v_charge_inprogress);
}
if (StandardMetrics.ms_v_charge_limit_range->IsModifiedAndClear(MyOvmsServerV3Modifier))
{
TransmitMetric(StandardMetrics.ms_v_charge_limit_range);
}
if (StandardMetrics.ms_v_charge_limit_soc->IsModifiedAndClear(MyOvmsServerV3Modifier))
{
TransmitMetric(StandardMetrics.ms_v_charge_limit_soc);
}
if (StandardMetrics.ms_v_env_cooling->IsModifiedAndClear(MyOvmsServerV3Modifier))
{
TransmitMetric(StandardMetrics.ms_v_env_cooling);
}
if (StandardMetrics.ms_v_bat_range_full->IsModifiedAndClear(MyOvmsServerV3Modifier))
{
TransmitMetric(StandardMetrics.ms_v_bat_range_full);
}
if (StandardMetrics.ms_v_bat_power->IsModifiedAndClear(MyOvmsServerV3Modifier))
{
TransmitMetric(StandardMetrics.ms_v_bat_power);
}
if (StandardMetrics.ms_v_bat_voltage->IsModifiedAndClear(MyOvmsServerV3Modifier))
{
TransmitMetric(StandardMetrics.ms_v_bat_voltage);
}
if (StandardMetrics.ms_v_bat_soh->IsModifiedAndClear(MyOvmsServerV3Modifier))
{
TransmitMetric(StandardMetrics.ms_v_bat_soh);
}
if (StandardMetrics.ms_v_charge_power->IsModifiedAndClear(MyOvmsServerV3Modifier))
{
TransmitMetric(StandardMetrics.ms_v_charge_power);
}
if (StandardMetrics.ms_v_charge_efficiency->IsModifiedAndClear(MyOvmsServerV3Modifier))
{
TransmitMetric(StandardMetrics.ms_v_charge_efficiency);
}
if (StandardMetrics.ms_v_bat_current->IsModifiedAndClear(MyOvmsServerV3Modifier))
{
TransmitMetric(StandardMetrics.ms_v_bat_current);
}
if (StandardMetrics.ms_v_bat_range_speed->IsModifiedAndClear(MyOvmsServerV3Modifier))
{
TransmitMetric(StandardMetrics.ms_v_bat_range_speed);
}
if (StandardMetrics.ms_v_tpms_pressure->IsModifiedAndClear(MyOvmsServerV3Modifier))
{
TransmitMetric(StandardMetrics.ms_v_tpms_pressure);
}
if (StandardMetrics.ms_v_tpms_temp->IsModifiedAndClear(MyOvmsServerV3Modifier))
{
TransmitMetric(StandardMetrics.ms_v_tpms_temp);
}
if (StandardMetrics.ms_v_tpms_health->IsModifiedAndClear(MyOvmsServerV3Modifier))
{
TransmitMetric(StandardMetrics.ms_v_tpms_health);
}
if (StandardMetrics.ms_v_tpms_alert->IsModifiedAndClear(MyOvmsServerV3Modifier))
{
TransmitMetric(StandardMetrics.ms_v_tpms_alert);
if (metric->IsModifiedAndClear(MyOvmsServerV3Modifier))
{
TransmitMetric(metric);
}
metric = metric->m_next;
}
}
@ -867,25 +748,13 @@ void OvmsServerV3::MetricModified(OvmsMetric* metric)
{
if (!StandardMetrics.ms_s_v3_connected->AsBool()) return;
int now = StandardMetrics.ms_m_monotonic->AsInt();
//ESP_LOGD(TAG, "now: %d, m_lasttx_stream: %d, m_streaming: %d", now, m_lasttx_stream, m_streaming);
if (StandardMetrics.ms_v_env_on->AsBool() && m_streaming && now > m_lasttx_stream+m_streaming)
if (m_streaming)
{
OvmsMutexLock mg(&m_mgconn_mutex);
if (!m_mgconn)
return;
//metric->ClearModified(MyOvmsServerV3Modifier);
while (metric != NULL)
{
if (metric->IsModifiedAndClear(MyOvmsServerV3Modifier))
{
TransmitMetric(metric);
}
metric = metric->m_next;
}
//TransmitMetric(metric);
m_lasttx_stream = now;
metric->ClearModified(MyOvmsServerV3Modifier);
TransmitMetric(metric);
}
}
@ -948,22 +817,13 @@ void OvmsServerV3::EventListener(std::string event, void* data)
*/
void OvmsServerV3::ConfigChanged(OvmsConfigParam* param)
{
ESP_LOGD(TAG, "--- ConfigChanged ---");
m_streaming = MyConfig.GetParamValueInt("vehicle", "stream", 0);
ESP_LOGD(TAG, "m_streaming: %d", m_streaming);
m_updatetime_connected = MyConfig.GetParamValueInt("server.v3", "updatetime.connected", 60);
ESP_LOGD(TAG, "m_updatetime_connected: %d", m_updatetime_connected);
m_updatetime_idle = MyConfig.GetParamValueInt("server.v3", "updatetime.idle", 600);
ESP_LOGD(TAG, "m_updatetime_idle: %d", m_updatetime_idle);
m_updatetime_awake = MyConfig.GetParamValueInt("server.v3", "updatetime.awake", m_updatetime_idle);
ESP_LOGD(TAG, "m_updatetime_awake: %d", m_updatetime_awake);
m_updatetime_on = MyConfig.GetParamValueInt("server.v3", "updatetime.on", m_updatetime_idle);
ESP_LOGD(TAG, "m_updatetime_on: %d", m_updatetime_on);
m_updatetime_charging = MyConfig.GetParamValueInt("server.v3", "updatetime.charging", m_updatetime_idle);
ESP_LOGD(TAG, "m_updatetime_charging: %d", m_updatetime_charging);
m_updatetime_sendall = MyConfig.GetParamValueInt("server.v3", "updatetime.sendall", 0);
ESP_LOGD(TAG, "m_updatetime_sendall: %d", m_updatetime_sendall);
ESP_LOGD(TAG, "--- ConfigChanged ---");
}
void OvmsServerV3::NetUp(std::string event, void* data)
@ -1069,55 +929,12 @@ void OvmsServerV3::Ticker1(std::string event, void* data)
}
else if ((m_lasttx==0)||(now>(m_lasttx+next)))
{
ESP_LOGD(TAG, "m_lasttx: %d next: %d, now: %d", m_lasttx, next, now);
ESP_LOGD(TAG, "m_updatetime_connected: %d m_updatetime_on: %d, m_updatetime_charging: %d", m_updatetime_connected, m_updatetime_on, m_updatetime_charging);
ESP_LOGD(TAG, "m_updatetime_awake: %d ", m_updatetime_awake);
TransmitModifiedMetrics();
m_lasttx = m_lasttx_stream = now;
}
else if (m_streaming && caron && m_peers && now > m_lasttx_stream+m_streaming)
{
//Transmit important metrics while streaming
bool modified =
StandardMetrics.ms_v_pos_latitude->IsModifiedAndClear(MyOvmsServerV3Modifier) |
StandardMetrics.ms_v_pos_longitude->IsModifiedAndClear(MyOvmsServerV3Modifier) |
StandardMetrics.ms_v_pos_direction->IsModifiedAndClear(MyOvmsServerV3Modifier) |
StandardMetrics.ms_v_pos_altitude->IsModifiedAndClear(MyOvmsServerV3Modifier) |
StandardMetrics.ms_v_pos_gpslock->IsModifiedAndClear(MyOvmsServerV3Modifier) |
StandardMetrics.ms_v_pos_gpssq->IsModifiedAndClear(MyOvmsServerV3Modifier) |
StandardMetrics.ms_v_pos_gpsmode->IsModifiedAndClear(MyOvmsServerV3Modifier) |
StandardMetrics.ms_v_pos_gpshdop->IsModifiedAndClear(MyOvmsServerV3Modifier) |
StandardMetrics.ms_v_pos_satcount->IsModifiedAndClear(MyOvmsServerV3Modifier) |
StandardMetrics.ms_v_pos_gpsspeed->IsModifiedAndClear(MyOvmsServerV3Modifier) |
StandardMetrics.ms_v_pos_speed->IsModifiedAndClear(MyOvmsServerV3Modifier) |
StandardMetrics.ms_v_env_drivemode->IsModifiedAndClear(MyOvmsServerV3Modifier) |
StandardMetrics.ms_v_bat_power->IsModifiedAndClear(MyOvmsServerV3Modifier) |
StandardMetrics.ms_v_bat_energy_used->IsModifiedAndClear(MyOvmsServerV3Modifier) |
StandardMetrics.ms_v_bat_energy_recd->IsModifiedAndClear(MyOvmsServerV3Modifier) |
StandardMetrics.ms_v_inv_power->IsModifiedAndClear(MyOvmsServerV3Modifier) |
StandardMetrics.ms_v_inv_efficiency->IsModifiedAndClear(MyOvmsServerV3Modifier);
// Quick exit if nothing modified
if ((!modified)) return;
TransmitMetric(StandardMetrics.ms_v_pos_latitude);
TransmitMetric(StandardMetrics.ms_v_pos_longitude);
TransmitMetric(StandardMetrics.ms_v_pos_direction);
TransmitMetric(StandardMetrics.ms_v_pos_altitude);
TransmitMetric(StandardMetrics.ms_v_pos_gpslock);
TransmitMetric(StandardMetrics.ms_v_pos_gpssq);
TransmitMetric(StandardMetrics.ms_v_pos_gpsmode);
TransmitMetric(StandardMetrics.ms_v_pos_gpshdop);
TransmitMetric(StandardMetrics.ms_v_pos_satcount);
TransmitMetric(StandardMetrics.ms_v_pos_gpsspeed);
TransmitMetric(StandardMetrics.ms_v_pos_speed);
TransmitMetric(StandardMetrics.ms_v_env_drivemode);
TransmitMetric(StandardMetrics.ms_v_bat_power);
TransmitMetric(StandardMetrics.ms_v_bat_energy_used);
TransmitMetric(StandardMetrics.ms_v_bat_energy_recd);
TransmitMetric(StandardMetrics.ms_v_inv_power);
TransmitMetric(StandardMetrics.ms_v_inv_efficiency);
// TODO: transmit streaming metrics
m_lasttx_stream = now;
}
}
@ -1162,6 +979,7 @@ void ovmsv3_start(int verbosity, OvmsWriter* writer, OvmsCommand* cmd, int argc,
{
if (MyOvmsServerV3 == NULL)
{
writer->puts("Launching OVMS Server V3 connection (oscv3)");
MyOvmsServerV3 = new OvmsServerV3("oscv3");
}
}
@ -1170,8 +988,14 @@ void ovmsv3_stop(int verbosity, OvmsWriter* writer, OvmsCommand* cmd, int argc,
{
if (MyOvmsServerV3 != NULL)
{
delete MyOvmsServerV3;
writer->puts("Stopping OVMS Server V3 connection (oscv3)");
OvmsServerV3 *instance = MyOvmsServerV3;
MyOvmsServerV3 = NULL;
delete instance;
}
else
{
writer->puts("OVMS v3 server has not been started");
}
}

View file

@ -6,4 +6,4 @@ PID SCAN
Vehicle Type: **PID**
This is a research module that allows developers to scan an ECU for PIDs that respond
with a valid reply to an extended OBDII query. It is not made to me functional.
with a valid reply to an extended OBDII query. It is not made to be functional.

View file

@ -273,6 +273,14 @@ typedef struct
uint32_t lastused; // Timestamp of last channel access
} vwtp_channel_t;
enum class OvmsStatus : short {
OK = 0,
Warn = 1,
Alert = 2
};
inline bool operator<(OvmsStatus lhs, OvmsStatus rhs) {
return static_cast<short>(lhs) < static_cast<short>(rhs);
}
class OvmsVehicle : public InternalRamAllocated
{
@ -631,7 +639,7 @@ class OvmsVehicle : public InternalRamAllocated
float* m_bms_vmins; // BMS minimum voltages seen (since reset)
float* m_bms_vmaxs; // BMS maximum voltages seen (since reset)
float* m_bms_vdevmaxs; // BMS maximum voltage deviations seen (since reset)
short* m_bms_valerts; // BMS voltage deviation alerts (since reset)
OvmsStatus* m_bms_valerts; // BMS voltage deviation alerts (since reset)
int m_bms_valerts_new; // BMS new voltage alerts since last notification
int m_bms_vstddev_cnt; // BMS internal stddev counter
float m_bms_vstddev_avg; // BMS internal stddev average
@ -640,7 +648,7 @@ class OvmsVehicle : public InternalRamAllocated
float* m_bms_tmins; // BMS minimum temperatures seen (since reset)
float* m_bms_tmaxs; // BMS maximum temperatures seen (since reset)
float* m_bms_tdevmaxs; // BMS maximum temperature deviations seen (since reset)
short* m_bms_talerts; // BMS temperature deviation alerts (since reset)
OvmsStatus* m_bms_talerts; // BMS temperature deviation alerts (since reset)
int m_bms_talerts_new; // BMS new temperature alerts since last notification
bool m_bms_has_temperatures; // True if BMS has a complete set of temperature values
std::vector<bool> m_bms_bitset_v; // BMS tracking: true if corresponding voltage set
@ -688,6 +696,8 @@ class OvmsVehicle : public InternalRamAllocated
void BmsResetCellStats();
virtual void BmsStatus(int verbosity, OvmsWriter* writer);
virtual bool FormatBmsAlerts(int verbosity, OvmsWriter* writer, bool show_warnings);
bool BmsCheckChangeCellArrangementVoltage(int readings, int readingspermodule = 0);
bool BmsCheckChangeCellArrangementTemperature(int readings, int readingspermodule = 0);
};
template<typename Type> OvmsVehicle* CreateVehicle()

View file

@ -60,7 +60,7 @@ void OvmsVehicle::BmsSetCellArrangementVoltage(int readings, int readingspermodu
if (m_bms_vdevmaxs != NULL) delete m_bms_vdevmaxs;
m_bms_vdevmaxs = new float[readings];
if (m_bms_valerts != NULL) delete m_bms_valerts;
m_bms_valerts = new short[readings];
m_bms_valerts = new OvmsStatus[readings];
m_bms_valerts_new = 0;
m_bms_bitset_v.clear();
@ -72,6 +72,129 @@ void OvmsVehicle::BmsSetCellArrangementVoltage(int readings, int readingspermodu
BmsResetCellVoltages(true);
}
// Internal entry for changing cell arrangements.
struct reading_entry_t
{
int cell_no;
float entry;
};
/**
* Changes the cell arrangement for Voltage, if needs be restoring any readings that were there.
* Really should only do work the first time it is called.. as for any one car, the number of readings
* should be consistent.
* @return true If the cell arrangement was changed.
*/
bool OvmsVehicle::BmsCheckChangeCellArrangementVoltage(int readings, int readingspermodule /*=0*/)
{
bool res = false;
if (readingspermodule <= 0)
{
// Passing in 0 will leave the readings per module unchanged.
readingspermodule = m_bms_readingspermodule_v;
}
if (readings != m_bms_readings_v)
{
res = true;
if (m_bms_bitset_cv == 0)
{
BmsSetCellArrangementVoltage(readings, readingspermodule);
}
else
{
// Store (potentially) sparse readings into a vector.
std::vector<reading_entry_t> cells;
// At most we will need the number of voltages set in the bitset.
cells.reserve(m_bms_bitset_cv);
reading_entry_t reading;
int maxv = readings;
if (m_bms_readings_v < maxv)
{
maxv = m_bms_readings_v;
}
for (int i = 0; i< maxv; ++i)
{
if (m_bms_bitset_v[i])
{
reading.cell_no = i;
reading.entry = m_bms_voltages[i];
cells.insert(cells.end(),reading);
}
}
BmsSetCellArrangementVoltage(readings, readingspermodule);
for ( std::vector<reading_entry_t>::iterator iter = cells.begin(); iter != cells.end(); ++iter)
{
BmsSetCellVoltage(iter->cell_no, iter->entry);
}
}
}
else if (readingspermodule != m_bms_readingspermodule_v)
{
// This only changes the read-out.
m_bms_readingspermodule_v = readingspermodule;
res = true;
}
return res;
}
/**
* Changes the cell arrangement for Temperature, if needs be restoring any readings that were there.
* Really should only do work the first time it is called.. as for any one car, the number of readings
* should be consistent.
* @return true If the cell arrangement was changed.
*/
bool OvmsVehicle::BmsCheckChangeCellArrangementTemperature(int readings, int readingspermodule /*=0*/)
{
bool res = false;
if (readingspermodule <= 0)
{
// Passing in 0 will leave the readings per module unchanged.
readingspermodule = m_bms_readingspermodule_t;
}
if (readings != m_bms_readings_t)
{
res = true;
if (m_bms_bitset_ct == 0)
{
BmsSetCellArrangementTemperature(readings, readingspermodule);
}
else
{
// Store (potentially) sparse readings into a vector.
std::vector<reading_entry_t> cells;
// At most we will need the number of Temperatures set in the bitset.
cells.reserve(m_bms_bitset_ct);
reading_entry_t reading;
int maxv = readings;
if (m_bms_readings_t < maxv)
{
maxv = m_bms_readings_t;
}
for (int i = 0; i< maxv; ++i)
{
if (m_bms_bitset_t[i])
{
reading.cell_no = i;
reading.entry = m_bms_temperatures[i];
cells.insert(cells.end(),reading);
}
}
BmsSetCellArrangementTemperature(readings, readingspermodule);
for ( std::vector<reading_entry_t>::iterator iter = cells.begin(); iter != cells.end(); ++iter)
{
BmsSetCellTemperature(iter->cell_no, iter->entry);
}
}
}
else if (readingspermodule != m_bms_readingspermodule_t)
{
// This only changes the read-out.
m_bms_readingspermodule_t = readingspermodule;
res = true;
}
return res;
}
void OvmsVehicle::BmsSetCellArrangementTemperature(int readings, int readingspermodule)
{
if (m_bms_temperatures != NULL) delete m_bms_temperatures;
@ -83,7 +206,7 @@ void OvmsVehicle::BmsSetCellArrangementTemperature(int readings, int readingsper
if (m_bms_tdevmaxs != NULL) delete m_bms_tdevmaxs;
m_bms_tdevmaxs = new float[readings];
if (m_bms_talerts != NULL) delete m_bms_talerts;
m_bms_talerts = new short[readings];
m_bms_talerts = new OvmsStatus[readings];
m_bms_talerts_new = 0;
m_bms_bitset_t.clear();
@ -153,7 +276,7 @@ void OvmsVehicle::BmsSetCellLimitsTemperature(float min, float max)
void OvmsVehicle::BmsSetCellVoltage(int index, float value)
{
//ESP_LOGV(TAG,"BmsSetCellVoltage(%d,%f) c=%d", index, value, m_bms_bitset_cv);
// ESP_LOGV(TAG,"BmsSetCellVoltage(%d,%f) c=%d", index, value, m_bms_bitset_cv);
if ((index<0)||(index>=m_bms_readings_v)) return;
if ((value<m_bms_limit_vmin)||(value>m_bms_limit_vmax)) return;
m_bms_voltages[index] = value;
@ -245,20 +368,20 @@ void OvmsVehicle::BmsSetCellVoltage(int index, float value)
dev = ROUNDPREC(m_bms_voltages[i] - avg, 5);
if (ABS(dev) > ABS(m_bms_vdevmaxs[i]))
m_bms_vdevmaxs[i] = dev;
if (ABS(dev) >= stddev + thr_alert && m_bms_valerts[i] < 2)
if (ABS(dev) >= stddev + thr_alert && m_bms_valerts[i] <= OvmsStatus::Warn)
{
m_bms_valerts[i] = 2;
m_bms_valerts[i] = OvmsStatus::Alert;
m_bms_valerts_new++; // trigger notification
}
else if (ABS(dev) >= stddev + thr_warn && m_bms_valerts[i] < 1)
m_bms_valerts[i] = 1;
else if (ABS(dev) >= stddev + thr_warn && m_bms_valerts[i] < OvmsStatus::Warn)
m_bms_valerts[i] = OvmsStatus::Warn;
}
// Publish deviation maximums & alerts:
if (stddev > StandardMetrics.ms_v_bat_pack_vstddev_max->AsFloat())
StandardMetrics.ms_v_bat_pack_vstddev_max->SetValue(stddev);
StandardMetrics.ms_v_bat_cell_vdevmax->SetElemValues(0, m_bms_readings_v, m_bms_vdevmaxs);
StandardMetrics.ms_v_bat_cell_valert->SetElemValues(0, m_bms_readings_v, m_bms_valerts);
StandardMetrics.ms_v_bat_cell_valert->SetElemValues(0, m_bms_readings_v, (short *)m_bms_valerts);
}
// complete:
@ -275,7 +398,7 @@ void OvmsVehicle::BmsSetCellVoltage(int index, float value)
void OvmsVehicle::BmsSetCellTemperature(int index, float value)
{
//ESP_LOGV(TAG,"BmsSetCellTemperature(%d,%f) c=%d", index, value, m_bms_bitset_ct);
// ESP_LOGV(TAG,"BmsSetCellTemperature(%d,%f) c=%d", index, value, m_bms_bitset_ct);
if ((index<0)||(index>=m_bms_readings_t)) return;
if ((value<m_bms_limit_tmin)||(value>m_bms_limit_tmax)) return;
m_bms_temperatures[index] = value;
@ -319,13 +442,13 @@ void OvmsVehicle::BmsSetCellTemperature(int index, float value)
dev = ROUNDPREC(m_bms_temperatures[i] - avg, 2);
if (ABS(dev) > ABS(m_bms_tdevmaxs[i]))
m_bms_tdevmaxs[i] = dev;
if (ABS(dev) >= stddev + thr_alert && m_bms_talerts[i] < 2)
if (ABS(dev) >= stddev + thr_alert && m_bms_talerts[i] < OvmsStatus::Alert)
{
m_bms_talerts[i] = 2;
m_bms_talerts[i] = OvmsStatus::Alert;
m_bms_talerts_new++; // trigger notification
}
else if (ABS(dev) >= stddev + thr_warn && m_bms_valerts[i] < 1)
m_bms_talerts[i] = 1;
else if (ABS(dev) >= stddev + thr_warn && m_bms_valerts[i] < OvmsStatus::Warn)
m_bms_talerts[i] = OvmsStatus::Warn;
}
// publish to metrics:
@ -341,7 +464,7 @@ void OvmsVehicle::BmsSetCellTemperature(int index, float value)
StandardMetrics.ms_v_bat_cell_tmin->SetElemValues(0, m_bms_readings_t, m_bms_tmins);
StandardMetrics.ms_v_bat_cell_tmax->SetElemValues(0, m_bms_readings_t, m_bms_tmaxs);
StandardMetrics.ms_v_bat_cell_tdevmax->SetElemValues(0, m_bms_readings_t, m_bms_tdevmaxs);
StandardMetrics.ms_v_bat_cell_talert->SetElemValues(0, m_bms_readings_t, m_bms_talerts);
StandardMetrics.ms_v_bat_cell_talert->SetElemValues(0, m_bms_readings_t, (short *) m_bms_talerts);
// complete:
m_bms_has_temperatures = true;
@ -365,7 +488,7 @@ void OvmsVehicle::BmsRestartCellVoltages()
void OvmsVehicle::BmsRestartCellTemperatures()
{
m_bms_bitset_t.clear();
m_bms_bitset_v.resize(m_bms_readings_t);
m_bms_bitset_t.resize(m_bms_readings_t);
m_bms_bitset_ct = 0;
}
@ -382,7 +505,7 @@ void OvmsVehicle::BmsResetCellVoltages(bool full /*=false*/)
m_bms_vmins[k] = 0;
m_bms_vmaxs[k] = 0;
m_bms_vdevmaxs[k] = 0;
m_bms_valerts[k] = 0;
m_bms_valerts[k] = OvmsStatus::OK;
}
m_bms_valerts_new = 0;
m_bms_vstddev_cnt = 0;
@ -409,7 +532,7 @@ void OvmsVehicle::BmsResetCellTemperatures(bool full /*=false*/)
m_bms_tmins[k] = 0;
m_bms_tmaxs[k] = 0;
m_bms_tdevmaxs[k] = 0;
m_bms_talerts[k] = 0;
m_bms_talerts[k] = OvmsStatus::OK;
}
m_bms_talerts_new = 0;
if (full) StandardMetrics.ms_v_bat_cell_temp->ClearValue();
@ -439,14 +562,24 @@ void OvmsVehicle::BmsStatus(int verbosity, OvmsWriter* writer)
int vwarn=0, valert=0;
int twarn=0, talert=0;
for (c=0; c<m_bms_readings_v; c++) {
if (m_bms_valerts[c]==1) vwarn++;
if (m_bms_valerts[c]==2) valert++;
}
for (c=0; c<m_bms_readings_t; c++) {
if (m_bms_talerts[c]==1) twarn++;
if (m_bms_talerts[c]==2) talert++;
}
for (c=0; c<m_bms_readings_v; c++)
{
switch (m_bms_valerts[c])
{
case OvmsStatus::OK: break;
case OvmsStatus::Warn: vwarn++; break;
case OvmsStatus::Alert: valert++;break;
}
}
for (c=0; c<m_bms_readings_t; c++)
{
switch (m_bms_talerts[c])
{
case OvmsStatus::OK: break;
case OvmsStatus::Warn: twarn++; break;
case OvmsStatus::Alert: talert++; break;
}
}
writer->puts("Voltage:");
writer->printf(" Average: %5.3fV [%5.3fV - %5.3fV]\n",
@ -515,14 +648,18 @@ bool OvmsVehicle::FormatBmsAlerts(int verbosity, OvmsWriter* writer, bool show_w
writer->printf("Voltage: StdDev %dmV", (int)(StdMetrics.ms_v_bat_pack_vstddev_max->AsFloat() * 1000));
for (int i=0; i<m_bms_readings_v; i++)
{
int sts = StdMetrics.ms_v_bat_cell_valert->GetElemValue(i);
if (sts == 0) continue;
if (sts == 1 && !show_warnings) continue;
OvmsStatus sts = OvmsStatus(StdMetrics.ms_v_bat_cell_valert->GetElemValue(i));
switch (sts)
{
case OvmsStatus::OK: continue;
case OvmsStatus::Warn: if (!show_warnings) continue;
case OvmsStatus::Alert: ;
}
has_valerts++;
if (verbose || has_valerts <= 5)
{
int dev = StdMetrics.ms_v_bat_cell_vdevmax->GetElemValue(i) * 1000;
writer->printf("\n %c #%02d: %+4dmV", (sts==1) ? '?' : '!', i+1, dev);
writer->printf("\n %c #%02d: %+4dmV", (sts==OvmsStatus::Warn) ? '?' : '!', i+1, dev);
}
else
{
@ -537,14 +674,18 @@ bool OvmsVehicle::FormatBmsAlerts(int verbosity, OvmsWriter* writer, bool show_w
writer->printf("Temperature: StdDev %.1fC", StdMetrics.ms_v_bat_pack_tstddev_max->AsFloat());
for (int i=0; i<m_bms_readings_v; i++)
{
int sts = StdMetrics.ms_v_bat_cell_talert->GetElemValue(i);
if (sts == 0) continue;
if (sts == 1 && !show_warnings) continue;
OvmsStatus sts = OvmsStatus(StdMetrics.ms_v_bat_cell_talert->GetElemValue(i));
switch (sts)
{
case OvmsStatus::OK: continue;
case OvmsStatus::Warn: if (!show_warnings) continue;
case OvmsStatus::Alert: ;
}
has_talerts++;
if (verbose || has_talerts <= 5)
{
float dev = StdMetrics.ms_v_bat_cell_tdevmax->GetElemValue(i);
writer->printf("\n %c #%02d: %+3.1fC", (sts==1) ? '?' : '!', i+1, dev);
writer->printf("\n %c #%02d: %+3.1fC", (sts==OvmsStatus::Warn) ? '?' : '!', i+1, dev);
}
else
{

View file

@ -1,6 +1,6 @@
=======================
==============================
Renault Zoe Phase 2 (OBD port)
=======================
==============================
Vehicle Type: **RZ2O**
@ -32,8 +32,10 @@ Cabin Pre-heat/cool Control No (planned, but access to CAN after gw neccessary)
Lock/Unlock Vehicle Yes (display only)
Valet Mode Control No
=========================== ==============
Others:
=================================== ==============
Door open/close Yes (exclude hood)
Battery full charge cycles Yes
Battery max charge, recd pwr Yes
@ -44,3 +46,4 @@ Aux power gauges Yes (testing needed)
Charge type Yes (DC charge, testing needed)
Headlights Status Yes (lowbeam)
Charge efficiency calculation Yes (but only for AC, pf is measured with power analyzer and included as statics)
=================================== ==============

View file

@ -42,6 +42,8 @@
#include "vehicle_renaultzoe_ph2_obd.h"
#include "ph2_poller.h"
const char *OvmsVehicleRenaultZoePh2OBD::s_tag = "v-zoe-ph2-obd";
OvmsVehicleRenaultZoePh2OBD::OvmsVehicleRenaultZoePh2OBD() {
ESP_LOGI(TAG, "Start Renault Zoe Ph2 (OBD) vehicle module");

View file

@ -26,8 +26,6 @@
#ifndef __VEHICLE_RENAULTZOE_PH2_OBD_H__
#define __VEHICLE_RENAULTZOE_PH2_OBD_H__
static const char *TAG = "v-zoe-ph2-obd";
#include <atomic>
#include "can.h"
@ -58,7 +56,11 @@ static const char *TAG = "v-zoe-ph2-obd";
using namespace std;
#define TAG (OvmsVehicleRenaultZoePh2OBD::s_tag)
class OvmsVehicleRenaultZoePh2OBD : public OvmsVehicle {
public:
static const char *s_tag;
public:
OvmsVehicleRenaultZoePh2OBD();

View file

@ -239,7 +239,7 @@ Boot::Boot()
uint32_t adc_level = 0;
for (int i = 0; i < 5; i++)
adc_level += adc1_get_raw(ADC1_CHANNEL_0);
float level_12v = adc_level / 5 / 195.7;
float level_12v = (float) adc_level / 5 / 195.7;
ESP_LOGI(TAG, "12V level: ~%.1fV", level_12v);
if (level_12v > 11.0)
ESP_LOGI(TAG, "12V level sufficient, proceeding with boot");

View file

@ -44,6 +44,7 @@ static const char *TAG = "config";
#include "ovms_events.h"
#include "ovms_utils.h"
#include "ovms_boot.h"
#include "ovms_semaphore.h"
#ifdef CONFIG_OVMS_SC_ZIP
#include "zip_archive.h"
@ -852,7 +853,24 @@ bool OvmsConfig::Restore(std::string path, std::string password, OvmsWriter* wri
else
ESP_LOGD(TAG, "Restore: reading '%s'...", path.c_str());
m_store_lock.Lock();
// Lock config store:
if (!m_store_lock.Lock(pdMS_TO_TICKS(5000)))
{
if (writer)
writer->puts("Error: config store currently in use by another process");
else
ESP_LOGE(TAG, "Restore: timeout waiting for config lock");
return false;
}
// Signal & wait for components to shutdown:
{
OvmsSemaphore eventdone;
auto callback = [](const char* event, void* data) { ((OvmsSemaphore*)data)->Give(); };
MyEvents.SignalEvent("config.restore", &eventdone, callback);
eventdone.Take();
}
bool ok = true;
// unzip into restore directory:

View file

@ -612,3 +612,19 @@ std::string idtag(const char* tag, void* instance)
std::string res = buf.str();
return res;
}
/**
* get_buff_string: Helper function to get at string value from sized buffer.
*/
bool get_buff_string(const uint8_t *data, uint32_t size, uint32_t index, uint32_t len, std::string &strret)
{
int remain = size - index;
if (remain < 0)
return false;
if (remain < len)
len = remain;
const char *begin = reinterpret_cast<const char *>(data + index) ;
const char *end = begin + len;
strret.assign<const char *>(begin, end);
return true;
}

View file

@ -36,6 +36,7 @@
#include <cstring>
#include <string>
#include <iomanip>
#include <vector>
#include "ovms.h"
// Macro utils:
@ -338,4 +339,235 @@ double float2double(float f);
std::string idtag(const char* tag, void* instance);
#define IDTAG idtag(TAG,this)
/**
* sign_extend: Sign extend an unsigned to a signed integer of the same or bigger size.
* Sign bit is not known at compile time.
*/
template<typename UINT, typename INT>
INT sign_extend( UINT uvalue, uint8_t signbit)
{
typedef typename std::make_unsigned<INT>::type uint_t;
uint_t newuvalue = uvalue;
UINT signmask = UINT(1U) << signbit;
if ( newuvalue & signmask)
newuvalue |= ~ (static_cast<uint_t>(signmask) - 1);
return reinterpret_cast<INT &>(uvalue);
}
/**
* sign_extend: Sign extend an unsigned to a signed integer of the same or bigger size.
* Sign bit is known at compile time.
*/
template<typename UINT, typename INT, uint8_t SIGNBIT>
INT sign_extend( UINT uvalue)
{
typedef typename std::make_unsigned<INT>::type uint_t;
uint_t newuvalue = uvalue;
if ( newuvalue & ( UINT(1U) << SIGNBIT) )
newuvalue |= ~((uint_t(1U) << SIGNBIT) - 1);
return reinterpret_cast<INT &>(uvalue);
}
/**
* get_bit: Get at a specific (compile-time defined) bit in a byte.
*/
template<uint8_t BIT>
bool get_bit(uint8_t data)
{
return (0 != (data & (1 << BIT)));
}
/**
* get_bit: Get at a specific (run-time defined) bit in a byte.
*/
inline bool get_bit(uint8_t data, uint8_t bit)
{
return (0 != (data & (1 << bit)));
}
/**
* get_uint_bits: Get at unsigned integer values within data.
* Compile-time defined section.
*/
template<uint8_t BIT, uint8_t BITLEN>
uint16_t get_uint_bits(uint32_t data)
{
return (data >> BIT) & ((0x1U <<(BITLEN+1))-1);
}
/**
* get_uint_bits: Get at unsigned integer values within data.
* Run-time defined section.
*/
inline uint16_t get_uint_bits(uint32_t data, uint8_t bit, uint8_t bitlen)
{
return (data >> bit) & ((0x1U <<(bitlen+1))-1);
}
/**
* get_uint_bits: Get at signed integer values within data.
* Compile-time defined section.
*/
template<uint8_t BIT, uint8_t BITLEN>
int16_t get_int_bits(uint32_t data)
{
uint16_t unsigned_val = get_uint_bits<BIT,BITLEN>(data);
return sign_extend<uint16_t,int16_t, BITLEN-1>(unsigned_val);
}
/**
* get_uint_bits: Get at signed integer values within data.
* Run-time defined section.
*/
inline int16_t get_int_bits(uint32_t data, uint8_t bit, uint8_t bitlen)
{
uint16_t unsigned_val = get_uint_bits(data, bit, bitlen);
return sign_extend<uint16_t,int16_t>(unsigned_val, bitlen-1);
}
// helper to provide a big endian integer from a given number of bytes.
// The helper function checks the length before using this.
template<uint8_t BYTES, typename UINT = uint32_t>
struct ovms_bytes_impl_t
{
static UINT get_bytes_uint(const uint8_t *data, uint32_t index)
{
return (data[index + (BYTES - 1)])
| (ovms_bytes_impl_t < BYTES - 1, UINT>::get_bytes_uint(data, index) << 8);
}
};
template<typename UINT>
struct ovms_bytes_impl_t<1,UINT>
{
static UINT get_bytes_uint(const uint8_t *data, uint32_t index)
{
return (data[index]);
}
};
// Helper Class to access Little-Endian values.
template<uint8_t BYTES, typename UINT = uint32_t>
struct get_bytes_le_impl_t
{
static UINT get_bytes_uint( const uint8_t *data, uint32_t index)
{
return ((data[index + (BYTES - 1)]) << (UINT(8) * (BYTES - 1)))
| get_bytes_le_impl_t < BYTES - 1 >::get_bytes_uint(data, index);
}
};
template<typename UINT>
struct get_bytes_le_impl_t<1, UINT>
{
static UINT get_bytes_uint(const uint8_t *data, uint32_t index)
{
return (data[index]);
}
};
/**
* get_uint_bytes_be: Access to unsigned integer (big-endian) in a data buffer.
*
* @return true If within bounds
*/
template<uint8_t BYTES, typename UINT = uint32_t>
bool get_uint_bytes_be(const uint8_t *data, uint32_t index, uint32_t length, UINT &res)
{
if ((index + (BYTES - 1)) >= length) {
return false;
}
res = ovms_bytes_impl_t<BYTES,UINT>::get_bytes_uint(data, index);
return true;
}
/**
* get_int_bytes_be: Access to signed integer (big-endian) in a data buffer.
* @return true If within bounds
*/
template<uint8_t BYTES, typename INT = int32_t>
bool get_int_bytes_be(const uint8_t *data, uint32_t index, uint32_t length, INT &res)
{
if ((index + (BYTES - 1)) >= length)
return false;
typedef typename std::make_unsigned<INT>::type uint_t;
uint_t uresult = ovms_bytes_impl_t<BYTES,uint_t>::get_bytes_uint(data, index);
res = sign_extend<uint_t, INT, BYTES * 8 - 1>(uresult);
return true;
}
/**
* get_uint_buff_be: Access to unsigned integer (big-endian) in a vector data buffer.
* @return true If successful
*/
template<uint8_t BYTES, typename UINT = uint32_t>
bool get_uint_buff_be(const std::string &data, uint32_t index, UINT &ures)
{
if ((index + (BYTES - 1)) >= data.size())
return false;
ures = ovms_bytes_impl_t<BYTES,UINT>::get_bytes_uint(reinterpret_cast<const uint8_t *>(data.data()), index);
return true;
}
/**
* get_buff_int_be: Access to signed integer (big-endian) in a std::string data buffer.
* @return true If successful
*/
template<uint8_t BYTES, typename INT = int32_t>
bool get_buff_int_be(const std::string &data, uint32_t index, INT &res)
{
if ((index + (BYTES - 1)) >= data.size())
return false;
typedef typename std::make_unsigned<INT>::type uint_t;
uint_t ures = ovms_bytes_impl_t<BYTES,uint_t>::get_bytes_uint(reinterpret_cast<const uint8_t *>(data.data()), index);
res = sign_extend<uint_t, INT, BYTES * 8 - 1>(ures);
return true;
}
/**
* get_bytes_uint_le: Access to unsigned integer (little-endian) in a data buffer.
* @return true If within bounds
*/
template<uint8_t BYTES, typename UINT = uint32_t>
bool get_bytes_uint_le(const uint8_t *data, uint32_t index, uint32_t length, UINT &res)
{
if ((index + (BYTES - 1)) >= length)
return false;
res = get_bytes_le_impl_t<BYTES,UINT>::get_bytes_uint(data, index);
return true;
}
/** Access to unsigned integer (little-endian) in a vector data buffer.
* @return true If within bounds
*/
template<uint8_t BYTES, typename UINT = uint32_t>
bool get_buff_uint_le(const std::string &data, uint32_t index, UINT &res)
{
if ((index + (BYTES - 1)) >= data.size())
return false;
res = get_bytes_le_impl_t<BYTES,UINT>::get_bytes_uint(reinterpret_cast<const uint8_t *>(data.data()), index);
return true;
}
/** Access to signed integer (little-endian) in a vector data buffer.
* @return true If within bounds
*/
template<uint8_t BYTES, typename INT = int32_t>
bool get_buff_int_le(const std::string &data, uint32_t index, INT &res)
{
if ((index + (BYTES - 1)) >= data.size())
return false;
typedef typename std::make_unsigned<INT>::type uint_t;
uint_t uresult = ovms_bytes_impl_t<BYTES,uint_t>::get_bytes_uint(reinterpret_cast<const uint8_t *>(data.data()), index);
res = sign_extend < uint_t, INT, BYTES * 8 - 1 > (uresult);
return true;
}
/** Access a string portion in a vector data buffer.
* @return true if start is within bounds.
*/
bool get_buff_string(const uint8_t *data, uint32_t size, uint32_t index, uint32_t len, std::string &strret);
inline bool get_buff_string(const std::string &data, uint32_t index, uint32_t len, std::string &strret)
{
return get_buff_string(reinterpret_cast<const uint8_t *>(data.data()), data.size(), index, len, strret);
}
#endif // __OVMS_UTILS_H__

View file

@ -165,10 +165,11 @@ void TaskBase::Task(void *object)
}
// This function should be overridden in the derived class to perform any
// cleanup operations that must be done before the task is deleted.
// cleanup operations that must be done after Service() has finished/stopped
// and before the TaskBase instance is deleted.
// This function should NOT be called from the destructor because it is
// called explicitly here before the object is deleted. That separation
// is needed so DeleteTask can clean up before deleting the task and still
// is needed so DeleteFromParent can clean up before deleting the task and still
// wait to delete the object until after the task is deleted.
void TaskBase::Cleanup()
{
@ -192,8 +193,21 @@ void TaskBase::DeleteFromParent()
// parent object's task.
void TaskBase::DeleteTask()
{
Cleanup();
if (m_taskid)
{
ESP_LOGD(TAG, "Task %s deletion at %u stack free", m_name, uxTaskGetStackHighWaterMark(m_taskid));
vTaskDelete(m_taskid);
}
Cleanup();
delete this;
}
// Kill: immediate task removal and instance deletion.
// ATT: This will terminate the running task (Service()) unconditionally!
// This function must NOT be called from the TaskBase object's own task.
void TaskBase::Kill()
{
if (m_parent)
m_parent->RemoveChild(this);
DeleteTask();
}

View file

@ -66,6 +66,7 @@ class TaskBase
public:
TaskBase(const char* name, int stack = DEFAULT_STACK, UBaseType_t priority = DEFAULT_PRIORITY, Parent* parent = NULL);
Parent* parent() { return m_parent; }
virtual void Kill();
protected:
virtual ~TaskBase();

View file

@ -377,7 +377,7 @@ CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32
CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=4096
CONFIG_MAIN_TASK_STACK_SIZE=4096
CONFIG_IPC_TASK_STACK_SIZE=1024
CONFIG_TIMER_TASK_STACK_SIZE=3584
CONFIG_TIMER_TASK_STACK_SIZE=2048
CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF=y
CONFIG_NEWLIB_STDOUT_LINE_ENDING_LF=
CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR=
@ -556,7 +556,7 @@ CONFIG_FREERTOS_LEGACY_HOOKS=
CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16
CONFIG_SUPPORT_STATIC_ALLOCATION=
CONFIG_TIMER_TASK_PRIORITY=1
CONFIG_TIMER_TASK_STACK_DEPTH=3072
CONFIG_TIMER_TASK_STACK_DEPTH=3584
CONFIG_TIMER_QUEUE_LENGTH=10
CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=0
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
@ -640,7 +640,7 @@ CONFIG_TCP_OVERSIZE_DISABLE=
#
CONFIG_LWIP_MAX_UDP_PCBS=16
CONFIG_UDP_RECVMBOX_SIZE=6
CONFIG_TCPIP_TASK_STACK_SIZE=2560
CONFIG_TCPIP_TASK_STACK_SIZE=3072
CONFIG_PPP_SUPPORT=y
CONFIG_PPP_PAP_SUPPORT=y
CONFIG_PPP_CHAP_SUPPORT=y
@ -810,6 +810,7 @@ CONFIG_MBEDTLS_ECP_NIST_OPTIM=y
# mDNS
#
CONFIG_MDNS_MAX_SERVICES=10
CONFIG_MDNS_TASK_STACK_SIZE=3072
#
# OpenSSL

View file

@ -239,7 +239,7 @@ CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32
CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=4096
CONFIG_MAIN_TASK_STACK_SIZE=4096
CONFIG_IPC_TASK_STACK_SIZE=1024
CONFIG_TIMER_TASK_STACK_SIZE=3584
CONFIG_TIMER_TASK_STACK_SIZE=2048
CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF=y
CONFIG_NEWLIB_STDOUT_LINE_ENDING_LF=
CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR=
@ -475,7 +475,7 @@ CONFIG_FREERTOS_LEGACY_HOOKS=
CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16
CONFIG_SUPPORT_STATIC_ALLOCATION=
CONFIG_TIMER_TASK_PRIORITY=20
CONFIG_TIMER_TASK_STACK_DEPTH=3072
CONFIG_TIMER_TASK_STACK_DEPTH=3584
CONFIG_TIMER_QUEUE_LENGTH=10
CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=0
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
@ -574,7 +574,7 @@ CONFIG_LWIP_TCP_RTO_TIME=3000
#
CONFIG_LWIP_MAX_UDP_PCBS=16
CONFIG_UDP_RECVMBOX_SIZE=6
CONFIG_TCPIP_TASK_STACK_SIZE=2560
CONFIG_TCPIP_TASK_STACK_SIZE=3072
CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY=
CONFIG_TCPIP_TASK_AFFINITY_CPU0=
CONFIG_TCPIP_TASK_AFFINITY_CPU1=y
@ -625,7 +625,7 @@ CONFIG_OVMS_HW_CELLULAR_MODEM_BUFFER_SIZE=1024
CONFIG_OVMS_HW_CELLULAR_MODEM_UART_SIZE=2048
CONFIG_OVMS_HW_CELLULAR_MODEM_MUXCHANNEL_SIZE=2048
CONFIG_OVMS_HW_CELLULAR_MODEM_QUEUE_SIZE=50
CONFIG_OVMS_HW_CELLULAR_MODEM_STACK_SIZE=4096
CONFIG_OVMS_HW_CELLULAR_MODEM_STACK_SIZE=4608
#
# System Options
@ -802,6 +802,7 @@ CONFIG_MBEDTLS_ECP_NIST_OPTIM=y
# mDNS
#
CONFIG_MDNS_MAX_SERVICES=10
CONFIG_MDNS_TASK_STACK_SIZE=3072
#
# ESP-MQTT Configurations

View file

@ -239,7 +239,7 @@ CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32
CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=4096
CONFIG_MAIN_TASK_STACK_SIZE=4096
CONFIG_IPC_TASK_STACK_SIZE=1024
CONFIG_TIMER_TASK_STACK_SIZE=3584
CONFIG_TIMER_TASK_STACK_SIZE=2048
CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF=y
CONFIG_NEWLIB_STDOUT_LINE_ENDING_LF=
CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR=
@ -475,7 +475,7 @@ CONFIG_FREERTOS_LEGACY_HOOKS=
CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16
CONFIG_SUPPORT_STATIC_ALLOCATION=
CONFIG_TIMER_TASK_PRIORITY=20
CONFIG_TIMER_TASK_STACK_DEPTH=3072
CONFIG_TIMER_TASK_STACK_DEPTH=3584
CONFIG_TIMER_QUEUE_LENGTH=10
CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=0
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
@ -574,7 +574,7 @@ CONFIG_LWIP_TCP_RTO_TIME=3000
#
CONFIG_LWIP_MAX_UDP_PCBS=16
CONFIG_UDP_RECVMBOX_SIZE=6
CONFIG_TCPIP_TASK_STACK_SIZE=2560
CONFIG_TCPIP_TASK_STACK_SIZE=3072
CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY=
CONFIG_TCPIP_TASK_AFFINITY_CPU0=
CONFIG_TCPIP_TASK_AFFINITY_CPU1=y
@ -625,7 +625,7 @@ CONFIG_OVMS_HW_CELLULAR_MODEM_BUFFER_SIZE=1024
CONFIG_OVMS_HW_CELLULAR_MODEM_UART_SIZE=2048
CONFIG_OVMS_HW_CELLULAR_MODEM_MUXCHANNEL_SIZE=2048
CONFIG_OVMS_HW_CELLULAR_MODEM_QUEUE_SIZE=50
CONFIG_OVMS_HW_CELLULAR_MODEM_STACK_SIZE=4096
CONFIG_OVMS_HW_CELLULAR_MODEM_STACK_SIZE=4608
#
# System Options
@ -802,6 +802,7 @@ CONFIG_MBEDTLS_ECP_NIST_OPTIM=y
# mDNS
#
CONFIG_MDNS_MAX_SERVICES=10
CONFIG_MDNS_TASK_STACK_SIZE=3072
#
# ESP-MQTT Configurations

View file

@ -239,7 +239,7 @@ CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32
CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=4096
CONFIG_MAIN_TASK_STACK_SIZE=4096
CONFIG_IPC_TASK_STACK_SIZE=1024
CONFIG_TIMER_TASK_STACK_SIZE=3584
CONFIG_TIMER_TASK_STACK_SIZE=2048
CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF=y
CONFIG_NEWLIB_STDOUT_LINE_ENDING_LF=
CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR=
@ -475,7 +475,7 @@ CONFIG_FREERTOS_LEGACY_HOOKS=
CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16
CONFIG_SUPPORT_STATIC_ALLOCATION=
CONFIG_TIMER_TASK_PRIORITY=20
CONFIG_TIMER_TASK_STACK_DEPTH=3072
CONFIG_TIMER_TASK_STACK_DEPTH=3584
CONFIG_TIMER_QUEUE_LENGTH=10
CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=0
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
@ -574,7 +574,7 @@ CONFIG_LWIP_TCP_RTO_TIME=3000
#
CONFIG_LWIP_MAX_UDP_PCBS=16
CONFIG_UDP_RECVMBOX_SIZE=6
CONFIG_TCPIP_TASK_STACK_SIZE=2560
CONFIG_TCPIP_TASK_STACK_SIZE=3072
CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY=
CONFIG_TCPIP_TASK_AFFINITY_CPU0=
CONFIG_TCPIP_TASK_AFFINITY_CPU1=y
@ -625,7 +625,7 @@ CONFIG_OVMS_HW_CELLULAR_MODEM_BUFFER_SIZE=1024
CONFIG_OVMS_HW_CELLULAR_MODEM_UART_SIZE=2048
CONFIG_OVMS_HW_CELLULAR_MODEM_MUXCHANNEL_SIZE=2048
CONFIG_OVMS_HW_CELLULAR_MODEM_QUEUE_SIZE=50
CONFIG_OVMS_HW_CELLULAR_MODEM_STACK_SIZE=4096
CONFIG_OVMS_HW_CELLULAR_MODEM_STACK_SIZE=4608
#
# System Options
@ -802,6 +802,7 @@ CONFIG_MBEDTLS_ECP_NIST_OPTIM=y
# mDNS
#
CONFIG_MDNS_MAX_SERVICES=10
CONFIG_MDNS_TASK_STACK_SIZE=3072
#
# ESP-MQTT Configurations