From d0bcecb8e15dc6da8c0b490f4440e28b4742c849 Mon Sep 17 00:00:00 2001 From: sharkcow Date: Mon, 5 Aug 2024 14:14:19 +0200 Subject: [PATCH 01/45] improve handling of sufficient SoC add detection of faulty selector lever microswitch --- .../vehicle_vweup/src/vehicle_vweup.cpp | 27 +++++++-------- .../vehicle_vweup/src/vehicle_vweup.h | 5 +-- .../vehicle_vweup/src/vweup_t26.cpp | 33 +++++++++++++++++-- 3 files changed, 46 insertions(+), 19 deletions(-) diff --git a/vehicle/OVMS.V3/components/vehicle_vweup/src/vehicle_vweup.cpp b/vehicle/OVMS.V3/components/vehicle_vweup/src/vehicle_vweup.cpp index c243fbb59..a59cbc013 100644 --- a/vehicle/OVMS.V3/components/vehicle_vweup/src/vehicle_vweup.cpp +++ b/vehicle/OVMS.V3/components/vehicle_vweup/src/vehicle_vweup.cpp @@ -444,16 +444,15 @@ OvmsVehicleVWeUp::vehicle_command_t OvmsVehicleVWeUp::MsgCommandCA(std::string & // Handle changed T26 settings: if (vweup_enable_t26) { + bool soc_above_max = StdMetrics.ms_v_bat_soc->AsFloat() >= StdMetrics.ms_v_charge_limit_soc->AsInt(); if (vweup_chg_soclimit_new != StdMetrics.ms_v_charge_limit_soc->AsInt()) { - bool socswitch = StdMetrics.ms_v_charge_limit_soc->AsInt() <= StdMetrics.ms_v_bat_soc->AsFloat(); - StdMetrics.ms_v_charge_limit_soc->SetValue(vweup_chg_soclimit_new); - if (vweup_chg_soclimit_new == 0 || vweup_chg_soclimit_new > StdMetrics.ms_v_bat_soc->AsInt()) { + if (vweup_chg_soclimit_new == 0 || vweup_chg_soclimit_new > StdMetrics.ms_v_bat_soc->AsFloat()) { ESP_LOGD(TAG, "ConfigChanged: SoC limit changed to above current SoC"); if (IsCharging()) { ESP_LOGD(TAG, "ConfigChanged: already charging, nothing to do"); StdMetrics.ms_v_charge_state->SetValue("charging"); // switch from topoff mode to charging } - else if (socswitch) { // only start charge when previous max SoC was < SoC + else if (soc_above_max) { // only start charge when previous max SoC was <= SoC ESP_LOGD(TAG, "ConfigChanged: trying to start charge..."); fakestop = true; StartStopChargeT26(true); @@ -461,10 +460,11 @@ OvmsVehicleVWeUp::vehicle_command_t OvmsVehicleVWeUp::MsgCommandCA(std::string & } else { ESP_LOGD(TAG, "ConfigChanged: SoC limit changed to below current SoC"); - if (IsCharging()) { + if (IsCharging() && !soc_above_max) { // only stop charge when previous max SoC was > SoC ESP_LOGD(TAG, "ConfigChanged: stopping charge..."); StartStopChargeT26(false); } + StdMetrics.ms_v_charge_limit_soc->SetValue(vweup_chg_soclimit_new); } } if (vweup_charge_current_new != profile0_charge_current && profile0_charge_current != 0) { @@ -498,8 +498,8 @@ OvmsVehicleVWeUp::vehicle_command_t OvmsVehicleVWeUp::MsgCommandCA(std::string & } if (chg_autostop_new != chg_autostop) { chg_autostop = chg_autostop_new; - if (!chg_autostop_new) { - ESP_LOGD(TAG, "ConfigChanged: charge autostop disabled, trying to start charge..."); + if (!chg_autostop_new && soc_above_max && StdMetrics.ms_v_bat_soc->AsFloat() < 100) { + ESP_LOGD(TAG, "ConfigChanged: charge autostop disabled & SoC above max SoC, trying to start charge..."); fakestop = true; StartStopChargeT26(true); } @@ -610,12 +610,10 @@ void OvmsVehicleVWeUp::Ticker1(uint32_t ticker) } } } - if (HasT26() && m_chargestate_lastsoc > suff_soc && soc < suff_soc) { - ESP_LOGI(TAG, "Ticker1: SOC fell below sufficient SOC limit (%d%%), restarting charge", suff_soc); + if (m_chargestate_lastsoc > suff_soc && soc < suff_soc) { + ESP_LOGI(TAG, "Ticker1: SOC fell below sufficient SOC limit (%d%%), trying to restart charge...", suff_soc); fakestop = true; - ESP_LOGD(TAG, "Ticker1: trying to start charge..."); - fakestop = true; - StartStopChargeT26(true); + StartStopChargeT26(true); } m_chargestate_lastsoc = soc; @@ -1082,9 +1080,8 @@ int OvmsVehicleVWeUp::CalcChargeTime(float capacity, float max_pwr, int from_soc /** * UpdateChargeTimes: update all charge time predictions - * This is called by Ticker60() and by IncomingPollReply(), and on config changes. - * While charging, the car delivers a CTP for the current SOC limit if set, or 100%, - * but only if the OBD connection is available. + * This is called by Ticker60() and by IncomingPollReply(), and on config changes + */ void OvmsVehicleVWeUp::UpdateChargeTimes() { diff --git a/vehicle/OVMS.V3/components/vehicle_vweup/src/vehicle_vweup.h b/vehicle/OVMS.V3/components/vehicle_vweup/src/vehicle_vweup.h index 579026fb0..66e03bc26 100644 --- a/vehicle/OVMS.V3/components/vehicle_vweup/src/vehicle_vweup.h +++ b/vehicle/OVMS.V3/components/vehicle_vweup/src/vehicle_vweup.h @@ -251,7 +251,6 @@ class OvmsVehicleVWeUp : public OvmsVehicle int m_timermode_ticker; bool m_timermode_new; - // -------------------------------------------------------------------------- // Web UI Subsystem // - implementation: vweup_web.(h,cpp) @@ -356,7 +355,9 @@ class OvmsVehicleVWeUp : public OvmsVehicle bool wakeup_success; bool charge_timeout; uint8_t lever; - + uint8_t lever0_cnt; + bool p_problem; + private: RemoteCommand vweup_remote_command; // command to send, see RemoteCommandTimer() TimerHandle_t m_sendOcuHeartbeat; diff --git a/vehicle/OVMS.V3/components/vehicle_vweup/src/vweup_t26.cpp b/vehicle/OVMS.V3/components/vehicle_vweup/src/vweup_t26.cpp index a980578e9..8aa38d266 100644 --- a/vehicle/OVMS.V3/components/vehicle_vweup/src/vweup_t26.cpp +++ b/vehicle/OVMS.V3/components/vehicle_vweup/src/vweup_t26.cpp @@ -163,7 +163,7 @@ void OvmsVehicleVWeUp::T26Init() memset(m_vin, 0, sizeof(m_vin)); RegisterCanBus(3, CAN_MODE_ACTIVE, CAN_SPEED_100KBPS); - + MyConfig.RegisterParam("xvu", "VW e-Up", true, true); vin_part1 = false; vin_part2 = false; @@ -207,6 +207,8 @@ void OvmsVehicleVWeUp::T26Init() wakeup_success = false; charge_timeout = false; lever = 0x20; // assume position "P" on startup so climatecontrol works + lever0_cnt = 0; + p_problem = false; StdMetrics.ms_v_env_locked->SetValue(true); StdMetrics.ms_v_env_headlights->SetValue(false); @@ -336,8 +338,24 @@ void OvmsVehicleVWeUp::IncomingFrameCan3(CAN_frame_t *p_frame) } } if (lever != d[3]) { - ESP_LOGI(TAG, "Drive mode lever switched to %d", d[3]); + ESP_LOGI(TAG, "Drive mode lever switched to 0x%02x", d[3]); lever = d[3]; + if (lever != 0) { + lever0_cnt = 0; + p_problem = false; + } + } + if (lever == 0) { // detect "P-problem": when 12V battery is detected as defective, lever byte sometimes returns 0 when car is off. Then charge can't start since lever has to be in P position (0x20) for that... + if (lever0_cnt < 10) // wait for 10 occurences to suppress ghost triggering + lever0_cnt++; + else if (lever0_cnt == 10) { + lever0_cnt++; + if (HasOBD() && StdMetrics.ms_v_door_chargeport->AsBool()) { + ESP_LOGE(TAG, "T26: invalid selector lever value, charging impossible! Microswitch possibly defective?"); + MyNotify.NotifyStringf("alert", "Drive Mode Selector", "Invalid selector lever value, charging impossible! Microswitch possibly defective?"); + } + p_problem = true; + } } break; @@ -925,6 +943,12 @@ OvmsVehicle::vehicle_command_t OvmsVehicleVWeUp::CommandStartCharge() xSemaphoreGive(xChargeSemaphore); return Fail; } + else if (p_problem) { + ESP_LOGE(TAG, "T26: invalid selector lever value, can't start charge! Microswitch possibly defective?"); + MyNotify.NotifyStringf("alert", "Drive Mode Selector", "Invalid selector lever value, can't start charge! Microswitch possibly defective?"); + p_problem = false; + return Fail; + } fakestop = false; // reset possible workaround charge stop xSemaphoreTake(xChargeSemaphore, 0); StartStopChargeT26(true); @@ -958,6 +982,11 @@ OvmsVehicle::vehicle_command_t OvmsVehicleVWeUp::CommandStopCharge() ESP_LOGE(TAG, "Vehicle is not charging!"); return Fail; } + else if (StdMetrics.ms_v_env_on->AsBool() && !chg_workaround) { + ESP_LOGE(TAG, "Vehicle is on, can't stop charge without workaround!"); + MyNotify.NotifyStringf("alert", "Charge control", "Vehicle is on, can't stop charge without workaround!"); + return Fail; + } xSemaphoreTake(xChargeSemaphore, 0); StartStopChargeT26(false); if (xSemaphoreTake(xChargeSemaphore, pdMS_TO_TICKS(2*profile0_retries*profile0_delay))) From b2ea6eea52bc88d08afd8dfc51b597b60dd6806f Mon Sep 17 00:00:00 2001 From: Jaime Date: Thu, 8 Aug 2024 17:47:44 -0400 Subject: [PATCH 02/45] wifiHasIp --- vehicle/OVMS.V3/components/esp32wifi/src/esp32wifi.cpp | 7 +++++++ vehicle/OVMS.V3/components/esp32wifi/src/esp32wifi.h | 1 + 2 files changed, 8 insertions(+) diff --git a/vehicle/OVMS.V3/components/esp32wifi/src/esp32wifi.cpp b/vehicle/OVMS.V3/components/esp32wifi/src/esp32wifi.cpp index 83216d11a..31eb47613 100644 --- a/vehicle/OVMS.V3/components/esp32wifi/src/esp32wifi.cpp +++ b/vehicle/OVMS.V3/components/esp32wifi/src/esp32wifi.cpp @@ -1021,6 +1021,13 @@ void esp32wifi::EventWifiGotIp(std::string event, void* data) IP2STR(&m_ip_info_sta.ip), IP2STR(&m_ip_info_sta.netmask), IP2STR(&m_ip_info_sta.gw)); } +bool esp32wifi::WifiHasIp() +{ + char numstr[150]; + sprintf(numstr, IPSTR, IP2STR(&m_ip_info_sta.ip)); + return strcmp(numstr, "0.0.0.0") == 1; +} + void esp32wifi::EventWifiLostIp(std::string event, void* data) { memset(&m_ip_info_sta,0,sizeof(m_ip_info_sta)); diff --git a/vehicle/OVMS.V3/components/esp32wifi/src/esp32wifi.h b/vehicle/OVMS.V3/components/esp32wifi/src/esp32wifi.h index 2725340fa..685d8b55f 100644 --- a/vehicle/OVMS.V3/components/esp32wifi/src/esp32wifi.h +++ b/vehicle/OVMS.V3/components/esp32wifi/src/esp32wifi.h @@ -87,6 +87,7 @@ class esp32wifi : public pcp, public InternalRamAllocated void StartDhcpClient(); void SetSTAWifiIP(std::string ip="", std::string sn="", std::string gw=""); void SetAPWifiBW(); + bool WifiHasIp(); public: void EventWifiStaState(std::string event, void* data); From 6be7ca94fa75daa1e99bb55a77efdc2405adc119 Mon Sep 17 00:00:00 2001 From: Jaime Date: Thu, 8 Aug 2024 18:14:59 -0400 Subject: [PATCH 03/45] connectIIFip --- .../ovms_server_v3/src/ovms_server_v3.cpp | 37 ++++++++++++++++--- .../ovms_server_v3/src/ovms_server_v3.h | 2 + 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/vehicle/OVMS.V3/components/ovms_server_v3/src/ovms_server_v3.cpp b/vehicle/OVMS.V3/components/ovms_server_v3/src/ovms_server_v3.cpp index b72ef62b8..88160a8d2 100644 --- a/vehicle/OVMS.V3/components/ovms_server_v3/src/ovms_server_v3.cpp +++ b/vehicle/OVMS.V3/components/ovms_server_v3/src/ovms_server_v3.cpp @@ -94,7 +94,7 @@ static void OvmsServerV3MongooseCallback(struct mg_connection *nc, int ev, void StandardMetrics.ms_s_v3_connected->SetValue(false); StandardMetrics.ms_s_v3_peers->SetValue(0); MyOvmsServerV3->SetStatus("Error: Connection failed", true, OvmsServerV3::WaitReconnect); - MyOvmsServerV3->m_connretry = 60; + MyOvmsServerV3->m_connretry = 30; } } } @@ -107,7 +107,7 @@ static void OvmsServerV3MongooseCallback(struct mg_connection *nc, int ev, void if (MyOvmsServerV3) { MyOvmsServerV3->Disconnect(); - MyOvmsServerV3->m_connretry = 60; + MyOvmsServerV3->m_connretry = 30; } } else @@ -136,9 +136,14 @@ static void OvmsServerV3MongooseCallback(struct mg_connection *nc, int ev, void ESP_LOGI(TAG, "Incoming message %.*s: %.*s", (int) msg->topic.len, msg->topic.p, (int) msg->payload.len, msg->payload.p); if (MyOvmsServerV3) - { - MyOvmsServerV3->IncomingMsg(std::string(msg->topic.p,msg->topic.len), - std::string(msg->payload.p,msg->payload.len)); + { + if (MyOvmsServerV3->accept_command == 0) + { + MyOvmsServerV3->accept_command = 2; + MyOvmsServerV3->IncomingMsg( + std::string(msg->topic.p,msg->topic.len), + std::string(msg->payload.p,msg->payload.len)); + } } if (msg->qos == 1) { @@ -210,6 +215,8 @@ OvmsServerV3::OvmsServerV3(const char* name) m_notify_data_waitcomp = 0; m_notify_data_waittype = NULL; m_notify_data_waitentry = NULL; + accept_command = 0; + connection_available = false; ESP_LOGI(TAG, "OVMS Server v3 running"); @@ -625,6 +632,12 @@ void OvmsServerV3::CountClients() void OvmsServerV3::Connect() { + if (!connection_available) + { + ESP_LOGE(TAG, "No connection available, waiting for network"); + m_connretry = 10; + return; + } m_msgid = 1; m_vehicleid = MyConfig.GetParamValue("vehicle", "id"); m_server = MyConfig.GetParamValue("server.v3", "server"); @@ -877,9 +890,21 @@ void OvmsServerV3::NetmanStop(std::string event, void* data) void OvmsServerV3::Ticker1(std::string event, void* data) { + connection_available = StdMetrics.ms_m_net_connected->AsBool() && + StdMetrics.ms_m_net_ip->AsBool(); + if (accept_command != 0) + { + accept_command--; + } + if (!connection_available && m_mgconn) + { + Disconnect(); + m_connretry = 10; + } + if (m_connretry > 0) { - if (MyNetManager.m_connected_any) + if (connection_available) { m_connretry--; if (m_connretry == 0) diff --git a/vehicle/OVMS.V3/components/ovms_server_v3/src/ovms_server_v3.h b/vehicle/OVMS.V3/components/ovms_server_v3/src/ovms_server_v3.h index af843d280..80fcc241d 100644 --- a/vehicle/OVMS.V3/components/ovms_server_v3/src/ovms_server_v3.h +++ b/vehicle/OVMS.V3/components/ovms_server_v3/src/ovms_server_v3.h @@ -96,6 +96,7 @@ class OvmsServerV3 : public OvmsServer OvmsMutex m_mgconn_mutex; int m_connretry; bool m_sendall; + int accept_command; int m_msgid; int m_lasttx; int m_lasttx_sendall; @@ -108,6 +109,7 @@ class OvmsServerV3 : public OvmsServer int m_updatetime_charging; int m_updatetime_sendall; + bool connection_available; bool m_notify_info_pending; bool m_notify_error_pending; bool m_notify_alert_pending; From 9f03b7bc70731b1f3db171160866b1ab3d48abd1 Mon Sep 17 00:00:00 2001 From: Jaime Date: Fri, 9 Aug 2024 11:51:58 -0400 Subject: [PATCH 04/45] reset if not connected connected with connection available --- .../ovms_cellular/src/ovms_cellular.cpp | 5 +++ vehicle/OVMS.V3/main/metrics_standard.h | 4 ++ vehicle/OVMS.V3/main/ovms_netmanager.cpp | 39 +++++++++++++++++++ vehicle/OVMS.V3/main/ovms_netmanager.h | 1 + 4 files changed, 49 insertions(+) diff --git a/vehicle/OVMS.V3/components/ovms_cellular/src/ovms_cellular.cpp b/vehicle/OVMS.V3/components/ovms_cellular/src/ovms_cellular.cpp index 6f8683364..e477a3ea8 100644 --- a/vehicle/OVMS.V3/components/ovms_cellular/src/ovms_cellular.cpp +++ b/vehicle/OVMS.V3/components/ovms_cellular/src/ovms_cellular.cpp @@ -358,6 +358,11 @@ void modem::SetPowerMode(PowerMode powermode) } } +bool modem::ModemIsNetMode() + { + return m_state1 == NetMode; + } + void modem::AutoInit() { if (MyConfig.GetParamValueBool("auto", "modem", false)) diff --git a/vehicle/OVMS.V3/main/metrics_standard.h b/vehicle/OVMS.V3/main/metrics_standard.h index d0246f79e..0ae98969b 100644 --- a/vehicle/OVMS.V3/main/metrics_standard.h +++ b/vehicle/OVMS.V3/main/metrics_standard.h @@ -59,6 +59,8 @@ #define MS_N_MDM_MODE "m.net.mdm.mode" #define MS_N_WIFI_NETWORK "m.net.wifi.network" #define MS_N_WIFI_SQ "m.net.wifi.sq" +#define MS_N_CONNECTED "m.net.connected" +#define MS_N_IP "m.net.ip" #ifdef CONFIG_OVMS_COMP_MAX7317 #define MS_M_EGPIO_INPUT "m.egpio.input" @@ -297,6 +299,8 @@ class MetricsStandard OvmsMetricString* ms_m_net_mdm_iccid; // ICCID of SIM card in modem OvmsMetricString* ms_m_net_mdm_model; // Model of modem discovered OvmsMetricString* ms_m_net_mdm_mode; // Cellular connection mode and status + OvmsMetricBool* ms_m_net_connected; // True = connected_any is true + OvmsMetricBool* ms_m_net_ip; // True = device has ip available #ifdef CONFIG_OVMS_COMP_MAX7317 OvmsMetricBitset<10,0>* ms_m_egpio_input; // EGPIO (MAX7317) input port state (ports 0…9) diff --git a/vehicle/OVMS.V3/main/ovms_netmanager.cpp b/vehicle/OVMS.V3/main/ovms_netmanager.cpp index 2265a8c70..e403a39f6 100644 --- a/vehicle/OVMS.V3/main/ovms_netmanager.cpp +++ b/vehicle/OVMS.V3/main/ovms_netmanager.cpp @@ -343,6 +343,7 @@ void network_connections(int verbosity, OvmsWriter* writer, OvmsCommand* cmd, in OvmsNetManager::OvmsNetManager() { ESP_LOGI(TAG, "Initialising NETMANAGER (8999)"); + not_connected_counter = 0; m_connected_wifi = false; m_connected_modem = false; m_connected_any = false; @@ -399,6 +400,7 @@ OvmsNetManager::OvmsNetManager() MyEvents.RegisterEvent(TAG,"system.wifi.ap.sta.disconnected", std::bind(&OvmsNetManager::WifiApStaDisconnect, this, _1, _2)); #endif // #ifdef CONFIG_OVMS_COMP_WIFI + MyEvents.RegisterEvent(TAG, "ticker.1", std::bind(&OvmsNetManager::Ticker1, this, _1, _2)); MyEvents.RegisterEvent(TAG,"system.modem.gotip", std::bind(&OvmsNetManager::ModemUp, this, _1, _2)); MyEvents.RegisterEvent(TAG,"system.modem.stop", std::bind(&OvmsNetManager::ModemDown, this, _1, _2)); MyEvents.RegisterEvent(TAG,"system.modem.down", std::bind(&OvmsNetManager::ModemDown, this, _1, _2)); @@ -499,6 +501,7 @@ void OvmsNetManager::WifiDisconnect() void OvmsNetManager::WifiStaGotIP(std::string event, void* data) { m_wifi_sta = true; + StdMetrics.ms_m_net_ip->SetValue(true); ESP_LOGI(TAG, "WIFI client got IP"); SaveDNSServer(m_dns_wifi); @@ -518,6 +521,7 @@ void OvmsNetManager::WifiStaLostIP(std::string event, void* data) // Re-prioritise, just in case, as Wifi stack seems to mess with this // (in particular if an AP interface is up, and STA goes down, Wifi // stack seems to switch default interface to AP) + StdMetrics.ms_m_net_ip->SetValue(false); PrioritiseAndIndicate(); #ifdef CONFIG_OVMS_SC_GPL_MONGOOSE ScheduleCleanup(); @@ -652,6 +656,41 @@ void OvmsNetManager::WifiApStaDisconnect(std::string event, void* data) #endif // #ifdef CONFIG_OVMS_COMP_WIFI +void OvmsNetManager::Ticker1(std::string event, void *data) + { + StdMetrics.ms_m_net_connected->SetValue(m_connected_any); + if (!m_connected_any) + StdMetrics.ms_m_net_ip->SetValue(false); + else + { + bool connected = false; + // respect the priority of wifi over modem + if (m_connected_modem){ + if (MyPeripherals && MyPeripherals->m_cellular_modem) + { + connected = MyPeripherals->m_cellular_modem->ModemIsNetMode() && + MyPeripherals->m_cellular_modem->m_mux->IsMuxUp() && + MyPeripherals->m_cellular_modem->m_ppp->m_connected; + } + } + if (m_connected_wifi){ + if (MyPeripherals && MyPeripherals->m_esp32wifi) + { + connected = MyPeripherals->m_esp32wifi->WifiHasIp(); + } + } + StdMetrics.ms_m_net_ip->SetValue(connected); + if (m_connected_any && !connected){ + not_connected_counter++; + if (not_connected_counter > 300){ + MyBoot.Restart(); + } + } else { + not_connected_counter = 0; + } + } + } + void OvmsNetManager::ModemUp(std::string event, void* data) { m_connected_modem = true; diff --git a/vehicle/OVMS.V3/main/ovms_netmanager.h b/vehicle/OVMS.V3/main/ovms_netmanager.h index e647937ec..4437b4fdd 100644 --- a/vehicle/OVMS.V3/main/ovms_netmanager.h +++ b/vehicle/OVMS.V3/main/ovms_netmanager.h @@ -137,6 +137,7 @@ class OvmsNetManager void SetDNSServer(ip_addr_t* dnsstore); public: + int not_connected_counter; bool m_connected_wifi; bool m_connected_modem; bool m_connected_any; From 1f07c782e59726779c3c38e7ef66f4cd2b02f917 Mon Sep 17 00:00:00 2001 From: Jaime Date: Fri, 9 Aug 2024 12:15:19 -0400 Subject: [PATCH 05/45] missing imports --- vehicle/OVMS.V3/components/ovms_cellular/src/ovms_cellular.h | 1 + vehicle/OVMS.V3/main/ovms_netmanager.cpp | 1 + vehicle/OVMS.V3/main/ovms_netmanager.h | 1 + 3 files changed, 3 insertions(+) diff --git a/vehicle/OVMS.V3/components/ovms_cellular/src/ovms_cellular.h b/vehicle/OVMS.V3/components/ovms_cellular/src/ovms_cellular.h index a00db8c1a..a47ac0a4a 100644 --- a/vehicle/OVMS.V3/components/ovms_cellular/src/ovms_cellular.h +++ b/vehicle/OVMS.V3/components/ovms_cellular/src/ovms_cellular.h @@ -199,6 +199,7 @@ class modem : public pcp, public InternalRamAllocated public: // High level API functions + bool ModemIsNetMode(); void StartTask(); void StopTask(); bool StartNMEA(bool force=false); diff --git a/vehicle/OVMS.V3/main/ovms_netmanager.cpp b/vehicle/OVMS.V3/main/ovms_netmanager.cpp index e403a39f6..e38d1d5ee 100644 --- a/vehicle/OVMS.V3/main/ovms_netmanager.cpp +++ b/vehicle/OVMS.V3/main/ovms_netmanager.cpp @@ -49,6 +49,7 @@ static const char *TAG = "netmanager"; #include "ovms_command.h" #include "ovms_config.h" #include "ovms_module.h" +#include "ovms_boot.h" #ifdef CONFIG_OVMS_DEV_NETMANAGER_PING #include "ping/ping_sock.h" #endif // CONFIG_OVMS_DEV_NETMANAGER_PING diff --git a/vehicle/OVMS.V3/main/ovms_netmanager.h b/vehicle/OVMS.V3/main/ovms_netmanager.h index 4437b4fdd..c81cca2b5 100644 --- a/vehicle/OVMS.V3/main/ovms_netmanager.h +++ b/vehicle/OVMS.V3/main/ovms_netmanager.h @@ -116,6 +116,7 @@ class OvmsNetManager void WifiApStaDisconnect(std::string event, void* data); #endif // CONFIG_OVMS_COMP_WIFI + void Ticker1(std::string event, void *data); void ModemUp(std::string event, void* data); void ModemDown(std::string event, void* data); void InterfaceUp(std::string event, void* data); From 1b4f73af88bb61f0859e29ff9898c0c21fb18554 Mon Sep 17 00:00:00 2001 From: Jaime Date: Fri, 9 Aug 2024 14:21:24 -0400 Subject: [PATCH 06/45] fix definitions --- vehicle/OVMS.V3/main/metrics_standard.cpp | 2 ++ vehicle/OVMS.V3/main/ovms_netmanager.cpp | 10 ++++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/vehicle/OVMS.V3/main/metrics_standard.cpp b/vehicle/OVMS.V3/main/metrics_standard.cpp index ddcb3ab50..c11c6c175 100644 --- a/vehicle/OVMS.V3/main/metrics_standard.cpp +++ b/vehicle/OVMS.V3/main/metrics_standard.cpp @@ -56,6 +56,8 @@ MetricsStandard::MetricsStandard() ms_m_net_mdm_iccid = new OvmsMetricString(MS_N_MDM_ICCID, SM_STALE_MAX); ms_m_net_mdm_model = new OvmsMetricString(MS_N_MDM_MODEL, SM_STALE_MAX); ms_m_net_mdm_mode = new OvmsMetricString(MS_N_MDM_MODE, SM_STALE_MAX); + ms_m_net_connected = new OvmsMetricBool(MS_N_CONNECTED); + ms_m_net_ip = new OvmsMetricBool(MS_N_IP); #ifdef CONFIG_OVMS_COMP_MAX7317 ms_m_egpio_input = new OvmsMetricBitset<10,0>(MS_M_EGPIO_INPUT, SM_STALE_MAX); diff --git a/vehicle/OVMS.V3/main/ovms_netmanager.cpp b/vehicle/OVMS.V3/main/ovms_netmanager.cpp index e38d1d5ee..fe4c01693 100644 --- a/vehicle/OVMS.V3/main/ovms_netmanager.cpp +++ b/vehicle/OVMS.V3/main/ovms_netmanager.cpp @@ -659,11 +659,13 @@ void OvmsNetManager::WifiApStaDisconnect(std::string event, void* data) void OvmsNetManager::Ticker1(std::string event, void *data) { - StdMetrics.ms_m_net_connected->SetValue(m_connected_any); - if (!m_connected_any) + if (!m_connected_any){ StdMetrics.ms_m_net_ip->SetValue(false); + StdMetrics.ms_m_net_connected->SetValue(false); + } else - { + { + StdMetrics.ms_m_net_connected->SetValue(true); bool connected = false; // respect the priority of wifi over modem if (m_connected_modem){ @@ -689,7 +691,7 @@ void OvmsNetManager::Ticker1(std::string event, void *data) } else { not_connected_counter = 0; } - } + } } void OvmsNetManager::ModemUp(std::string event, void* data) From dcd23fdb8d1d10cd95fd1328885303c33ecd208d Mon Sep 17 00:00:00 2001 From: Jaime Date: Mon, 12 Aug 2024 17:52:03 -0400 Subject: [PATCH 07/45] avoid task overflow --- vehicle/OVMS.V3/main/ovms_events.cpp | 23 +++++++++++++++++++++-- vehicle/OVMS.V3/main/ovms_events.h | 1 + 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/vehicle/OVMS.V3/main/ovms_events.cpp b/vehicle/OVMS.V3/main/ovms_events.cpp index b758eae34..e83755fff 100644 --- a/vehicle/OVMS.V3/main/ovms_events.cpp +++ b/vehicle/OVMS.V3/main/ovms_events.cpp @@ -225,7 +225,7 @@ OvmsEvents::OvmsEvents() cmd_eventtrace->RegisterCommand("off","Turn event tracing OFF",event_trace); m_taskqueue = xQueueCreate(CONFIG_OVMS_HW_EVENT_QUEUE_SIZE,sizeof(event_queue_t)); - xTaskCreatePinnedToCore(EventLaunchTask, "OVMS Events", 8192, (void*)this, 8, &m_taskid, CORE(1)); + xTaskCreatePinnedToCore(EventLaunchTask, "OVMS Events", 12288, (void*)this, 8, &m_taskid, CORE(1)); AddTaskToMap(m_taskid); #ifdef CONFIG_OVMS_SC_JAVASCRIPT_DUKTAPE @@ -246,6 +246,7 @@ OvmsEvents::~OvmsEvents() void OvmsEvents::EventTask() { event_queue_t msg; + detect_event_loop_blockage = 0; esp_task_wdt_add(NULL); // WATCHDOG is active for this task while(1) @@ -259,7 +260,25 @@ void OvmsEvents::EventTask() break; case EVENT_signal: m_current_event = msg.body.signal.event; - HandleQueueSignalEvent(&msg); + if (startsWith(m_current_event, "ticker.") && uxQueueSpacesAvailable(m_taskqueue) < CONFIG_OVMS_HW_EVENT_QUEUE_SIZE/5) + { + ESP_LOGE(TAG, "Droped %s, counter %i", m_current_event.c_str(), detect_event_loop_blockage); + FreeQueueSignalEvent(&msg); + detect_event_loop_blockage++; + if (detect_event_loop_blockage > 30) + { + ESP_LOGE(TAG, "Timer service / ticker timer has died => aborting"); + MyBoot.Restart(); + } + } + else + { + HandleQueueSignalEvent(&msg); + if (startsWith(m_current_event, "ticker.") && detect_event_loop_blockage > 0) + { + detect_event_loop_blockage--; + } + } esp_task_wdt_reset(); // Reset WATCHDOG timer for this task m_current_event.clear(); break; diff --git a/vehicle/OVMS.V3/main/ovms_events.h b/vehicle/OVMS.V3/main/ovms_events.h index f1120a286..ef9f8ae08 100644 --- a/vehicle/OVMS.V3/main/ovms_events.h +++ b/vehicle/OVMS.V3/main/ovms_events.h @@ -129,6 +129,7 @@ class OvmsEvents TimerList m_timers; TimerStatusMap m_timer_active; OvmsMutex m_timers_mutex; + int detect_event_loop_blockage; #if ESP_IDF_VERSION_MAJOR >= 4 esp_event_handler_instance_t event_handler_instance; #endif From f3cfc3f17d11b8c597badb418feec041a19e1fc9 Mon Sep 17 00:00:00 2001 From: axel troncoso Date: Wed, 14 Aug 2024 13:01:24 -0400 Subject: [PATCH 08/45] Feat(init-commit-support-maxus-eu6) --- .../vehicle_maxus_euniq6/CMakeLists.txt | 13 + .../vehicle_maxus_euniq6/component.mk | 14 + .../vehicle_maxus_euniq6/src/vehicle_me6.cpp | 645 ++++++++++++++++++ .../vehicle_maxus_euniq6/src/vehicle_me6.h | 97 +++ vehicle/OVMS.V3/main/Kconfig | 8 + 5 files changed, 777 insertions(+) create mode 100644 vehicle/OVMS.V3/components/vehicle_maxus_euniq6/CMakeLists.txt create mode 100644 vehicle/OVMS.V3/components/vehicle_maxus_euniq6/component.mk create mode 100644 vehicle/OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.cpp create mode 100644 vehicle/OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.h diff --git a/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/CMakeLists.txt b/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/CMakeLists.txt new file mode 100644 index 000000000..1c2ad99a3 --- /dev/null +++ b/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/CMakeLists.txt @@ -0,0 +1,13 @@ +set(srcs) +set(include_dirs) + +if (CONFIG_OVMS_VEHICLE_MAXE6) + list(APPEND srcs "vehicle_me6.cpp") + list(APPEND include_dirs "src") +endif () + +# requirements can't depend on config +idf_component_register(SRCS ${srcs} + INCLUDE_DIRS ${include_dirs} + PRIV_REQUIRES "main" + WHOLE_ARCHIVE) diff --git a/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/component.mk b/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/component.mk new file mode 100644 index 000000000..095e6f1e3 --- /dev/null +++ b/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/component.mk @@ -0,0 +1,14 @@ +# +# Main component makefile. +# +# This Makefile can be left empty. By default, it will take the sources in the +# src/ directory, compile them and link them into lib(subdirectory_name).a +# in the build directory. This behaviour is entirely configurable, +# please read the ESP-IDF documents if you need to do this. +# + +ifdef CONFIG_OVMS_VEHICLE_MAXE6 +COMPONENT_ADD_INCLUDEDIRS:=src +COMPONENT_SRCDIRS:=src +COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive +endif diff --git a/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.cpp b/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.cpp new file mode 100644 index 000000000..06a0773af --- /dev/null +++ b/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.cpp @@ -0,0 +1,645 @@ +/* +; Project: Open Vehicle Monitor System +; Date: 14th August 2024 +; +; Changes: +; 1.0 Initial release +; +; (C) 2021 Jaime Middleton / Tucar +; (C) 2021 Axel Troncoso / Tucar +; +; Permission is hereby granted, free of charge, to any person obtaining a copy +; of this software and associated documentation files (the "Software"), to deal +; in the Software without restriction, including without limitation the rights +; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +; copies of the Software, and to permit persons to whom the Software is +; furnished to do so, subject to the following conditions: +; +; The above copyright notice and this permission notice shall be included in +; all copies or substantial portions of the Software. +; +; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +; THE SOFTWARE. +*/ + +#include "ovms_log.h" +static const char *TAG = "v-maxe6"; + +#include +#include "vehicle_me6.h" +#include "me56_pids.h" +#include "ovms_notify.h" +#include +#include "metrics_standard.h" + +// Vehicle states: +#define STATE_OFF 0 // Pollstate 0 - POLLSTATE_OFF - car is off +#define STATE_ON 1 // Pollstate 1 - POLLSTATE_ON - car is on +#define STATE_RUNNING 2 // Pollstate 2 - POLLSTATE_RUNNING - car is driving +#define STATE_CHARGING 3 // Pollstate 3 - POLLSTATE_CHARGING - car is charging + +// RX buffer access macros: b=byte# +#define RXB_BYTE(b) m_rxbuf[b] +#define RXB_UINT16(b) (((uint16_t)RXB_BYTE(b) << 8) | RXB_BYTE(b+1)) +#define RXB_UINT24(b) (((uint32_t)RXB_BYTE(b) << 16) | ((uint32_t)RXB_BYTE(b+1) << 8) \ + | RXB_BYTE(b+2)) +#define RXB_UINT32(b) (((uint32_t)RXB_BYTE(b) << 24) | ((uint32_t)RXB_BYTE(b+1) << 16) \ + | ((uint32_t)RXB_BYTE(b+2) << 8) | RXB_BYTE(b+3)) +#define RXB_INT8(b) ((int8_t)RXB_BYTE(b)) +#define RXB_INT16(b) ((int16_t)RXB_UINT16(b)) +#define RXB_INT32(b) ((int32_t)RXB_UINT32(b)) + +namespace +{ + +// The parameter namespace for this vehicle +const char PARAM_NAME[] = "xme"; + +static const OvmsPoller::poll_pid_t obdii_polls[] = + { + // VCU Polls +// { vcutx, vcurx, VEHICLE_POLL_TYPE_OBDIIEXTENDED, vcusoc, { 0, 0, 30, 30 }, 0, ISOTP_STD }, //SOC Scaled below + { vcutx, vcurx, VEHICLE_POLL_TYPE_OBDIIEXTENDED, vcutemp1, { 0, 0, 30, 30 }, 0, ISOTP_STD }, //temp + { vcutx, vcurx, VEHICLE_POLL_TYPE_OBDIIEXTENDED, vcutemp2, { 0, 0, 30, 30 }, 0, ISOTP_STD }, //temp + { vcutx, vcurx, VEHICLE_POLL_TYPE_OBDIIEXTENDED, vcuspeed, { 0, 0, 1, 30 }, 0, ISOTP_STD }, //speed in KM (maybe cruise setpoint) + { vcutx, vcurx, VEHICLE_POLL_TYPE_OBDIIEXTENDED, vcupackvolts, { 0, 0, 30, 30 }, 0, ISOTP_STD }, //Pack Voltage + { vcutx, vcurx, VEHICLE_POLL_TYPE_OBDIIEXTENDED, vcu12vamps, { 0, 0, 30, 30 }, 0, ISOTP_STD }, //12v amps? + { vcutx, vcurx, VEHICLE_POLL_TYPE_OBDIIEXTENDED, vcuchargervolts, { 0, 0, 15, 15 }, 0, ISOTP_STD }, //charger volts at a guess? +// { vcutx, vcurx, VEHICLE_POLL_TYPE_OBDIIEXTENDED, vcuchargeramps, { 0, 0, 5, 5 }, 0, ISOTP_STD }, //charger amps? + // BMS Polls + { bmstx, bmsrx, VEHICLE_POLL_TYPE_OBDIIEXTENDED, bmsStatusPid, { 0, 5, 5, 5 }, 0, ISOTP_STD }, //bms charger state??? + { bmstx, bmsrx, VEHICLE_POLL_TYPE_OBDIIEXTENDED, cellvolts, { 0, 0, 15, 15 }, 0, ISOTP_STD }, //cell volts + { bmstx, bmsrx, VEHICLE_POLL_TYPE_OBDIIEXTENDED, celltemps, { 0, 0, 15, 15 }, 0, ISOTP_STD }, //cell temps + { bmstx, bmsrx, VEHICLE_POLL_TYPE_OBDIIEXTENDED, bmssoc, { 0, 0, 30, 30 }, 0, ISOTP_STD }, //bms SOC + { bmstx, bmsrx, VEHICLE_POLL_TYPE_OBDIIEXTENDED, bmssoh, { 0, 0, 30, 30 }, 0, ISOTP_STD }, //bms SOH?? + { bmstx, bmsrx, VEHICLE_POLL_TYPE_OBDIIEXTENDED, bmssocraw, { 0, 0, 30, 30 }, 0, ISOTP_STD }, //bms raw SOC +// { bmstx, bmsrx, VEHICLE_POLL_TYPE_OBDIIEXTENDED, packamps, { 0, 0, 30, 30 }, 0, ISOTP_STD }, //bms hv amps to pack + { bmstx, bmsrx, VEHICLE_POLL_TYPE_OBDIIEXTENDED, bmsccsamps, { 0, 0, 15, 15 }, 0, ISOTP_STD }, // looks CCS state + { bmstx, bmsrx, VEHICLE_POLL_TYPE_OBDIIEXTENDED, bmsacamps, { 0, 0, 15, 15 }, 0, ISOTP_STD }, // looks CCS state +// { bmstx, bmsrx, VEHICLE_POLL_TYPE_OBDIIEXTENDED, bmsccschargeon, { 0, 0, 15, 15 }, 0, ISOTP_STD }, // looks CCS state +// { bmstx, bmsrx, VEHICLE_POLL_TYPE_OBDIIEXTENDED, bmsacchargeon, { 0, 0, 15, 15 }, 0, ISOTP_STD }, // looks CCS state + { 0, 0, 0x00, 0x00, { 0, 0, 0, 0 }, 0, 0 } + }; +charging_profile granny_steps[] = { + {0,98,6375}, // Max charge rate (7200) less charge loss + {98,100,2700}, // Observed charge rate + {0,0,0}, + }; + +charging_profile ccs_steps[] = { + {0,20,75000}, + {20,30,67000}, + {30,40,59000}, + {40,50,50000}, + {50,60,44000}, + {60,80,37000}, + {80,83,26600}, + {83,95,16200}, + {95,100,5700}, + {0,0,0}, +}; + +// Responses to the BMS Status PID +enum BmsStatus : unsigned char { + Off = 0x0, // Seen when connected but not locked + Idle = 0x1, // When the car does not have the ignition on + CcsCharging = 0x2, // When charging on a rapid CCS charger + Charging = 0x3, // When charging normally + Running = 0x4, // When the ignition is on aux or running +// AboutToSleep = 0x8, // Seen just before going to sleep +// Connected = 0xa, // Connected but not charging +// StartingCharge = 0xc // Seen when the charge was about to start +}; + +} // anon namespace + +// OvmsVehicleMaxe6 constructor + +OvmsVehicleMaxe6::OvmsVehicleMaxe6() + { + ESP_LOGI(TAG, "Start Maxus Euniq 6 vehicle module"); + + // Init CAN: + RegisterCanBus(1,CAN_MODE_ACTIVE,CAN_SPEED_500KBPS); + + // Init BMS: + BmsSetCellArrangementVoltage(96, 16); + BmsSetCellArrangementTemperature(16, 1); + BmsSetCellLimitsVoltage(2.0, 5.0); + BmsSetCellLimitsTemperature(-39, 200); + BmsSetCellDefaultThresholdsVoltage(0.020, 0.030); + BmsSetCellDefaultThresholdsTemperature(2.0, 3.0); + + // Init polling: + PollSetThrottling(0); + PollSetResponseSeparationTime(1); + PollSetState(STATE_OFF); + PollSetPidList(m_can1, obdii_polls); + + // Init VIN: + memset(m_vin, 0, sizeof(m_vin)); + + // Init Raw Soc: + m_poll_state_metric = MyMetrics.InitInt("xme.state.poll", SM_STALE_MAX, m_poll_state); + m_soc_raw = MyMetrics.InitFloat("xme.v.soc.raw", 0, SM_STALE_HIGH, Percentage); + m_consump_raw = MyMetrics.InitFloat("xme.v.consump.raw", 0, SM_STALE_HIGH); // temp to monitor bms range + m_consumprange_raw = MyMetrics.InitFloat("xme.v.consumprange.raw", 0, SM_STALE_HIGH); // temp to monitor bms range + m_watt_hour_raw = MyMetrics.InitFloat("xme.v.watt.hour.raw", 0, SM_STALE_HIGH); // temp to monitor bms range + m_poll_bmsstate = MyMetrics.InitFloat("xme.bmsstate.poll", SM_STALE_HIGH); //temp to monitor bms state + + // Register config params + MyConfig.RegisterParam("xme", "Maxus EV configuration", true, true); + + + // Init Energy: + StdMetrics.ms_v_charge_mode->SetValue("standard"); + StdMetrics.ms_v_env_ctrl_login->SetValue(true); + me56_cum_energy_charge_wh = 0; + } + +//OvmsVehicleMaxe6 destructor + +OvmsVehicleMaxe6::~OvmsVehicleMaxe6() + { + ESP_LOGI(TAG, "Stop Euniq 6 vehicle module"); + PollSetPidList(m_can1, NULL); + } + +// IncomingPollReply: + +void OvmsVehicleMaxe6::IncomingPollReply(const OvmsPoller::poll_job_t &job, uint8_t* data, uint8_t length) +{ + // init / fill rx buffer: + if (job.mlframe == 0) { + m_rxbuf.clear(); + m_rxbuf.reserve(length + job.mlremain); + } + m_rxbuf.append((char*)data, length); + if (job.mlremain) + return; + + // response complete: + ESP_LOGV(TAG, "IncomingPollReply: PID %02X: len=%d %s", job.pid, m_rxbuf.size(), hexencode(m_rxbuf).c_str()); + + int value1 = (int)data[0]; + int value2 = ((int)data[0] << 8) + (int)data[1]; + + switch (job.pid) + { + case vcuvin: // VIN + StdMetrics.ms_v_vin->SetValue(m_rxbuf); + break; + case bmsStatusPid: + SetBmsStatus(data[0]); + m_poll_bmsstate->SetValue(value1); + break; + + // set status to on StdMetrics.ms_v_env_on->SetValue(bool( d[7] & 0x10 )); + case bmssoh: //soh + StdMetrics.ms_v_bat_soh->SetValue(value1); + break; + case bmssoc: //soc from bms + StdMetrics.ms_v_bat_soc->SetValue(value2 / 100.0f); + if(StdMetrics.ms_v_bat_soc->AsFloat() >=99.35)StdMetrics.ms_v_bat_soc->SetValue(100.0f); + break; + + case bmssocraw: //soc from bms + m_soc_raw->SetValue(value2 / 100.0f); + break; + case vcutemp1: // temperature?? + StdMetrics.ms_v_mot_temp->SetValue(value1 / 10.0f); + break; + case vcutemp2: // temperature?? + StdMetrics.ms_v_env_temp->SetValue(value1 / 10.0f); + break; + case vcuspeed: // Speed in Km + { + vanIsOn = StdMetrics.ms_v_env_on->AsBool(); + if (vanIsOn) + StdMetrics.ms_v_pos_speed->SetValue(value1); // in km + else + StdMetrics.ms_v_pos_speed->SetValue(0); + } + break; + case vcupackvolts: // Pack Voltage + StdMetrics.ms_v_bat_voltage->SetValue(value2 / 10.0f); + break; + + + case bmsccsamps: + if (StdMetrics.ms_v_charge_type->AsString() == "ccs") + { + StdMetrics.ms_v_bat_current->SetValue((value2 / 10.0f) - ((value2 / 10.0f) * 2)); // converted to negative + StdMetrics.ms_v_bat_power->SetValue((((value2 / 10.0f) - ((value2 / 10.0f) * 2)) * StdMetrics.ms_v_bat_voltage->AsFloat()) / 1000.0f);// converted to negtive + } + break; + + case bmsacamps: + if (StdMetrics.ms_v_charge_type->AsString() == "type2") + { + StdMetrics.ms_v_bat_current->SetValue((StdMetrics.ms_v_bat_power->AsFloat() * 1000) / StdMetrics.ms_v_bat_voltage->AsFloat() ); // + + // + StdMetrics.ms_v_charge_current->SetValue((value2 *2) / 10.0f); + } + + break; + + case vcu12vamps: + StdMetrics.ms_v_bat_12v_current->SetValue(value1 / 10.0f); + break; + case vcuchargervolts: + if (StdMetrics.ms_v_charge_type->AsString() == "type2") + { + StdMetrics.ms_v_charge_voltage->SetValue(value2 - 16140); // possible but always 224 untill found only + } + break; + + case cellvolts: + { + // Read battery cell voltages 1-96: + BmsRestartCellVoltages(); + for (int i = 0; i < 96; i++) + { + BmsSetCellVoltage(i, RXB_UINT16(i*2) * 0.001f); + } + break; + } + case celltemps: + { + // Read battery cell temperatures 1-20: + BmsRestartCellTemperatures(); + for (int i = 0; i < 20; i++) + { + BmsSetCellTemperature(i, RXB_UINT16(i*2) * 0.001f); + } + break; + } + + default: + { + ESP_LOGW(TAG, "IncomingPollReply: unhandled PID %02X: len=%d %s", job.pid, m_rxbuf.size(), hexencode(m_rxbuf).c_str()); + } + } +} + +void OvmsVehicleMaxe6::SetBmsStatus(uint8_t status) +{ + switch (status) { +// case StartingCharge: + case Charging: + StdMetrics.ms_v_charge_type->SetValue("type2"); + StdMetrics.ms_v_door_chargeport->SetValue(true); + StdMetrics.ms_v_charge_pilot->SetValue(true); + StdMetrics.ms_v_charge_inprogress->SetValue(true); + //StdMetrics.ms_v_charge_substate->SetValue("onrequest"); + StdMetrics.ms_v_charge_state->SetValue("charging"); + StdMetrics.ms_v_charge_climit->SetValue(StdMetrics.ms_v_charge_current->AsFloat()); + StdMetrics.ms_v_charge_power->SetValue((StdMetrics.ms_v_charge_current->AsFloat() * StdMetrics.ms_v_charge_voltage->AsFloat()) / 1000); + PollSetState(STATE_CHARGING); + + break; + case CcsCharging: + StdMetrics.ms_v_charge_type->SetValue("ccs"); + StdMetrics.ms_v_door_chargeport->SetValue(true); + StdMetrics.ms_v_charge_pilot->SetValue(true); + StdMetrics.ms_v_charge_inprogress->SetValue(true); + StdMetrics.ms_v_charge_state->SetValue("charging"); + //These are added while CCS charging, EVCC won't show up so we set these here + StdMetrics.ms_v_charge_current->SetValue(-StdMetrics.ms_v_bat_current->AsFloat()); + StdMetrics.ms_v_charge_power->SetValue(-StdMetrics.ms_v_bat_power->AsFloat()); + StdMetrics.ms_v_charge_climit->SetValue(-StdMetrics.ms_v_bat_current->AsFloat()); + StdMetrics.ms_v_charge_voltage->SetValue(StdMetrics.ms_v_bat_voltage->AsFloat()); + PollSetState(STATE_CHARGING); + break; + case Running: + StdMetrics.ms_v_env_on->SetValue(true); + StdMetrics.ms_v_charge_pilot->SetValue(false); + StdMetrics.ms_v_charge_inprogress->SetValue(false); + StdMetrics.ms_v_door_chargeport->SetValue(false); + StdMetrics.ms_v_charge_type->SetValue(""); + PollSetState(STATE_RUNNING); + break; + default: + StdMetrics.ms_v_charge_pilot->SetValue(false); + StdMetrics.ms_v_charge_inprogress->SetValue(false); + StdMetrics.ms_v_door_chargeport->SetValue(false); + StdMetrics.ms_v_charge_type->SetValue(""); + StdMetrics.ms_v_charge_state->SetValue(""); + /* if (!StdMetrics.ms_v_charge_inprogress->AsBool()) + { + StdMetrics.ms_v_bat_current->SetValue(0); + StdMetrics.ms_v_bat_power->SetValue(0); + + } */ + break; + } +} + + + +// Can Frames + +void OvmsVehicleMaxe6::IncomingFrameCan1(CAN_frame_t* p_frame) + { + +//set batt temp + StdMetrics.ms_v_bat_temp->SetValue(StdMetrics.ms_v_bat_pack_tavg->AsFloat()); + + uint8_t *d = p_frame->data.u8; + + switch (p_frame->MsgID) + { + case 0x6f2: // broadcast + { + //Set ideal, est when CANdata received + float soc = StdMetrics.ms_v_bat_soc->AsFloat(); + // Setup Calculates for Efficient Range + float batTemp = StdMetrics.ms_v_bat_temp->AsFloat(); + float effSoh = StdMetrics.ms_v_bat_soh->AsFloat(); + float kwhPerKm = 1000/(consumpRange * 59 + consumpRange) / 60; + float kmPerKwh = (1000/kwhPerKm) * 1.609; + //float kmPerKwhAvg = (kmPerKwh * 59 + kmPerKwh) / 60; + m_watt_hour_raw->SetValue(kmPerKwh); + m_consumprange_raw->SetValue(kwhPerKm); + m_consump_raw->SetValue(consumpRange); + + if(kmPerKwh<4.5)kmPerKwh=4.5; + if(kmPerKwh>6.4)kmPerKwh=6.6; + if(batTemp>20)batTemp=20; + + StdMetrics.ms_v_bat_range_full->SetValue(360); + StdMetrics.ms_v_bat_range_ideal->SetValue(360 * soc / 100); + //StdMetrics.ms_v_bat_range_est->SetValue(360 * soc / 108); + StdMetrics.ms_v_bat_range_est->SetValue(72.7*((kmPerKwh * (1-((20-batTemp)*1.3)/100)*(soc/100))*(effSoh/100))); + + break; + } + default: + break; + + case 0x540: // odometer in KM + { + StdMetrics.ms_v_pos_odometer->SetValue(d[0] << 16 | d[1] << 8 | d[2]);// odometer + break; + } + + case 0x389: // charger or battery temp + { + float invtemp = d[1]; + StdMetrics.ms_v_inv_temp->SetValue(invtemp / 10); + break; + } + + case 0x604: // actual power to HV Battery ( does not work on ccs and maybe ac?\) + { + // hvpower = d[5]; + // float hvbatpower = (hvpower * 42 / 1000); + // StdMetrics.ms_v_bat_power->SetValue(-hvbatpower); + break; + } + } +} + +void OvmsVehicleMaxe6::Ticker1(uint32_t ticker) +{ + processEnergy(); +} + +// PollerStateTicker: framework callback: check for state changes +// This is called by VehicleTicker1() just before the next PollerSend(). + +void OvmsVehicleMaxe6::PollerStateTicker(canbus *bus) +{ + bool charging12v = StdMetrics.ms_v_env_charging12v->AsBool(); + StdMetrics.ms_v_env_charging12v->SetValue(StdMetrics.ms_v_bat_12v_voltage->AsFloat() >= 12.9); + //StdMetrics.ms_v_charge_inprogress->SetValue(-StdMetrics.ms_v_bat_power->AsFloat() >= 1.000f); + m_poll_state_metric->SetValue(m_poll_state); + + // Determine new polling state: + // int poll_state; + if (charging12v) + { + // poll_state = STATE_ON; + PollSetState(STATE_ON); + StdMetrics.ms_v_env_awake->SetValue(true); + } + else + { + // poll_state = STATE_OFF; + PollSetState(STATE_OFF); + StdMetrics.ms_v_env_awake->SetValue(false); + } +} + +// Vehicle framework registration + +void OvmsVehicleMaxe6::processEnergy() +{ + // When called each to battery power for a second is calculated. + // This is added to ms_v_bat_energy_recd if regenerating or + // ms_v_bat_energy_used if power is being drawn from the battery + + // Only calculate if the car is turned on and not charging. + if (StdMetrics.ms_v_env_awake->AsBool() && + !StdMetrics.ms_v_charge_inprogress->AsBool()) { + // Are we in READY state? Ready to drive off. + if (StdMetrics.ms_v_env_on->AsBool()) { + auto bat_power = StdMetrics.ms_v_bat_power->AsFloat(); + // Calculate battery power (kW) for one second + auto energy = bat_power / 3600.0; + // Calculate current (A) used for one second. + auto coulombs = (StdMetrics.ms_v_bat_current->AsFloat() / 3600.0); + // Car is still parked so trip has not started. + // Set all values to zero + if (StdMetrics.ms_v_env_drivetime->AsInt() == 0) { + ESP_LOGI(TAG, "Trip has started"); + StdMetrics.ms_v_bat_coulomb_used->SetValue(0); + StdMetrics.ms_v_bat_coulomb_recd->SetValue(0); + StdMetrics.ms_v_bat_energy_used->SetValue(0); + StdMetrics.ms_v_bat_energy_recd->SetValue(0); + // Otherwise we are already moving so do calculations + } + else + { + // Calculate regeneration power + if (bat_power < 0) { + StdMetrics.ms_v_bat_energy_recd->SetValue + (StdMetrics.ms_v_bat_energy_recd->AsFloat() + -(energy)); + + StdMetrics.ms_v_bat_coulomb_recd->SetValue + (StdMetrics.ms_v_bat_coulomb_recd->AsFloat() + -(coulombs)); + + // Calculate power usage. Add power used each second + } + else + { + StdMetrics.ms_v_bat_energy_used->SetValue + (StdMetrics.ms_v_bat_energy_used->AsFloat() + energy); + + StdMetrics.ms_v_bat_coulomb_used->SetValue + (StdMetrics.ms_v_bat_coulomb_used->AsFloat() + coulombs); + } + } + } + // Not in READY so must have been turned off + else + { + // We have only just stopped so add trip values to the totals + if (StdMetrics.ms_v_env_parktime->AsInt() == 0) { + ESP_LOGI(TAG, "Trip has ended"); + StdMetrics.ms_v_bat_energy_used_total->SetValue + (StdMetrics.ms_v_bat_energy_used_total->AsFloat() + + StdMetrics.ms_v_bat_energy_used->AsFloat()); + + StdMetrics.ms_v_bat_energy_recd_total->SetValue + (StdMetrics.ms_v_bat_energy_recd_total->AsFloat() + + StdMetrics.ms_v_bat_energy_recd->AsFloat()); + + StdMetrics.ms_v_bat_coulomb_used_total->SetValue + (StdMetrics.ms_v_bat_coulomb_used_total->AsFloat() + + StdMetrics.ms_v_bat_coulomb_used->AsFloat()); + + StdMetrics.ms_v_bat_coulomb_recd_total->SetValue + (StdMetrics.ms_v_bat_coulomb_recd_total->AsFloat() + + StdMetrics.ms_v_bat_coulomb_recd->AsFloat()); + } + } + } + + // Add cumulative charge energy each second to ms_v_charge_power + if(StdMetrics.ms_v_charge_inprogress->AsBool()) + { + me56_cum_energy_charge_wh += StdMetrics.ms_v_charge_power->AsFloat()*1000/3600; + StdMetrics.ms_v_charge_kwh->SetValue(me56_cum_energy_charge_wh/1000); +// me56_cum_energy_charge_wh += StdMetrics.ms_v_charge_power->AsFloat()/3600; +// StdMetrics.ms_v_charge_kwh->SetValue((me56_cum_energy_charge_wh/1000) * 1.609f); + + int limit_soc = StdMetrics.ms_v_charge_limit_soc->AsInt(0); + float limit_range = StdMetrics.ms_v_charge_limit_range->AsFloat(0, Kilometers); + float max_range = StdMetrics.ms_v_bat_range_full->AsFloat(0, Kilometers); + + // Calculate time to reach 100% charge + int minsremaining_full = StdMetrics.ms_v_charge_type->AsString() == "ccs" ? calcMinutesRemaining(100, ccs_steps) : calcMinutesRemaining(100, granny_steps); + StdMetrics.ms_v_charge_duration_full->SetValue(minsremaining_full); + ESP_LOGV(TAG, "Time remaining: %d mins to full", minsremaining_full); + + // Calculate time to charge to SoC Limit + if (limit_soc > 0) + { + // if limit_soc is set, then calculate remaining time to limit_soc + int minsremaining_soc = StdMetrics.ms_v_charge_type->AsString() == "ccs" ? calcMinutesRemaining(limit_soc, ccs_steps) : calcMinutesRemaining(limit_soc, granny_steps); + StdMetrics.ms_v_charge_duration_soc->SetValue(minsremaining_soc, Minutes); + if ( minsremaining_soc == 0 && !soc_limit_reached && limit_soc >= StdMetrics.ms_v_bat_soc->AsFloat(100)) + { + MyNotify.NotifyStringf("info", "charge.limit.soc", "Charge limit of %d%% reached", limit_soc); + soc_limit_reached = true; + } + ESP_LOGV(TAG, "Time remaining: %d mins to %d%% soc", minsremaining_soc, limit_soc); + } + + // Calculate time to charge to Range Limit + if (limit_range > 0.0 && max_range > 0.0) + { + // if range limit is set, then compute required soc and then calculate remaining time to that soc + int range_soc = limit_range / max_range * 100.0; + int minsremaining_range = StdMetrics.ms_v_charge_type->AsString() == "ccs" ? calcMinutesRemaining(range_soc, ccs_steps) : calcMinutesRemaining(range_soc, granny_steps); + StdMetrics.ms_v_charge_duration_range->SetValue(minsremaining_range, Minutes); + if ( minsremaining_range == 0 && !range_limit_reached && range_soc >= StdMetrics.ms_v_bat_soc->AsFloat(100)) + { + MyNotify.NotifyStringf("info", "charge.limit.range", "Charge limit of %dkm reached", (int) limit_range); + range_limit_reached = true; + } + ESP_LOGV(TAG, "Time remaining: %d mins for %0.0f km (%d%% soc)", minsremaining_range, limit_range, range_soc); + } + // When we are not charging set back to zero ready for next charge. + } + else + { + me56_cum_energy_charge_wh=0; + StdMetrics.ms_v_charge_duration_full->SetValue(0); + StdMetrics.ms_v_charge_duration_soc->SetValue(0); + StdMetrics.ms_v_charge_duration_range->SetValue(0); + soc_limit_reached = false; + range_limit_reached = false; + } +} + +// Calculate the time to reach the Target and return in minutes +int OvmsVehicleMaxe6::calcMinutesRemaining(int toSoc, charging_profile charge_steps[]) +{ + + int minutes = 0; + int percents_In_Step; + int fromSoc = StdMetrics.ms_v_bat_soc->AsInt(100); + int batterySize = 72700; + float chargespeed = -StdMetrics.ms_v_bat_power->AsFloat() * 1000; + + for (int i = 0; charge_steps[i].toPercent != 0; i++) { + if (charge_steps[i].toPercent > fromSoc && charge_steps[i].fromPercenttoSoc ? toSoc : charge_steps[i].toPercent) - (charge_steps[i].fromPercentAsFloat() >= 5) //temp removed till speed found + //if (StdMetrics.ms_v_env_on->AsBool()) //Temp till speed found + consumption = ABS(StdMetrics.ms_v_bat_power->AsFloat(0, Watts)) / StdMetrics.ms_v_pos_speed->AsFloat(); + StdMetrics.ms_v_bat_consumption->SetValue((StdMetrics.ms_v_bat_consumption->AsFloat() * 29 + consumption) / 30); + consumpRange = ABS(StdMetrics.ms_v_bat_consumption->AsFloat()); + + + } + +//Called by OVMS when a config param is changed +void OvmsVehicleMaxe6::ConfigChanged(OvmsConfigParam* param) +{ + if (param && param->GetName() != PARAM_NAME) + { + return; + } + + ESP_LOGI(TAG, "%s config changed", PARAM_NAME); + + // Instances: + // xme + // suffsoc Sufficient SOC [%] (Default: 0=disabled) + // suffrange Sufficient range [km] (Default: 0=disabled) + StdMetrics.ms_v_charge_limit_soc->SetValue( + (float) MyConfig.GetParamValueInt("xme", "suffsoc"), Percentage ); + + if (MyConfig.GetParamValue("vehicle", "units.distance") == "K") + { + StdMetrics.ms_v_charge_limit_range->SetValue( + (float) MyConfig.GetParamValueInt("xme", "suffrange"), Kilometers ); + } + else + { + StdMetrics.ms_v_charge_limit_range->SetValue( + (float) MyConfig.GetParamValueInt("xme", "suffrange"), Miles ); + } +} + +class OvmsVehicleMaxe6Init + { + public: OvmsVehicleMaxe6Init(); + } OvmsVehicleMaxe6Init __attribute__ ((init_priority (9000))); + +OvmsVehicleMaxe6Init::OvmsVehicleMaxe6Init() + { + ESP_LOGI(TAG, "Registering Vehicle: Maxus Euniq 6 (9000)"); + + MyVehicleFactory.RegisterVehicle("ME56","Maxus Euniq 6"); + } diff --git a/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.h b/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.h new file mode 100644 index 000000000..def0e6ac7 --- /dev/null +++ b/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.h @@ -0,0 +1,97 @@ +/* +; Project: Open Vehicle Monitor System +; Date: 14th August 2024 +; +; Changes: +; 1.0 Initial release +; +; (C) 2021 Jaime Middleton / Tucar +; (C) 2021 Axel Troncoso / Tucar +; +; Permission is hereby granted, free of charge, to any person obtaining a copy +; of this software and associated documentation files (the "Software"), to deal +; in the Software without restriction, including without limitation the rights +; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +; copies of the Software, and to permit persons to whom the Software is +; furnished to do so, subject to the following conditions: +; +; The above copyright notice and this permission notice shall be included in +; all copies or substantial portions of the Software. +; +; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +; THE SOFTWARE. +*/ + +#ifndef __VEHICLE_ME6_H__ +#define __VEHICLE_ME6_H__ + +#include "vehicle.h" +#include "metrics_standard.h" + +#include "freertos/timers.h" + +#include + + +using namespace std; + +typedef struct{ + int fromPercent; + int toPercent; + float maxChargeSpeed; +}charging_profile; + +class OvmsCommand; + +class OvmsVehicleMaxe6 : public OvmsVehicle + { + public: + OvmsVehicleMaxe6(); + ~OvmsVehicleMaxe6(); + + OvmsMetricInt *m_poll_state_metric; // Kept equal to m_poll_state for debugging purposes + OvmsMetricFloat* m_soc_raw; + OvmsMetricFloat* m_watt_hour_raw; + OvmsMetricFloat* m_consump_raw; + OvmsMetricFloat* m_consumprange_raw; + OvmsMetricFloat* m_poll_bmsstate; + + protected: + std::string m_rxbuf; + + + protected: + void ConfigChanged(OvmsConfigParam* param) override; + void PollerStateTicker(canbus *bus); + void Ticker1(uint32_t ticker) override; + void IncomingPollReply(const OvmsPoller::poll_job_t &job, uint8_t* data, uint8_t length) override; + void processEnergy(); + float consumpRange; + float hvpower; + char m_vin[17]; + + private: + void IncomingFrameCan1(CAN_frame_t* p_frame) override; + void IncomingPollFrame(CAN_frame_t* frame); + void SetBmsStatus(uint8_t status); + /// A temporary store for the VIN + + int calcMinutesRemaining(int toSoc, charging_profile charge_steps[]); + float me56_cum_energy_charge_wh; + bool soc_limit_reached; + bool range_limit_reached; + bool vanIsOn; + bool ccschargeon; + bool acchargeon; + + virtual void calculateEfficiency(); + + }; + +#endif //#ifndef __VEHICLE_ME6_H__ + diff --git a/vehicle/OVMS.V3/main/Kconfig b/vehicle/OVMS.V3/main/Kconfig index e37cd6fab..8db1415c6 100644 --- a/vehicle/OVMS.V3/main/Kconfig +++ b/vehicle/OVMS.V3/main/Kconfig @@ -429,6 +429,14 @@ config OVMS_VEHICLE_MAXE56 depends on OVMS_COMP_POLLER help Enable to include support for Maxus Euniq 5 6-seats vehicle. + +config OVMS_VEHICLE_MAXE6 + bool "Include support for Maxus Euniq 6 vehicle" + default y + depends on OVMS + depends on OVMS_COMP_POLLER + help + Enable to include support for Maxus Euniq 6 vehicle. config OVMS_VEHICLE_KIASOULEV bool "Include support for Kia Soul EV vehicles" From 74f6e20dba8e79a8478c2d44077b386cff0e6196 Mon Sep 17 00:00:00 2001 From: axel troncoso Date: Wed, 14 Aug 2024 16:27:43 -0400 Subject: [PATCH 09/45] Feat(correct-can-codes-and-tested) --- .../vehicle_maxus_euniq6/src/vehicle_me6.cpp | 729 ++++-------------- .../vehicle_maxus_euniq6/src/vehicle_me6.h | 51 +- 2 files changed, 158 insertions(+), 622 deletions(-) diff --git a/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.cpp b/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.cpp index 06a0773af..166182d93 100644 --- a/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.cpp +++ b/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.cpp @@ -31,605 +31,174 @@ static const char *TAG = "v-maxe6"; #include +#include + #include "vehicle_me6.h" #include "me56_pids.h" #include "ovms_notify.h" #include #include "metrics_standard.h" -// Vehicle states: -#define STATE_OFF 0 // Pollstate 0 - POLLSTATE_OFF - car is off -#define STATE_ON 1 // Pollstate 1 - POLLSTATE_ON - car is on -#define STATE_RUNNING 2 // Pollstate 2 - POLLSTATE_RUNNING - car is driving -#define STATE_CHARGING 3 // Pollstate 3 - POLLSTATE_CHARGING - car is charging - -// RX buffer access macros: b=byte# -#define RXB_BYTE(b) m_rxbuf[b] -#define RXB_UINT16(b) (((uint16_t)RXB_BYTE(b) << 8) | RXB_BYTE(b+1)) -#define RXB_UINT24(b) (((uint32_t)RXB_BYTE(b) << 16) | ((uint32_t)RXB_BYTE(b+1) << 8) \ - | RXB_BYTE(b+2)) -#define RXB_UINT32(b) (((uint32_t)RXB_BYTE(b) << 24) | ((uint32_t)RXB_BYTE(b+1) << 16) \ - | ((uint32_t)RXB_BYTE(b+2) << 8) | RXB_BYTE(b+3)) -#define RXB_INT8(b) ((int8_t)RXB_BYTE(b)) -#define RXB_INT16(b) ((int16_t)RXB_UINT16(b)) -#define RXB_INT32(b) ((int32_t)RXB_UINT32(b)) - -namespace -{ - -// The parameter namespace for this vehicle -const char PARAM_NAME[] = "xme"; - -static const OvmsPoller::poll_pid_t obdii_polls[] = - { - // VCU Polls -// { vcutx, vcurx, VEHICLE_POLL_TYPE_OBDIIEXTENDED, vcusoc, { 0, 0, 30, 30 }, 0, ISOTP_STD }, //SOC Scaled below - { vcutx, vcurx, VEHICLE_POLL_TYPE_OBDIIEXTENDED, vcutemp1, { 0, 0, 30, 30 }, 0, ISOTP_STD }, //temp - { vcutx, vcurx, VEHICLE_POLL_TYPE_OBDIIEXTENDED, vcutemp2, { 0, 0, 30, 30 }, 0, ISOTP_STD }, //temp - { vcutx, vcurx, VEHICLE_POLL_TYPE_OBDIIEXTENDED, vcuspeed, { 0, 0, 1, 30 }, 0, ISOTP_STD }, //speed in KM (maybe cruise setpoint) - { vcutx, vcurx, VEHICLE_POLL_TYPE_OBDIIEXTENDED, vcupackvolts, { 0, 0, 30, 30 }, 0, ISOTP_STD }, //Pack Voltage - { vcutx, vcurx, VEHICLE_POLL_TYPE_OBDIIEXTENDED, vcu12vamps, { 0, 0, 30, 30 }, 0, ISOTP_STD }, //12v amps? - { vcutx, vcurx, VEHICLE_POLL_TYPE_OBDIIEXTENDED, vcuchargervolts, { 0, 0, 15, 15 }, 0, ISOTP_STD }, //charger volts at a guess? -// { vcutx, vcurx, VEHICLE_POLL_TYPE_OBDIIEXTENDED, vcuchargeramps, { 0, 0, 5, 5 }, 0, ISOTP_STD }, //charger amps? - // BMS Polls - { bmstx, bmsrx, VEHICLE_POLL_TYPE_OBDIIEXTENDED, bmsStatusPid, { 0, 5, 5, 5 }, 0, ISOTP_STD }, //bms charger state??? - { bmstx, bmsrx, VEHICLE_POLL_TYPE_OBDIIEXTENDED, cellvolts, { 0, 0, 15, 15 }, 0, ISOTP_STD }, //cell volts - { bmstx, bmsrx, VEHICLE_POLL_TYPE_OBDIIEXTENDED, celltemps, { 0, 0, 15, 15 }, 0, ISOTP_STD }, //cell temps - { bmstx, bmsrx, VEHICLE_POLL_TYPE_OBDIIEXTENDED, bmssoc, { 0, 0, 30, 30 }, 0, ISOTP_STD }, //bms SOC - { bmstx, bmsrx, VEHICLE_POLL_TYPE_OBDIIEXTENDED, bmssoh, { 0, 0, 30, 30 }, 0, ISOTP_STD }, //bms SOH?? - { bmstx, bmsrx, VEHICLE_POLL_TYPE_OBDIIEXTENDED, bmssocraw, { 0, 0, 30, 30 }, 0, ISOTP_STD }, //bms raw SOC -// { bmstx, bmsrx, VEHICLE_POLL_TYPE_OBDIIEXTENDED, packamps, { 0, 0, 30, 30 }, 0, ISOTP_STD }, //bms hv amps to pack - { bmstx, bmsrx, VEHICLE_POLL_TYPE_OBDIIEXTENDED, bmsccsamps, { 0, 0, 15, 15 }, 0, ISOTP_STD }, // looks CCS state - { bmstx, bmsrx, VEHICLE_POLL_TYPE_OBDIIEXTENDED, bmsacamps, { 0, 0, 15, 15 }, 0, ISOTP_STD }, // looks CCS state -// { bmstx, bmsrx, VEHICLE_POLL_TYPE_OBDIIEXTENDED, bmsccschargeon, { 0, 0, 15, 15 }, 0, ISOTP_STD }, // looks CCS state -// { bmstx, bmsrx, VEHICLE_POLL_TYPE_OBDIIEXTENDED, bmsacchargeon, { 0, 0, 15, 15 }, 0, ISOTP_STD }, // looks CCS state - { 0, 0, 0x00, 0x00, { 0, 0, 0, 0 }, 0, 0 } - }; -charging_profile granny_steps[] = { - {0,98,6375}, // Max charge rate (7200) less charge loss - {98,100,2700}, // Observed charge rate - {0,0,0}, - }; - -charging_profile ccs_steps[] = { - {0,20,75000}, - {20,30,67000}, - {30,40,59000}, - {40,50,50000}, - {50,60,44000}, - {60,80,37000}, - {80,83,26600}, - {83,95,16200}, - {95,100,5700}, - {0,0,0}, -}; +// CAN buffer access macros: b=byte# 0..7 / n=nibble# 0..15 +#define CAN_BYTE(b) data[b] +#define CAN_INT(b) ((int16_t)CAN_UINT(b)) +#define CAN_UINT(b) (((UINT)CAN_BYTE(b) << 8) | CAN_BYTE(b+1)) +#define CAN_UINT24(b) (((uint32_t)CAN_BYTE(b) << 16) | ((UINT)CAN_BYTE(b+1) << 8) | CAN_BYTE(b+2)) +#define CAN_UINT32(b) (((uint32_t)CAN_BYTE(b) << 24) | ((uint32_t)CAN_BYTE(b+1) << 16) | ((UINT)CAN_BYTE(b+2) << 8) | CAN_BYTE(b+3)) +#define CAN_NIBL(b) (can_databuffer[b] & 0x0f) +#define CAN_NIBH(b) (can_databuffer[b] >> 4) +#define CAN_NIB(n) (((n)&1) ? CAN_NIBL((n)>>1) : CAN_NIBH((n)>>1)) +#define CAN_BIT(b,pos) !!(data[b] & (1<<(pos))) -// Responses to the BMS Status PID -enum BmsStatus : unsigned char { - Off = 0x0, // Seen when connected but not locked - Idle = 0x1, // When the car does not have the ignition on - CcsCharging = 0x2, // When charging on a rapid CCS charger - Charging = 0x3, // When charging normally - Running = 0x4, // When the ignition is on aux or running -// AboutToSleep = 0x8, // Seen just before going to sleep -// Connected = 0xa, // Connected but not charging -// StartingCharge = 0xc // Seen when the charge was about to start -}; - -} // anon namespace - -// OvmsVehicleMaxe6 constructor - OvmsVehicleMaxe6::OvmsVehicleMaxe6() - { - ESP_LOGI(TAG, "Start Maxus Euniq 6 vehicle module"); - - // Init CAN: - RegisterCanBus(1,CAN_MODE_ACTIVE,CAN_SPEED_500KBPS); - - // Init BMS: - BmsSetCellArrangementVoltage(96, 16); - BmsSetCellArrangementTemperature(16, 1); - BmsSetCellLimitsVoltage(2.0, 5.0); - BmsSetCellLimitsTemperature(-39, 200); - BmsSetCellDefaultThresholdsVoltage(0.020, 0.030); - BmsSetCellDefaultThresholdsTemperature(2.0, 3.0); - - // Init polling: - PollSetThrottling(0); - PollSetResponseSeparationTime(1); - PollSetState(STATE_OFF); - PollSetPidList(m_can1, obdii_polls); - - // Init VIN: - memset(m_vin, 0, sizeof(m_vin)); - - // Init Raw Soc: - m_poll_state_metric = MyMetrics.InitInt("xme.state.poll", SM_STALE_MAX, m_poll_state); - m_soc_raw = MyMetrics.InitFloat("xme.v.soc.raw", 0, SM_STALE_HIGH, Percentage); - m_consump_raw = MyMetrics.InitFloat("xme.v.consump.raw", 0, SM_STALE_HIGH); // temp to monitor bms range - m_consumprange_raw = MyMetrics.InitFloat("xme.v.consumprange.raw", 0, SM_STALE_HIGH); // temp to monitor bms range - m_watt_hour_raw = MyMetrics.InitFloat("xme.v.watt.hour.raw", 0, SM_STALE_HIGH); // temp to monitor bms range - m_poll_bmsstate = MyMetrics.InitFloat("xme.bmsstate.poll", SM_STALE_HIGH); //temp to monitor bms state - - // Register config params - MyConfig.RegisterParam("xme", "Maxus EV configuration", true, true); - - - // Init Energy: - StdMetrics.ms_v_charge_mode->SetValue("standard"); - StdMetrics.ms_v_env_ctrl_login->SetValue(true); - me56_cum_energy_charge_wh = 0; - } - -//OvmsVehicleMaxe6 destructor - -OvmsVehicleMaxe6::~OvmsVehicleMaxe6() - { - ESP_LOGI(TAG, "Stop Euniq 6 vehicle module"); - PollSetPidList(m_can1, NULL); - } - -// IncomingPollReply: - -void OvmsVehicleMaxe6::IncomingPollReply(const OvmsPoller::poll_job_t &job, uint8_t* data, uint8_t length) -{ - // init / fill rx buffer: - if (job.mlframe == 0) { - m_rxbuf.clear(); - m_rxbuf.reserve(length + job.mlremain); + { + ESP_LOGI(TAG, "Start Maxus Euniq 6 vehicle module"); + + // Init CAN: + RegisterCanBus(1,CAN_MODE_ACTIVE,CAN_SPEED_500KBPS); + + // Init CAN buffer: + send_can_buffer.id = 0; + send_can_buffer.status = 0; + memset(send_can_buffer.byte, 0, sizeof(send_can_buffer.byte)); + + // Init BMS: + BmsSetCellArrangementVoltage(96, 16); + BmsSetCellArrangementTemperature(16, 1); + BmsSetCellLimitsVoltage(2.0, 5.0); + BmsSetCellLimitsTemperature(-39, 200); + BmsSetCellDefaultThresholdsVoltage(0.020, 0.030); + BmsSetCellDefaultThresholdsTemperature(2.0, 3.0); + + // Init Energy: + StdMetrics.ms_v_charge_mode->SetValue("standard"); + StdMetrics.ms_v_env_ctrl_login->SetValue(true); + + // Require GPS: + MyEvents.SignalEvent("vehicle.require.gps", NULL); + MyEvents.SignalEvent("vehicle.require.gpstime", NULL); } - m_rxbuf.append((char*)data, length); - if (job.mlremain) - return; - // response complete: - ESP_LOGV(TAG, "IncomingPollReply: PID %02X: len=%d %s", job.pid, m_rxbuf.size(), hexencode(m_rxbuf).c_str()); - - int value1 = (int)data[0]; - int value2 = ((int)data[0] << 8) + (int)data[1]; - - switch (job.pid) +OvmsVehicleMaxe6::~OvmsVehicleMaxe6() { - case vcuvin: // VIN - StdMetrics.ms_v_vin->SetValue(m_rxbuf); - break; - case bmsStatusPid: - SetBmsStatus(data[0]); - m_poll_bmsstate->SetValue(value1); - break; - - // set status to on StdMetrics.ms_v_env_on->SetValue(bool( d[7] & 0x10 )); - case bmssoh: //soh - StdMetrics.ms_v_bat_soh->SetValue(value1); - break; - case bmssoc: //soc from bms - StdMetrics.ms_v_bat_soc->SetValue(value2 / 100.0f); - if(StdMetrics.ms_v_bat_soc->AsFloat() >=99.35)StdMetrics.ms_v_bat_soc->SetValue(100.0f); - break; - - case bmssocraw: //soc from bms - m_soc_raw->SetValue(value2 / 100.0f); - break; - case vcutemp1: // temperature?? - StdMetrics.ms_v_mot_temp->SetValue(value1 / 10.0f); - break; - case vcutemp2: // temperature?? - StdMetrics.ms_v_env_temp->SetValue(value1 / 10.0f); - break; - case vcuspeed: // Speed in Km - { - vanIsOn = StdMetrics.ms_v_env_on->AsBool(); - if (vanIsOn) - StdMetrics.ms_v_pos_speed->SetValue(value1); // in km - else - StdMetrics.ms_v_pos_speed->SetValue(0); - } - break; - case vcupackvolts: // Pack Voltage - StdMetrics.ms_v_bat_voltage->SetValue(value2 / 10.0f); - break; - - - case bmsccsamps: - if (StdMetrics.ms_v_charge_type->AsString() == "ccs") - { - StdMetrics.ms_v_bat_current->SetValue((value2 / 10.0f) - ((value2 / 10.0f) * 2)); // converted to negative - StdMetrics.ms_v_bat_power->SetValue((((value2 / 10.0f) - ((value2 / 10.0f) * 2)) * StdMetrics.ms_v_bat_voltage->AsFloat()) / 1000.0f);// converted to negtive - } - break; - - case bmsacamps: - if (StdMetrics.ms_v_charge_type->AsString() == "type2") - { - StdMetrics.ms_v_bat_current->SetValue((StdMetrics.ms_v_bat_power->AsFloat() * 1000) / StdMetrics.ms_v_bat_voltage->AsFloat() ); // - - // - StdMetrics.ms_v_charge_current->SetValue((value2 *2) / 10.0f); - } - - break; - - case vcu12vamps: - StdMetrics.ms_v_bat_12v_current->SetValue(value1 / 10.0f); - break; - case vcuchargervolts: - if (StdMetrics.ms_v_charge_type->AsString() == "type2") - { - StdMetrics.ms_v_charge_voltage->SetValue(value2 - 16140); // possible but always 224 untill found only - } - break; - - case cellvolts: - { - // Read battery cell voltages 1-96: - BmsRestartCellVoltages(); - for (int i = 0; i < 96; i++) - { - BmsSetCellVoltage(i, RXB_UINT16(i*2) * 0.001f); - } - break; - } - case celltemps: - { - // Read battery cell temperatures 1-20: - BmsRestartCellTemperatures(); - for (int i = 0; i < 20; i++) - { - BmsSetCellTemperature(i, RXB_UINT16(i*2) * 0.001f); - } - break; - } - - default: - { - ESP_LOGW(TAG, "IncomingPollReply: unhandled PID %02X: len=%d %s", job.pid, m_rxbuf.size(), hexencode(m_rxbuf).c_str()); - } + ESP_LOGI(TAG, "Stop Euniq 6 vehicle module"); } -} -void OvmsVehicleMaxe6::SetBmsStatus(uint8_t status) +void OvmsVehicleMaxe6::IncomingFrameCan1(CAN_frame_t *p_frame) { - switch (status) { -// case StartingCharge: - case Charging: - StdMetrics.ms_v_charge_type->SetValue("type2"); - StdMetrics.ms_v_door_chargeport->SetValue(true); - StdMetrics.ms_v_charge_pilot->SetValue(true); - StdMetrics.ms_v_charge_inprogress->SetValue(true); - //StdMetrics.ms_v_charge_substate->SetValue("onrequest"); - StdMetrics.ms_v_charge_state->SetValue("charging"); - StdMetrics.ms_v_charge_climit->SetValue(StdMetrics.ms_v_charge_current->AsFloat()); - StdMetrics.ms_v_charge_power->SetValue((StdMetrics.ms_v_charge_current->AsFloat() * StdMetrics.ms_v_charge_voltage->AsFloat()) / 1000); - PollSetState(STATE_CHARGING); - - break; - case CcsCharging: - StdMetrics.ms_v_charge_type->SetValue("ccs"); - StdMetrics.ms_v_door_chargeport->SetValue(true); - StdMetrics.ms_v_charge_pilot->SetValue(true); - StdMetrics.ms_v_charge_inprogress->SetValue(true); - StdMetrics.ms_v_charge_state->SetValue("charging"); - //These are added while CCS charging, EVCC won't show up so we set these here - StdMetrics.ms_v_charge_current->SetValue(-StdMetrics.ms_v_bat_current->AsFloat()); - StdMetrics.ms_v_charge_power->SetValue(-StdMetrics.ms_v_bat_power->AsFloat()); - StdMetrics.ms_v_charge_climit->SetValue(-StdMetrics.ms_v_bat_current->AsFloat()); - StdMetrics.ms_v_charge_voltage->SetValue(StdMetrics.ms_v_bat_voltage->AsFloat()); - PollSetState(STATE_CHARGING); - break; - case Running: - StdMetrics.ms_v_env_on->SetValue(true); - StdMetrics.ms_v_charge_pilot->SetValue(false); - StdMetrics.ms_v_charge_inprogress->SetValue(false); - StdMetrics.ms_v_door_chargeport->SetValue(false); - StdMetrics.ms_v_charge_type->SetValue(""); - PollSetState(STATE_RUNNING); - break; - default: - StdMetrics.ms_v_charge_pilot->SetValue(false); - StdMetrics.ms_v_charge_inprogress->SetValue(false); - StdMetrics.ms_v_door_chargeport->SetValue(false); - StdMetrics.ms_v_charge_type->SetValue(""); - StdMetrics.ms_v_charge_state->SetValue(""); - /* if (!StdMetrics.ms_v_charge_inprogress->AsBool()) - { - StdMetrics.ms_v_bat_current->SetValue(0); - StdMetrics.ms_v_bat_power->SetValue(0); - - } */ - break; - } -} - - - -// Can Frames - -void OvmsVehicleMaxe6::IncomingFrameCan1(CAN_frame_t* p_frame) - { - -//set batt temp - StdMetrics.ms_v_bat_temp->SetValue(StdMetrics.ms_v_bat_pack_tavg->AsFloat()); - - uint8_t *d = p_frame->data.u8; - switch (p_frame->MsgID) - { - case 0x6f2: // broadcast - { - //Set ideal, est when CANdata received - float soc = StdMetrics.ms_v_bat_soc->AsFloat(); - // Setup Calculates for Efficient Range - float batTemp = StdMetrics.ms_v_bat_temp->AsFloat(); - float effSoh = StdMetrics.ms_v_bat_soh->AsFloat(); - float kwhPerKm = 1000/(consumpRange * 59 + consumpRange) / 60; - float kmPerKwh = (1000/kwhPerKm) * 1.609; - //float kmPerKwhAvg = (kmPerKwh * 59 + kmPerKwh) / 60; - m_watt_hour_raw->SetValue(kmPerKwh); - m_consumprange_raw->SetValue(kwhPerKm); - m_consump_raw->SetValue(consumpRange); - - if(kmPerKwh<4.5)kmPerKwh=4.5; - if(kmPerKwh>6.4)kmPerKwh=6.6; - if(batTemp>20)batTemp=20; - - StdMetrics.ms_v_bat_range_full->SetValue(360); - StdMetrics.ms_v_bat_range_ideal->SetValue(360 * soc / 100); - //StdMetrics.ms_v_bat_range_est->SetValue(360 * soc / 108); - StdMetrics.ms_v_bat_range_est->SetValue(72.7*((kmPerKwh * (1-((20-batTemp)*1.3)/100)*(soc/100))*(effSoh/100))); - - break; - } - default: - break; - - case 0x540: // odometer in KM - { - StdMetrics.ms_v_pos_odometer->SetValue(d[0] << 16 | d[1] << 8 | d[2]);// odometer - break; - } - - case 0x389: // charger or battery temp - { - float invtemp = d[1]; - StdMetrics.ms_v_inv_temp->SetValue(invtemp / 10); - break; - } - - case 0x604: // actual power to HV Battery ( does not work on ccs and maybe ac?\) - { - // hvpower = d[5]; - // float hvbatpower = (hvpower * 42 / 1000); - // StdMetrics.ms_v_bat_power->SetValue(-hvbatpower); - break; - } - } + uint8_t *d = p_frame->data.u8; + + // Check if response is from synchronous can message + if (send_can_buffer.status == 0xff && p_frame->MsgID == (send_can_buffer.id + 0x08)) + { + // Store message bytes so that the async method can continue + send_can_buffer.status = 3; + + send_can_buffer.byte[0] = d[0]; + send_can_buffer.byte[1] = d[1]; + send_can_buffer.byte[2] = d[2]; + send_can_buffer.byte[3] = d[3]; + send_can_buffer.byte[4] = d[4]; + send_can_buffer.byte[5] = d[5]; + send_can_buffer.byte[6] = d[6]; + send_can_buffer.byte[7] = d[7]; + } + + /* + BASIC METRICS + StdMetrics.ms_v_pos_speed ok + StdMetrics.ms_v_bat_soc ok + StdMetrics.ms_v_pos_odometer ok + + StdMetrics.ms_v_door_fl ok; yes when open, no when closed + StdMetrics.ms_v_door_fr ok + StdMetrics.ms_v_door_rl ok + StdMetrics.ms_v_door_rr ok + StdMetrics.ms_v_trunk ok + StdMetrics.ms_v_env_locked ok + + StdMetrics.ms_v_env_onepedal - + StdMetrics.ms_v_env_efficiencymode - + StdMetrics.ms_v_env_regenlevel Percentage - + + StdMetrics.ms_v_bat_current - + StdMetrics.ms_v_bat_voltage - + StdMetrics.ms_v_bat_power wip esta en porcentaje + + StdMetrics.ms_v_charge_inprogress ok + + StdMetrics.ms_v_env_on ok + StdMetrics.ms_v_env_awake ok + + StdMetrics.ms_v_env_aux12v ok + + StdMetrics.ms_v_tpms_pressure->SetElemValue(MS_V_TPMS_IDX_FL, value, PSI); + StdMetrics.ms_v_tpms_pressure->SetElemValue(MS_V_TPMS_IDX_FR, value, PSI); + StdMetrics.ms_v_tpms_pressure->SetElemValue(MS_V_TPMS_IDX_RL, value, PSI); + StdMetrics.ms_v_tpms_pressure->SetElemValue(MS_V_TPMS_IDX_RR, value, PSI); + */ + + uint8_t *data = p_frame->data.u8; + + switch (p_frame->MsgID) + { + case 0x0c9: + { + StdMetrics.ms_v_charge_inprogress->SetValue( + CAN_BIT(2,0) && CAN_BIT(2,1) && CAN_BIT(2,2) + ); + break; + } + case 0x281: + { + StdMetrics.ms_v_env_locked->SetValue( + CAN_BIT(1,0) && CAN_BIT(1,2) && CAN_BIT(1,4) && CAN_BIT(1,6) && + !StdMetrics.ms_v_door_fl->AsBool() && + !StdMetrics.ms_v_door_fr->AsBool() && + !StdMetrics.ms_v_door_rl->AsBool() && + !StdMetrics.ms_v_door_rr->AsBool() && + !StdMetrics.ms_v_door_trunk->AsBool()); + break; + } + case 0x46a: + { + StdMetrics.ms_v_door_fl->SetValue(CAN_BIT(0, 0)); + StdMetrics.ms_v_door_fr->SetValue(CAN_BIT(0, 3)); + StdMetrics.ms_v_door_rr->SetValue(CAN_BIT(0, 5)); + StdMetrics.ms_v_door_rl->SetValue(CAN_BIT(0, 7)); + StdMetrics.ms_v_door_trunk->SetValue(CAN_BIT(1, 1)); + break; + } + case 0x540: + { + StdMetrics.ms_v_pos_odometer->SetValue(CAN_UINT24(0)); + break; + } + case 0x6f0: + { + StdMetrics.ms_v_pos_speed->SetValue(CAN_BYTE(4)); + break; + } + case 0x6f1: + { + StdMetrics.ms_v_env_awake->SetValue(CAN_BIT(4,7)); + StdMetrics.ms_v_env_on->SetValue(CAN_BIT(1,4) && CAN_BIT(4,7)); + break; + } + case 0x6f2: + { + StdMetrics.ms_v_bat_soc->SetValue(CAN_BYTE(1)); + StdMetrics.ms_v_bat_power->SetValue((CAN_BYTE(2) - 100) * 120, kW); // es porcentaje + break; + } + default: + break; + } } void OvmsVehicleMaxe6::Ticker1(uint32_t ticker) { - processEnergy(); -} - -// PollerStateTicker: framework callback: check for state changes -// This is called by VehicleTicker1() just before the next PollerSend(). - -void OvmsVehicleMaxe6::PollerStateTicker(canbus *bus) -{ - bool charging12v = StdMetrics.ms_v_env_charging12v->AsBool(); - StdMetrics.ms_v_env_charging12v->SetValue(StdMetrics.ms_v_bat_12v_voltage->AsFloat() >= 12.9); - //StdMetrics.ms_v_charge_inprogress->SetValue(-StdMetrics.ms_v_bat_power->AsFloat() >= 1.000f); - m_poll_state_metric->SetValue(m_poll_state); - - // Determine new polling state: - // int poll_state; - if (charging12v) - { - // poll_state = STATE_ON; - PollSetState(STATE_ON); - StdMetrics.ms_v_env_awake->SetValue(true); - } - else - { - // poll_state = STATE_OFF; - PollSetState(STATE_OFF); - StdMetrics.ms_v_env_awake->SetValue(false); - } -} - -// Vehicle framework registration - -void OvmsVehicleMaxe6::processEnergy() -{ - // When called each to battery power for a second is calculated. - // This is added to ms_v_bat_energy_recd if regenerating or - // ms_v_bat_energy_used if power is being drawn from the battery - - // Only calculate if the car is turned on and not charging. - if (StdMetrics.ms_v_env_awake->AsBool() && - !StdMetrics.ms_v_charge_inprogress->AsBool()) { - // Are we in READY state? Ready to drive off. - if (StdMetrics.ms_v_env_on->AsBool()) { - auto bat_power = StdMetrics.ms_v_bat_power->AsFloat(); - // Calculate battery power (kW) for one second - auto energy = bat_power / 3600.0; - // Calculate current (A) used for one second. - auto coulombs = (StdMetrics.ms_v_bat_current->AsFloat() / 3600.0); - // Car is still parked so trip has not started. - // Set all values to zero - if (StdMetrics.ms_v_env_drivetime->AsInt() == 0) { - ESP_LOGI(TAG, "Trip has started"); - StdMetrics.ms_v_bat_coulomb_used->SetValue(0); - StdMetrics.ms_v_bat_coulomb_recd->SetValue(0); - StdMetrics.ms_v_bat_energy_used->SetValue(0); - StdMetrics.ms_v_bat_energy_recd->SetValue(0); - // Otherwise we are already moving so do calculations - } - else - { - // Calculate regeneration power - if (bat_power < 0) { - StdMetrics.ms_v_bat_energy_recd->SetValue - (StdMetrics.ms_v_bat_energy_recd->AsFloat() + -(energy)); - - StdMetrics.ms_v_bat_coulomb_recd->SetValue - (StdMetrics.ms_v_bat_coulomb_recd->AsFloat() + -(coulombs)); - - // Calculate power usage. Add power used each second - } - else - { - StdMetrics.ms_v_bat_energy_used->SetValue - (StdMetrics.ms_v_bat_energy_used->AsFloat() + energy); - - StdMetrics.ms_v_bat_coulomb_used->SetValue - (StdMetrics.ms_v_bat_coulomb_used->AsFloat() + coulombs); - } - } - } - // Not in READY so must have been turned off - else - { - // We have only just stopped so add trip values to the totals - if (StdMetrics.ms_v_env_parktime->AsInt() == 0) { - ESP_LOGI(TAG, "Trip has ended"); - StdMetrics.ms_v_bat_energy_used_total->SetValue - (StdMetrics.ms_v_bat_energy_used_total->AsFloat() - + StdMetrics.ms_v_bat_energy_used->AsFloat()); - - StdMetrics.ms_v_bat_energy_recd_total->SetValue - (StdMetrics.ms_v_bat_energy_recd_total->AsFloat() - + StdMetrics.ms_v_bat_energy_recd->AsFloat()); - - StdMetrics.ms_v_bat_coulomb_used_total->SetValue - (StdMetrics.ms_v_bat_coulomb_used_total->AsFloat() - + StdMetrics.ms_v_bat_coulomb_used->AsFloat()); - - StdMetrics.ms_v_bat_coulomb_recd_total->SetValue - (StdMetrics.ms_v_bat_coulomb_recd_total->AsFloat() - + StdMetrics.ms_v_bat_coulomb_recd->AsFloat()); - } - } - } - - // Add cumulative charge energy each second to ms_v_charge_power - if(StdMetrics.ms_v_charge_inprogress->AsBool()) - { - me56_cum_energy_charge_wh += StdMetrics.ms_v_charge_power->AsFloat()*1000/3600; - StdMetrics.ms_v_charge_kwh->SetValue(me56_cum_energy_charge_wh/1000); -// me56_cum_energy_charge_wh += StdMetrics.ms_v_charge_power->AsFloat()/3600; -// StdMetrics.ms_v_charge_kwh->SetValue((me56_cum_energy_charge_wh/1000) * 1.609f); - - int limit_soc = StdMetrics.ms_v_charge_limit_soc->AsInt(0); - float limit_range = StdMetrics.ms_v_charge_limit_range->AsFloat(0, Kilometers); - float max_range = StdMetrics.ms_v_bat_range_full->AsFloat(0, Kilometers); - - // Calculate time to reach 100% charge - int minsremaining_full = StdMetrics.ms_v_charge_type->AsString() == "ccs" ? calcMinutesRemaining(100, ccs_steps) : calcMinutesRemaining(100, granny_steps); - StdMetrics.ms_v_charge_duration_full->SetValue(minsremaining_full); - ESP_LOGV(TAG, "Time remaining: %d mins to full", minsremaining_full); - - // Calculate time to charge to SoC Limit - if (limit_soc > 0) - { - // if limit_soc is set, then calculate remaining time to limit_soc - int minsremaining_soc = StdMetrics.ms_v_charge_type->AsString() == "ccs" ? calcMinutesRemaining(limit_soc, ccs_steps) : calcMinutesRemaining(limit_soc, granny_steps); - StdMetrics.ms_v_charge_duration_soc->SetValue(minsremaining_soc, Minutes); - if ( minsremaining_soc == 0 && !soc_limit_reached && limit_soc >= StdMetrics.ms_v_bat_soc->AsFloat(100)) - { - MyNotify.NotifyStringf("info", "charge.limit.soc", "Charge limit of %d%% reached", limit_soc); - soc_limit_reached = true; - } - ESP_LOGV(TAG, "Time remaining: %d mins to %d%% soc", minsremaining_soc, limit_soc); - } - - // Calculate time to charge to Range Limit - if (limit_range > 0.0 && max_range > 0.0) - { - // if range limit is set, then compute required soc and then calculate remaining time to that soc - int range_soc = limit_range / max_range * 100.0; - int minsremaining_range = StdMetrics.ms_v_charge_type->AsString() == "ccs" ? calcMinutesRemaining(range_soc, ccs_steps) : calcMinutesRemaining(range_soc, granny_steps); - StdMetrics.ms_v_charge_duration_range->SetValue(minsremaining_range, Minutes); - if ( minsremaining_range == 0 && !range_limit_reached && range_soc >= StdMetrics.ms_v_bat_soc->AsFloat(100)) - { - MyNotify.NotifyStringf("info", "charge.limit.range", "Charge limit of %dkm reached", (int) limit_range); - range_limit_reached = true; - } - ESP_LOGV(TAG, "Time remaining: %d mins for %0.0f km (%d%% soc)", minsremaining_range, limit_range, range_soc); - } - // When we are not charging set back to zero ready for next charge. - } - else - { - me56_cum_energy_charge_wh=0; - StdMetrics.ms_v_charge_duration_full->SetValue(0); - StdMetrics.ms_v_charge_duration_soc->SetValue(0); - StdMetrics.ms_v_charge_duration_range->SetValue(0); - soc_limit_reached = false; - range_limit_reached = false; - } -} - -// Calculate the time to reach the Target and return in minutes -int OvmsVehicleMaxe6::calcMinutesRemaining(int toSoc, charging_profile charge_steps[]) -{ - - int minutes = 0; - int percents_In_Step; - int fromSoc = StdMetrics.ms_v_bat_soc->AsInt(100); - int batterySize = 72700; - float chargespeed = -StdMetrics.ms_v_bat_power->AsFloat() * 1000; - - for (int i = 0; charge_steps[i].toPercent != 0; i++) { - if (charge_steps[i].toPercent > fromSoc && charge_steps[i].fromPercenttoSoc ? toSoc : charge_steps[i].toPercent) - (charge_steps[i].fromPercentAsFloat() >= 5) //temp removed till speed found - //if (StdMetrics.ms_v_env_on->AsBool()) //Temp till speed found - consumption = ABS(StdMetrics.ms_v_bat_power->AsFloat(0, Watts)) / StdMetrics.ms_v_pos_speed->AsFloat(); - StdMetrics.ms_v_bat_consumption->SetValue((StdMetrics.ms_v_bat_consumption->AsFloat() * 29 + consumption) / 30); - consumpRange = ABS(StdMetrics.ms_v_bat_consumption->AsFloat()); - - - } - -//Called by OVMS when a config param is changed -void OvmsVehicleMaxe6::ConfigChanged(OvmsConfigParam* param) -{ - if (param && param->GetName() != PARAM_NAME) - { - return; - } - - ESP_LOGI(TAG, "%s config changed", PARAM_NAME); - - // Instances: - // xme - // suffsoc Sufficient SOC [%] (Default: 0=disabled) - // suffrange Sufficient range [km] (Default: 0=disabled) - StdMetrics.ms_v_charge_limit_soc->SetValue( - (float) MyConfig.GetParamValueInt("xme", "suffsoc"), Percentage ); - - if (MyConfig.GetParamValue("vehicle", "units.distance") == "K") - { - StdMetrics.ms_v_charge_limit_range->SetValue( - (float) MyConfig.GetParamValueInt("xme", "suffrange"), Kilometers ); - } - else - { - StdMetrics.ms_v_charge_limit_range->SetValue( - (float) MyConfig.GetParamValueInt("xme", "suffrange"), Miles ); - } } class OvmsVehicleMaxe6Init diff --git a/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.h b/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.h index def0e6ac7..7cd27201b 100644 --- a/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.h +++ b/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.h @@ -40,57 +40,24 @@ using namespace std; -typedef struct{ - int fromPercent; - int toPercent; - float maxChargeSpeed; -}charging_profile; - -class OvmsCommand; - class OvmsVehicleMaxe6 : public OvmsVehicle { public: + OvmsVehicleMaxe6(); ~OvmsVehicleMaxe6(); - - OvmsMetricInt *m_poll_state_metric; // Kept equal to m_poll_state for debugging purposes - OvmsMetricFloat* m_soc_raw; - OvmsMetricFloat* m_watt_hour_raw; - OvmsMetricFloat* m_consump_raw; - OvmsMetricFloat* m_consumprange_raw; - OvmsMetricFloat* m_poll_bmsstate; protected: - std::string m_rxbuf; - - - protected: - void ConfigChanged(OvmsConfigParam* param) override; - void PollerStateTicker(canbus *bus); - void Ticker1(uint32_t ticker) override; - void IncomingPollReply(const OvmsPoller::poll_job_t &job, uint8_t* data, uint8_t length) override; - void processEnergy(); - float consumpRange; - float hvpower; - char m_vin[17]; + void Ticker1(uint32_t ticker) override; private: - void IncomingFrameCan1(CAN_frame_t* p_frame) override; - void IncomingPollFrame(CAN_frame_t* frame); - void SetBmsStatus(uint8_t status); - /// A temporary store for the VIN - - int calcMinutesRemaining(int toSoc, charging_profile charge_steps[]); - float me56_cum_energy_charge_wh; - bool soc_limit_reached; - bool range_limit_reached; - bool vanIsOn; - bool ccschargeon; - bool acchargeon; - - virtual void calculateEfficiency(); - + void IncomingFrameCan1(CAN_frame_t* p_frame) override; + + struct { + uint8_t byte[8]; + uint8_t status; + uint16_t id; + } send_can_buffer; }; #endif //#ifndef __VEHICLE_ME6_H__ From 13754bef766b54901a228d0fc8fa00783b6d6725 Mon Sep 17 00:00:00 2001 From: axel troncoso Date: Mon, 19 Aug 2024 11:05:50 -0400 Subject: [PATCH 10/45] Feat(support-for-door-status-on-maple) --- .../vehicle_maple60s/CMakeLists.txt | 13 ++ .../components/vehicle_maple60s/component.mk | 14 ++ .../vehicle_maple60s/docs/index.rst | 34 +++ .../src/vehicle_maple_60s.cpp | 218 ++++++++++++++++++ .../vehicle_maple60s/src/vehicle_maple_60s.h | 55 +++++ vehicle/OVMS.V3/main/Kconfig | 7 + 6 files changed, 341 insertions(+) create mode 100644 vehicle/OVMS.V3/components/vehicle_maple60s/CMakeLists.txt create mode 100644 vehicle/OVMS.V3/components/vehicle_maple60s/component.mk create mode 100644 vehicle/OVMS.V3/components/vehicle_maple60s/docs/index.rst create mode 100644 vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.cpp create mode 100644 vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.h diff --git a/vehicle/OVMS.V3/components/vehicle_maple60s/CMakeLists.txt b/vehicle/OVMS.V3/components/vehicle_maple60s/CMakeLists.txt new file mode 100644 index 000000000..445c99f7d --- /dev/null +++ b/vehicle/OVMS.V3/components/vehicle_maple60s/CMakeLists.txt @@ -0,0 +1,13 @@ +set(srcs) +set(include_dirs) + +if (CONFIG_OVMS_VEHICLE_MAPLE60S) + list(APPEND srcs "src/vehicle_maple60s.cpp") + list(APPEND include_dirs "src") +endif () + +# requirements can't depend on config +idf_component_register(SRCS ${srcs} + INCLUDE_DIRS ${include_dirs} + PRIV_REQUIRES "main" + WHOLE_ARCHIVE) \ No newline at end of file diff --git a/vehicle/OVMS.V3/components/vehicle_maple60s/component.mk b/vehicle/OVMS.V3/components/vehicle_maple60s/component.mk new file mode 100644 index 000000000..040f9e492 --- /dev/null +++ b/vehicle/OVMS.V3/components/vehicle_maple60s/component.mk @@ -0,0 +1,14 @@ +# +# Main component makefile. +# +# This Makefile can be left empty. By default, it will take the sources in the +# src/ directory, compile them and link them into lib(subdirectory_name).a +# in the build directory. This behaviour is entirely configurable, +# please read the ESP-IDF documents if you need to do this. +# + +ifdef CONFIG_OVMS_VEHICLE_MAPLE60S +COMPONENT_ADD_INCLUDEDIRS:=src +COMPONENT_SRCDIRS:=src +COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive +endif diff --git a/vehicle/OVMS.V3/components/vehicle_maple60s/docs/index.rst b/vehicle/OVMS.V3/components/vehicle_maple60s/docs/index.rst new file mode 100644 index 000000000..87e105e77 --- /dev/null +++ b/vehicle/OVMS.V3/components/vehicle_maple60s/docs/index.rst @@ -0,0 +1,34 @@ +======================= +Maple 60s +======================= + +Vehicle Type: **Maple 60a** + +The Maple 60s will be documented here. + +---------------- +Support Overview +---------------- + +=========================== ============== +Function Support Status +=========================== ============== +Hardware OVMS v3 (or later) +Vehicle Cable OBD-II to DB9 Data Cable for OVMS (1441200 right, or 1139300 left) +GSM Antenna 1000500 Open Vehicles OVMS GSM Antenna (or any compatible antenna) +GPS Antenna 1020200 Universal GPS Antenna (SMA Connector) (or any compatible antenna) +SOC Display Yes +Range Display Yes +GPS Location Yes (from modem module GPS) +Speed Display Yes +Temperature Display Yes (External Temp and Battery) +BMS v+t Display Yes +TPMS Display No +Charge Status Display Yes +Charge Interruption Alerts No +Charge Control No +Cabin Pre-heat/cool Control No +Lock/Unlock Vehicle Yes +Valet Mode Control No +Others +=========================== ============== diff --git a/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.cpp b/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.cpp new file mode 100644 index 000000000..438338a95 --- /dev/null +++ b/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.cpp @@ -0,0 +1,218 @@ +/* +; Project: Open Vehicle Monitor System +; Date: 16th August 2024 +; +; Changes: +; 1.0 Initial stub +; +; (C) 2024 Jaime Middleton / Tucar +; (C) 2024 Axel Troncoso / Tucar +; +; Permission is hereby granted, free of charge, to any person obtaining a copy +; of this software and associated documentation files (the "Software"), to deal +; in the Software without restriction, including without limitation the rights +; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +; copies of the Software, and to permit persons to whom the Software is +; furnished to do so, subject to the following conditions: +; +; The above copyright notice and this permission notice shall be included in +; all copies or substantial portions of the Software. +; +; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +; THE SOFTWARE. +*/ + +#include "vehicle_maple_60s.h" + +#include "metrics_standard.h" +#include "ovms_log.h" +#include "ovms_metrics.h" + +#define VERSION "0.0.1" + +static const char *TAG = "v-maple60s"; + +// CAN buffer access macros: b=byte# 0..7 / n=nibble# 0..15 +#define CAN_BYTE(b) data[b] +#define CAN_INT(b) ((int16_t)CAN_UINT(b)) +#define CAN_UINT(b) (((UINT)CAN_BYTE(b) << 8) | CAN_BYTE(b+1)) +#define CAN_UINT24(b) (((uint32_t)CAN_BYTE(b) << 16) | ((UINT)CAN_BYTE(b+1) << 8) | CAN_BYTE(b+2)) +#define CAN_UINT32(b) (((uint32_t)CAN_BYTE(b) << 24) | ((uint32_t)CAN_BYTE(b+1) << 16) | ((UINT)CAN_BYTE(b+2) << 8) | CAN_BYTE(b+3)) +#define CAN_NIBL(b) (can_databuffer[b] & 0x0f) +#define CAN_NIBH(b) (can_databuffer[b] >> 4) +#define CAN_NIB(n) (((n)&1) ? CAN_NIBL((n)>>1) : CAN_NIBH((n)>>1)) +#define CAN_BIT(b,pos) !!(data[b] & (1<<(pos))) + +OvmsVehicleMaple60S::OvmsVehicleMaple60S() +{ + ESP_LOGI(TAG, "Maple 60s vehicle module"); + + send_can_buffer.id = 0; + send_can_buffer.status = 0; + + memset(send_can_buffer.byte, 0, sizeof(send_can_buffer.byte)); + + StdMetrics.ms_v_bat_12v_voltage->SetValue(12.5, Volts); + StdMetrics.ms_v_charge_inprogress->SetValue(false); + StdMetrics.ms_v_env_on->SetValue(false); + StdMetrics.ms_v_bat_temp->SetValue(20, Celcius); + StdMetrics.ms_v_env_locked->SetValue(false); + + // Require GPS. + MyEvents.SignalEvent("vehicle.require.gps", NULL); + MyEvents.SignalEvent("vehicle.require.gpstime", NULL); + + RegisterCanBus(1, CAN_MODE_LISTEN, CAN_SPEED_500KBPS); +} + +/** + * Destructor + */ +OvmsVehicleMaple60S::~OvmsVehicleMaple60S() +{ + ESP_LOGI(TAG, "Shutdown Maple 60S vehicle module"); +} + +void OvmsVehicleMaple60S::Ticker1(uint32_t ticker) +{ +} + +void OvmsVehicleMaple60S::IncomingFrameCan1(CAN_frame_t *p_frame) +{ + uint8_t *d = p_frame->data.u8; + + // Check if response is from synchronous can message + if (send_can_buffer.status == 0xff && p_frame->MsgID == (send_can_buffer.id + 0x08)) + { + // Store message bytes so that the async method can continue + send_can_buffer.status = 3; + + send_can_buffer.byte[0] = d[0]; + send_can_buffer.byte[1] = d[1]; + send_can_buffer.byte[2] = d[2]; + send_can_buffer.byte[3] = d[3]; + send_can_buffer.byte[4] = d[4]; + send_can_buffer.byte[5] = d[5]; + send_can_buffer.byte[6] = d[6]; + send_can_buffer.byte[7] = d[7]; + } + + /* + BASIC METRICS + StdMetrics.ms_v_pos_speed ok + StdMetrics.ms_v_bat_soc ok + StdMetrics.ms_v_pos_odometer ok + + StdMetrics.ms_v_door_fl rev + StdMetrics.ms_v_door_fr rev + StdMetrics.ms_v_door_rl rev + StdMetrics.ms_v_door_rr rev + StdMetrics.ms_v_env_locked no + + StdMetrics.ms_v_env_onepedal NA + StdMetrics.ms_v_env_efficiencymode ok + StdMetrics.ms_v_env_regenlevel Percentage ok + + StdMetrics.ms_v_bat_current NA + StdMetrics.ms_v_bat_voltage NA + StdMetrics.ms_v_bat_power ok + + StdMetrics.ms_v_charge_inprogress rev + + StdMetrics.ms_v_env_on ok + StdMetrics.ms_v_env_awake ok + + StdMetrics.ms_v_env_aux12v rev + + StdMetrics.ms_v_tpms_pressure->SetElemValue(MS_V_TPMS_IDX_FL, value, PSI); + StdMetrics.ms_v_tpms_pressure->SetElemValue(MS_V_TPMS_IDX_FR, value, PSI); + StdMetrics.ms_v_tpms_pressure->SetElemValue(MS_V_TPMS_IDX_RL, value, PSI); + StdMetrics.ms_v_tpms_pressure->SetElemValue(MS_V_TPMS_IDX_RR, value, PSI); + */ + + uint8_t *data = p_frame->data.u8; + + switch (p_frame->MsgID) + { + case 0x250: + StdMetrics.ms_v_charge_inprogress->SetValue(CAN_BIT(7, 0)); + break; + // case 0x46a: + // StdMetrics.ms_v_door_fl->SetValue(CAN_BIT(0, 0)); + // StdMetrics.ms_v_door_fr->SetValue(CAN_BIT(0, 3)); + // StdMetrics.ms_v_door_rl->SetValue(CAN_BIT(0, 5)); + // StdMetrics.ms_v_door_rr->SetValue(CAN_BIT(0, 7)); + // StdMetrics.ms_v_door_trunk->SetValue(CAN_BIT(1, 1)); + // break; + case 0x3F1: + StdMetrics.ms_v_pos_odometer->SetValue(CAN_UINT24(0) / 10.0, Kilometers); + break; + case 0x125: + StdMetrics.ms_v_pos_speed->SetValue((CAN_BYTE(1) * 2) + (2 * (CAN_BYTE(2) - 1) / 250.0)); + break; + case 0x162: // awake, on, off and power + { + StdMetrics.ms_v_env_awake->SetValue(CAN_BIT(5, 0)); + StdMetrics.ms_v_env_on->SetValue(CAN_BIT(3, 7) && CAN_BIT(5, 0)); + StdMetrics.ms_v_bat_power->SetValue(CAN_BYTE(4) - 100); + + auto usingCcsCharger = StdMetrics.ms_v_bat_power->AsFloat(0, kW) < -15; + StdMetrics.ms_v_charge_type->SetValue(usingCcsCharger ? "ccs" : "type2"); + break; + } + case 0x2F4: // Charge state + StdMetrics.ms_v_bat_soc->SetValue((100 * CAN_BYTE(1)) / 255, Percentage); + break; + case 0x235: + StdMetrics.ms_v_env_aux12v->SetValue((CAN_BYTE(7) + 67)/15); + break; + case 0x284: + StdMetrics.ms_v_door_trunk->SetValue(CAN_BIT(1, 6)); + break; + case 0x285: + { + StdMetrics.ms_v_door_fl->SetValue(CAN_BIT(4, 8)); + StdMetrics.ms_v_door_rl->SetValue(CAN_BIT(4, 7)); + + auto fl_locked = static_cast(StdMetrics.ms_v_door_fl->AsBool(true)); + auto rl_locked = static_cast(StdMetrics.ms_v_door_rl->AsBool(true)); + auto fr_locked = static_cast(StdMetrics.ms_v_door_fr->AsBool(true)); + auto rr_locked = static_cast(StdMetrics.ms_v_door_rr->AsBool(true)); + + StdMetrics.ms_v_env_locked->SetValue( + fl_locked && rl_locked && fr_locked && rr_locked); + break; + } + case 0x286: + { + StdMetrics.ms_v_door_fr->SetValue(CAN_BIT(4, 8)); + StdMetrics.ms_v_door_rr->SetValue(CAN_BIT(4, 7)); + + auto fl_locked = static_cast(StdMetrics.ms_v_door_fl->AsBool(true)); + auto rl_locked = static_cast(StdMetrics.ms_v_door_rl->AsBool(true)); + auto fr_locked = static_cast(StdMetrics.ms_v_door_fr->AsBool(true)); + auto rr_locked = static_cast(StdMetrics.ms_v_door_rr->AsBool(true)); + + StdMetrics.ms_v_env_locked->SetValue( + fl_locked && rl_locked && fr_locked && rr_locked); + break; + } + } +} + +class OvmsVehicleMaple60SInit +{ +public: + OvmsVehicleMaple60SInit(); +} MyOvmsVehicleMaple60SInit __attribute__((init_priority(9000))); + +OvmsVehicleMaple60SInit::OvmsVehicleMaple60SInit() +{ + ESP_LOGI(TAG, "Registering Vehicle: Maple 60S (9000)"); + MyVehicleFactory.RegisterVehicle("MPL60S", "Maple 60S"); +} diff --git a/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.h b/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.h new file mode 100644 index 000000000..0fec83c21 --- /dev/null +++ b/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.h @@ -0,0 +1,55 @@ +/* +; Project: Open Vehicle Monitor System +; Date: 16th August 2024 +; +; Changes: +; 1.0 Initial stub +; +; (C) 2024 Jaime Middleton / Tucar +; (C) 2024 Axel Troncoso / Tucar +; +; Permission is hereby granted, free of charge, to any person obtaining a copy +; of this software and associated documentation files (the "Software"), to deal +; in the Software without restriction, including without limitation the rights +; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +; copies of the Software, and to permit persons to whom the Software is +; furnished to do so, subject to the following conditions: +; +; The above copyright notice and this permission notice shall be included in +; all copies or substantial portions of the Software. +; +; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +; THE SOFTWARE. +*/ + +#ifndef __VEHICLE_MAPLE60S_H__ +#define __VEHICLE_MAPLE60S_H__ + +#include "vehicle.h" + +using namespace std; + +class OvmsVehicleMaple60S : public OvmsVehicle + { + public: + OvmsVehicleMaple60S(); + ~OvmsVehicleMaple60S(); + + public: + void IncomingFrameCan1(CAN_frame_t *p_frame) override; + void Ticker1(uint32_t ticker) override; + + private: + struct { + uint8_t byte[8]; + uint8_t status; + uint16_t id; + } send_can_buffer; + }; + +#endif // #ifndef __VEHICLE_MAPLE60S_H__ \ No newline at end of file diff --git a/vehicle/OVMS.V3/main/Kconfig b/vehicle/OVMS.V3/main/Kconfig index e37cd6fab..83c8220c6 100644 --- a/vehicle/OVMS.V3/main/Kconfig +++ b/vehicle/OVMS.V3/main/Kconfig @@ -600,6 +600,13 @@ config OVMS_VEHICLE_BYD_ATTO3 depends on OVMS_COMP_POLLER help Enable support for BYD Atto 3 +config OVMS_VEHICLE_MAPLE60S + bool "Include support for Maple 60s" + default y + depends on OVMS + depends on OVMS_COMP_POLLER + help + Enable support for Maple 60s config OVMS_VEHICLE_RXTASK_STACK int "Stack size for ISOTP Poller RX task" From e71493709664e09fb1bd39540523bc5853c1183c Mon Sep 17 00:00:00 2001 From: axel troncoso Date: Mon, 19 Aug 2024 14:54:35 -0400 Subject: [PATCH 11/45] Feat(tested-maple-with-logs) --- .../src/vehicle_maple_60s.cpp | 106 ++++++++++++++---- .../vehicle_maple60s/src/vehicle_maple_60s.h | 2 + 2 files changed, 87 insertions(+), 21 deletions(-) diff --git a/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.cpp b/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.cpp index 438338a95..4c3720aa0 100644 --- a/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.cpp +++ b/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.cpp @@ -29,6 +29,9 @@ #include "vehicle_maple_60s.h" +#include +#include + #include "metrics_standard.h" #include "ovms_log.h" #include "ovms_metrics.h" @@ -57,6 +60,8 @@ OvmsVehicleMaple60S::OvmsVehicleMaple60S() memset(send_can_buffer.byte, 0, sizeof(send_can_buffer.byte)); + m_door_lock_status.fill(false); + StdMetrics.ms_v_bat_12v_voltage->SetValue(12.5, Volts); StdMetrics.ms_v_charge_inprogress->SetValue(false); StdMetrics.ms_v_env_on->SetValue(false); @@ -172,34 +177,93 @@ void OvmsVehicleMaple60S::IncomingFrameCan1(CAN_frame_t *p_frame) StdMetrics.ms_v_env_aux12v->SetValue((CAN_BYTE(7) + 67)/15); break; case 0x284: - StdMetrics.ms_v_door_trunk->SetValue(CAN_BIT(1, 6)); - break; - case 0x285: { - StdMetrics.ms_v_door_fl->SetValue(CAN_BIT(4, 8)); - StdMetrics.ms_v_door_rl->SetValue(CAN_BIT(4, 7)); + auto byte = static_cast>(CAN_BYTE(4)); + ESP_LOGI(TAG, "0x284: %s", byte.to_string().c_str()); - auto fl_locked = static_cast(StdMetrics.ms_v_door_fl->AsBool(true)); - auto rl_locked = static_cast(StdMetrics.ms_v_door_rl->AsBool(true)); - auto fr_locked = static_cast(StdMetrics.ms_v_door_fr->AsBool(true)); - auto rr_locked = static_cast(StdMetrics.ms_v_door_rr->AsBool(true)); + StdMetrics.ms_v_door_trunk->SetValue(CAN_BIT(1, 2)); - StdMetrics.ms_v_env_locked->SetValue( - fl_locked && rl_locked && fr_locked && rr_locked); + ESP_LOGI(TAG, "0x284: trunk: %d", StdMetrics.ms_v_door_trunk->AsBool(true)); + break; + } + case 0x285: + { + auto bit0 = static_cast(CAN_BIT(4, 0)); + auto bit1 = static_cast(CAN_BIT(4, 1)); + auto bit2 = static_cast(CAN_BIT(4, 2)); + auto bit3 = static_cast(CAN_BIT(4, 3)); + auto bit4 = static_cast(CAN_BIT(4, 4)); + auto bit5 = static_cast(CAN_BIT(4, 5)); + auto bit6 = static_cast(CAN_BIT(4, 6)); + auto bit7 = static_cast(CAN_BIT(4, 7)); + + auto byte = static_cast>(CAN_BYTE(4)); + + ESP_LOGI(TAG, "0x285: %s", byte.to_string().c_str()); + ESP_LOGI(TAG, "0x285: %d %d %d %d %d %d %d %d", + bit0, bit1, bit2, bit3, bit4, bit5, bit6, bit7); + + StdMetrics.ms_v_door_fl->SetValue(CAN_BIT(4, 0)); + StdMetrics.ms_v_door_rl->SetValue(CAN_BIT(4, 1)); + + /* It's unclear which bit is associated with which door. + * However this doesn't matter since to consider the + * vehicle locked, all must be locked. */ + m_door_lock_status[0] = CAN_BIT(4, 2); + m_door_lock_status[1] = CAN_BIT(4, 4); + + ESP_LOGI(TAG, "lock_status %d %d %d %d", + m_door_lock_status[0], m_door_lock_status[1], + m_door_lock_status[2], m_door_lock_status[3]); + + auto vehicle_locked = std::accumulate( + m_door_lock_status.begin(), + m_door_lock_status.end(), + true, + [](bool a, bool b) + { return a && b; }); + + StdMetrics.ms_v_env_locked->SetValue(vehicle_locked); break; } case 0x286: { - StdMetrics.ms_v_door_fr->SetValue(CAN_BIT(4, 8)); - StdMetrics.ms_v_door_rr->SetValue(CAN_BIT(4, 7)); - - auto fl_locked = static_cast(StdMetrics.ms_v_door_fl->AsBool(true)); - auto rl_locked = static_cast(StdMetrics.ms_v_door_rl->AsBool(true)); - auto fr_locked = static_cast(StdMetrics.ms_v_door_fr->AsBool(true)); - auto rr_locked = static_cast(StdMetrics.ms_v_door_rr->AsBool(true)); - - StdMetrics.ms_v_env_locked->SetValue( - fl_locked && rl_locked && fr_locked && rr_locked); + auto bit0 = static_cast(CAN_BIT(4, 0)); + auto bit1 = static_cast(CAN_BIT(4, 1)); + auto bit2 = static_cast(CAN_BIT(4, 2)); + auto bit3 = static_cast(CAN_BIT(4, 3)); + auto bit4 = static_cast(CAN_BIT(4, 4)); + auto bit5 = static_cast(CAN_BIT(4, 5)); + auto bit6 = static_cast(CAN_BIT(4, 6)); + auto bit7 = static_cast(CAN_BIT(4, 7)); + + auto byte = static_cast>(CAN_BYTE(4)); + + ESP_LOGI(TAG, "0x286: %s", byte.to_string().c_str()); + ESP_LOGI(TAG, "0x286: %d %d %d %d %d %d %d %d", + bit0, bit1, bit2, bit3, bit4, bit5, bit6, bit7); + + StdMetrics.ms_v_door_fr->SetValue(CAN_BIT(4, 0)); + StdMetrics.ms_v_door_rr->SetValue(CAN_BIT(4, 1)); + + /* It's unclear which bit is associated with which door. + * However this doesn't matter since to consider the + * vehicle locked, all must be locked. */ + m_door_lock_status[2] = CAN_BIT(4, 2); + m_door_lock_status[3] = CAN_BIT(4, 4); + + ESP_LOGI(TAG, "lock_status %d %d %d %d", + m_door_lock_status[0], m_door_lock_status[1], + m_door_lock_status[2], m_door_lock_status[3]); + + auto vehicle_locked = std::accumulate( + m_door_lock_status.begin(), + m_door_lock_status.end(), + true, + [](bool a, bool b) + { return a && b; }); + + StdMetrics.ms_v_env_locked->SetValue(vehicle_locked); break; } } diff --git a/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.h b/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.h index 0fec83c21..be8d09d69 100644 --- a/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.h +++ b/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.h @@ -50,6 +50,8 @@ class OvmsVehicleMaple60S : public OvmsVehicle uint8_t status; uint16_t id; } send_can_buffer; + + std::array m_door_lock_status; }; #endif // #ifndef __VEHICLE_MAPLE60S_H__ \ No newline at end of file From 14ee5aebe8cc6446d7058becc0d32c02ee83c885 Mon Sep 17 00:00:00 2001 From: axel troncoso Date: Mon, 19 Aug 2024 14:56:49 -0400 Subject: [PATCH 12/45] Feat(removing-unnecessary-logs) --- .../src/vehicle_maple_60s.cpp | 43 ------------------- 1 file changed, 43 deletions(-) diff --git a/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.cpp b/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.cpp index 4c3720aa0..63e6923e8 100644 --- a/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.cpp +++ b/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.cpp @@ -178,31 +178,11 @@ void OvmsVehicleMaple60S::IncomingFrameCan1(CAN_frame_t *p_frame) break; case 0x284: { - auto byte = static_cast>(CAN_BYTE(4)); - ESP_LOGI(TAG, "0x284: %s", byte.to_string().c_str()); - StdMetrics.ms_v_door_trunk->SetValue(CAN_BIT(1, 2)); - - ESP_LOGI(TAG, "0x284: trunk: %d", StdMetrics.ms_v_door_trunk->AsBool(true)); break; } case 0x285: { - auto bit0 = static_cast(CAN_BIT(4, 0)); - auto bit1 = static_cast(CAN_BIT(4, 1)); - auto bit2 = static_cast(CAN_BIT(4, 2)); - auto bit3 = static_cast(CAN_BIT(4, 3)); - auto bit4 = static_cast(CAN_BIT(4, 4)); - auto bit5 = static_cast(CAN_BIT(4, 5)); - auto bit6 = static_cast(CAN_BIT(4, 6)); - auto bit7 = static_cast(CAN_BIT(4, 7)); - - auto byte = static_cast>(CAN_BYTE(4)); - - ESP_LOGI(TAG, "0x285: %s", byte.to_string().c_str()); - ESP_LOGI(TAG, "0x285: %d %d %d %d %d %d %d %d", - bit0, bit1, bit2, bit3, bit4, bit5, bit6, bit7); - StdMetrics.ms_v_door_fl->SetValue(CAN_BIT(4, 0)); StdMetrics.ms_v_door_rl->SetValue(CAN_BIT(4, 1)); @@ -212,10 +192,6 @@ void OvmsVehicleMaple60S::IncomingFrameCan1(CAN_frame_t *p_frame) m_door_lock_status[0] = CAN_BIT(4, 2); m_door_lock_status[1] = CAN_BIT(4, 4); - ESP_LOGI(TAG, "lock_status %d %d %d %d", - m_door_lock_status[0], m_door_lock_status[1], - m_door_lock_status[2], m_door_lock_status[3]); - auto vehicle_locked = std::accumulate( m_door_lock_status.begin(), m_door_lock_status.end(), @@ -228,21 +204,6 @@ void OvmsVehicleMaple60S::IncomingFrameCan1(CAN_frame_t *p_frame) } case 0x286: { - auto bit0 = static_cast(CAN_BIT(4, 0)); - auto bit1 = static_cast(CAN_BIT(4, 1)); - auto bit2 = static_cast(CAN_BIT(4, 2)); - auto bit3 = static_cast(CAN_BIT(4, 3)); - auto bit4 = static_cast(CAN_BIT(4, 4)); - auto bit5 = static_cast(CAN_BIT(4, 5)); - auto bit6 = static_cast(CAN_BIT(4, 6)); - auto bit7 = static_cast(CAN_BIT(4, 7)); - - auto byte = static_cast>(CAN_BYTE(4)); - - ESP_LOGI(TAG, "0x286: %s", byte.to_string().c_str()); - ESP_LOGI(TAG, "0x286: %d %d %d %d %d %d %d %d", - bit0, bit1, bit2, bit3, bit4, bit5, bit6, bit7); - StdMetrics.ms_v_door_fr->SetValue(CAN_BIT(4, 0)); StdMetrics.ms_v_door_rr->SetValue(CAN_BIT(4, 1)); @@ -252,10 +213,6 @@ void OvmsVehicleMaple60S::IncomingFrameCan1(CAN_frame_t *p_frame) m_door_lock_status[2] = CAN_BIT(4, 2); m_door_lock_status[3] = CAN_BIT(4, 4); - ESP_LOGI(TAG, "lock_status %d %d %d %d", - m_door_lock_status[0], m_door_lock_status[1], - m_door_lock_status[2], m_door_lock_status[3]); - auto vehicle_locked = std::accumulate( m_door_lock_status.begin(), m_door_lock_status.end(), From 242cc992d3092dc7dc36ad9171f154c3eb1c63d9 Mon Sep 17 00:00:00 2001 From: axel troncoso Date: Mon, 19 Aug 2024 15:14:39 -0400 Subject: [PATCH 13/45] Feat(remove-maple-docs) --- .../vehicle_maple60s/docs/index.rst | 34 ------------------- 1 file changed, 34 deletions(-) delete mode 100644 vehicle/OVMS.V3/components/vehicle_maple60s/docs/index.rst diff --git a/vehicle/OVMS.V3/components/vehicle_maple60s/docs/index.rst b/vehicle/OVMS.V3/components/vehicle_maple60s/docs/index.rst deleted file mode 100644 index 87e105e77..000000000 --- a/vehicle/OVMS.V3/components/vehicle_maple60s/docs/index.rst +++ /dev/null @@ -1,34 +0,0 @@ -======================= -Maple 60s -======================= - -Vehicle Type: **Maple 60a** - -The Maple 60s will be documented here. - ----------------- -Support Overview ----------------- - -=========================== ============== -Function Support Status -=========================== ============== -Hardware OVMS v3 (or later) -Vehicle Cable OBD-II to DB9 Data Cable for OVMS (1441200 right, or 1139300 left) -GSM Antenna 1000500 Open Vehicles OVMS GSM Antenna (or any compatible antenna) -GPS Antenna 1020200 Universal GPS Antenna (SMA Connector) (or any compatible antenna) -SOC Display Yes -Range Display Yes -GPS Location Yes (from modem module GPS) -Speed Display Yes -Temperature Display Yes (External Temp and Battery) -BMS v+t Display Yes -TPMS Display No -Charge Status Display Yes -Charge Interruption Alerts No -Charge Control No -Cabin Pre-heat/cool Control No -Lock/Unlock Vehicle Yes -Valet Mode Control No -Others -=========================== ============== From ffa69d29068a74c9777aec2d74cfe873bf1bc0b6 Mon Sep 17 00:00:00 2001 From: axel troncoso Date: Mon, 19 Aug 2024 15:24:34 -0400 Subject: [PATCH 14/45] Refactor(Replace-tabs-for-spaces) --- .../src/vehicle_maple_60s.cpp | 144 +++++++++--------- .../vehicle_maple60s/src/vehicle_maple_60s.h | 36 ++--- 2 files changed, 90 insertions(+), 90 deletions(-) diff --git a/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.cpp b/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.cpp index 63e6923e8..15d265fcd 100644 --- a/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.cpp +++ b/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.cpp @@ -144,92 +144,92 @@ void OvmsVehicleMaple60S::IncomingFrameCan1(CAN_frame_t *p_frame) switch (p_frame->MsgID) { - case 0x250: - StdMetrics.ms_v_charge_inprogress->SetValue(CAN_BIT(7, 0)); - break; - // case 0x46a: - // StdMetrics.ms_v_door_fl->SetValue(CAN_BIT(0, 0)); - // StdMetrics.ms_v_door_fr->SetValue(CAN_BIT(0, 3)); - // StdMetrics.ms_v_door_rl->SetValue(CAN_BIT(0, 5)); - // StdMetrics.ms_v_door_rr->SetValue(CAN_BIT(0, 7)); - // StdMetrics.ms_v_door_trunk->SetValue(CAN_BIT(1, 1)); - // break; - case 0x3F1: - StdMetrics.ms_v_pos_odometer->SetValue(CAN_UINT24(0) / 10.0, Kilometers); - break; - case 0x125: - StdMetrics.ms_v_pos_speed->SetValue((CAN_BYTE(1) * 2) + (2 * (CAN_BYTE(2) - 1) / 250.0)); - break; - case 0x162: // awake, on, off and power + case 0x250: + StdMetrics.ms_v_charge_inprogress->SetValue(CAN_BIT(7, 0)); + break; + // case 0x46a: + // StdMetrics.ms_v_door_fl->SetValue(CAN_BIT(0, 0)); + // StdMetrics.ms_v_door_fr->SetValue(CAN_BIT(0, 3)); + // StdMetrics.ms_v_door_rl->SetValue(CAN_BIT(0, 5)); + // StdMetrics.ms_v_door_rr->SetValue(CAN_BIT(0, 7)); + // StdMetrics.ms_v_door_trunk->SetValue(CAN_BIT(1, 1)); + // break; + case 0x3F1: + StdMetrics.ms_v_pos_odometer->SetValue(CAN_UINT24(0) / 10.0, Kilometers); + break; + case 0x125: + StdMetrics.ms_v_pos_speed->SetValue((CAN_BYTE(1) * 2) + (2 * (CAN_BYTE(2) - 1) / 250.0)); + break; + case 0x162: // awake, on, off and power { - StdMetrics.ms_v_env_awake->SetValue(CAN_BIT(5, 0)); - StdMetrics.ms_v_env_on->SetValue(CAN_BIT(3, 7) && CAN_BIT(5, 0)); - StdMetrics.ms_v_bat_power->SetValue(CAN_BYTE(4) - 100); + StdMetrics.ms_v_env_awake->SetValue(CAN_BIT(5, 0)); + StdMetrics.ms_v_env_on->SetValue(CAN_BIT(3, 7) && CAN_BIT(5, 0)); + StdMetrics.ms_v_bat_power->SetValue(CAN_BYTE(4) - 100); - auto usingCcsCharger = StdMetrics.ms_v_bat_power->AsFloat(0, kW) < -15; - StdMetrics.ms_v_charge_type->SetValue(usingCcsCharger ? "ccs" : "type2"); - break; + auto usingCcsCharger = StdMetrics.ms_v_bat_power->AsFloat(0, kW) < -15; + StdMetrics.ms_v_charge_type->SetValue(usingCcsCharger ? "ccs" : "type2"); + break; } - case 0x2F4: // Charge state - StdMetrics.ms_v_bat_soc->SetValue((100 * CAN_BYTE(1)) / 255, Percentage); - break; - case 0x235: - StdMetrics.ms_v_env_aux12v->SetValue((CAN_BYTE(7) + 67)/15); - break; - case 0x284: + case 0x2F4: // Charge state + StdMetrics.ms_v_bat_soc->SetValue((100 * CAN_BYTE(1)) / 255, Percentage); + break; + case 0x235: + StdMetrics.ms_v_env_aux12v->SetValue((CAN_BYTE(7) + 67)/15); + break; + case 0x284: { - StdMetrics.ms_v_door_trunk->SetValue(CAN_BIT(1, 2)); - break; + StdMetrics.ms_v_door_trunk->SetValue(CAN_BIT(1, 2)); + break; } - case 0x285: + case 0x285: { - StdMetrics.ms_v_door_fl->SetValue(CAN_BIT(4, 0)); - StdMetrics.ms_v_door_rl->SetValue(CAN_BIT(4, 1)); - - /* It's unclear which bit is associated with which door. - * However this doesn't matter since to consider the - * vehicle locked, all must be locked. */ - m_door_lock_status[0] = CAN_BIT(4, 2); - m_door_lock_status[1] = CAN_BIT(4, 4); - - auto vehicle_locked = std::accumulate( - m_door_lock_status.begin(), - m_door_lock_status.end(), - true, - [](bool a, bool b) - { return a && b; }); - - StdMetrics.ms_v_env_locked->SetValue(vehicle_locked); - break; + StdMetrics.ms_v_door_fl->SetValue(CAN_BIT(4, 0)); + StdMetrics.ms_v_door_rl->SetValue(CAN_BIT(4, 1)); + + /* It's unclear which bit is associated with which door. + * However this doesn't matter since to consider the + * vehicle locked, all must be locked. */ + m_door_lock_status[0] = CAN_BIT(4, 2); + m_door_lock_status[1] = CAN_BIT(4, 4); + + auto vehicle_locked = std::accumulate( + m_door_lock_status.begin(), + m_door_lock_status.end(), + true, + [](bool a, bool b) + { return a && b; }); + + StdMetrics.ms_v_env_locked->SetValue(vehicle_locked); + break; } - case 0x286: + case 0x286: { - StdMetrics.ms_v_door_fr->SetValue(CAN_BIT(4, 0)); - StdMetrics.ms_v_door_rr->SetValue(CAN_BIT(4, 1)); - - /* It's unclear which bit is associated with which door. - * However this doesn't matter since to consider the - * vehicle locked, all must be locked. */ - m_door_lock_status[2] = CAN_BIT(4, 2); - m_door_lock_status[3] = CAN_BIT(4, 4); - - auto vehicle_locked = std::accumulate( - m_door_lock_status.begin(), - m_door_lock_status.end(), - true, - [](bool a, bool b) - { return a && b; }); - - StdMetrics.ms_v_env_locked->SetValue(vehicle_locked); - break; + StdMetrics.ms_v_door_fr->SetValue(CAN_BIT(4, 0)); + StdMetrics.ms_v_door_rr->SetValue(CAN_BIT(4, 1)); + + /* It's unclear which bit is associated with which door. + * However this doesn't matter since to consider the + * vehicle locked, all must be locked. */ + m_door_lock_status[2] = CAN_BIT(4, 2); + m_door_lock_status[3] = CAN_BIT(4, 4); + + auto vehicle_locked = std::accumulate( + m_door_lock_status.begin(), + m_door_lock_status.end(), + true, + [](bool a, bool b) + { return a && b; }); + + StdMetrics.ms_v_env_locked->SetValue(vehicle_locked); + break; } } } class OvmsVehicleMaple60SInit { -public: - OvmsVehicleMaple60SInit(); + public: + OvmsVehicleMaple60SInit(); } MyOvmsVehicleMaple60SInit __attribute__((init_priority(9000))); OvmsVehicleMaple60SInit::OvmsVehicleMaple60SInit() diff --git a/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.h b/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.h index be8d09d69..9b7f97513 100644 --- a/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.h +++ b/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.h @@ -35,23 +35,23 @@ using namespace std; class OvmsVehicleMaple60S : public OvmsVehicle - { - public: - OvmsVehicleMaple60S(); - ~OvmsVehicleMaple60S(); - - public: - void IncomingFrameCan1(CAN_frame_t *p_frame) override; - void Ticker1(uint32_t ticker) override; - - private: - struct { - uint8_t byte[8]; - uint8_t status; - uint16_t id; - } send_can_buffer; - - std::array m_door_lock_status; - }; +{ +public: + OvmsVehicleMaple60S(); + ~OvmsVehicleMaple60S(); + +public: + void IncomingFrameCan1(CAN_frame_t *p_frame) override; + void Ticker1(uint32_t ticker) override; + +private: + struct { + uint8_t byte[8]; + uint8_t status; + uint16_t id; + } send_can_buffer; + + std::array m_door_lock_status; +}; #endif // #ifndef __VEHICLE_MAPLE60S_H__ \ No newline at end of file From 4cf7e15769a33e256ee8aab286fe84a701b7d67b Mon Sep 17 00:00:00 2001 From: axel troncoso Date: Mon, 19 Aug 2024 15:26:07 -0400 Subject: [PATCH 15/45] Refactor(Replace-tabs-for-spaces) --- .../src/vehicle_maple_60s.cpp | 308 +++++++++--------- 1 file changed, 154 insertions(+), 154 deletions(-) diff --git a/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.cpp b/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.cpp index 15d265fcd..f833860d0 100644 --- a/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.cpp +++ b/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.cpp @@ -53,26 +53,26 @@ static const char *TAG = "v-maple60s"; OvmsVehicleMaple60S::OvmsVehicleMaple60S() { - ESP_LOGI(TAG, "Maple 60s vehicle module"); + ESP_LOGI(TAG, "Maple 60s vehicle module"); - send_can_buffer.id = 0; - send_can_buffer.status = 0; + send_can_buffer.id = 0; + send_can_buffer.status = 0; - memset(send_can_buffer.byte, 0, sizeof(send_can_buffer.byte)); + memset(send_can_buffer.byte, 0, sizeof(send_can_buffer.byte)); - m_door_lock_status.fill(false); + m_door_lock_status.fill(false); - StdMetrics.ms_v_bat_12v_voltage->SetValue(12.5, Volts); - StdMetrics.ms_v_charge_inprogress->SetValue(false); - StdMetrics.ms_v_env_on->SetValue(false); - StdMetrics.ms_v_bat_temp->SetValue(20, Celcius); - StdMetrics.ms_v_env_locked->SetValue(false); + StdMetrics.ms_v_bat_12v_voltage->SetValue(12.5, Volts); + StdMetrics.ms_v_charge_inprogress->SetValue(false); + StdMetrics.ms_v_env_on->SetValue(false); + StdMetrics.ms_v_bat_temp->SetValue(20, Celcius); + StdMetrics.ms_v_env_locked->SetValue(false); - // Require GPS. - MyEvents.SignalEvent("vehicle.require.gps", NULL); - MyEvents.SignalEvent("vehicle.require.gpstime", NULL); + // Require GPS. + MyEvents.SignalEvent("vehicle.require.gps", NULL); + MyEvents.SignalEvent("vehicle.require.gpstime", NULL); - RegisterCanBus(1, CAN_MODE_LISTEN, CAN_SPEED_500KBPS); + RegisterCanBus(1, CAN_MODE_LISTEN, CAN_SPEED_500KBPS); } /** @@ -80,7 +80,7 @@ OvmsVehicleMaple60S::OvmsVehicleMaple60S() */ OvmsVehicleMaple60S::~OvmsVehicleMaple60S() { - ESP_LOGI(TAG, "Shutdown Maple 60S vehicle module"); + ESP_LOGI(TAG, "Shutdown Maple 60S vehicle module"); } void OvmsVehicleMaple60S::Ticker1(uint32_t ticker) @@ -89,151 +89,151 @@ void OvmsVehicleMaple60S::Ticker1(uint32_t ticker) void OvmsVehicleMaple60S::IncomingFrameCan1(CAN_frame_t *p_frame) { - uint8_t *d = p_frame->data.u8; - - // Check if response is from synchronous can message - if (send_can_buffer.status == 0xff && p_frame->MsgID == (send_can_buffer.id + 0x08)) - { - // Store message bytes so that the async method can continue - send_can_buffer.status = 3; - - send_can_buffer.byte[0] = d[0]; - send_can_buffer.byte[1] = d[1]; - send_can_buffer.byte[2] = d[2]; - send_can_buffer.byte[3] = d[3]; - send_can_buffer.byte[4] = d[4]; - send_can_buffer.byte[5] = d[5]; - send_can_buffer.byte[6] = d[6]; - send_can_buffer.byte[7] = d[7]; - } - - /* - BASIC METRICS - StdMetrics.ms_v_pos_speed ok - StdMetrics.ms_v_bat_soc ok - StdMetrics.ms_v_pos_odometer ok - - StdMetrics.ms_v_door_fl rev - StdMetrics.ms_v_door_fr rev - StdMetrics.ms_v_door_rl rev - StdMetrics.ms_v_door_rr rev - StdMetrics.ms_v_env_locked no - - StdMetrics.ms_v_env_onepedal NA - StdMetrics.ms_v_env_efficiencymode ok - StdMetrics.ms_v_env_regenlevel Percentage ok - - StdMetrics.ms_v_bat_current NA - StdMetrics.ms_v_bat_voltage NA - StdMetrics.ms_v_bat_power ok - - StdMetrics.ms_v_charge_inprogress rev - - StdMetrics.ms_v_env_on ok - StdMetrics.ms_v_env_awake ok - - StdMetrics.ms_v_env_aux12v rev - - StdMetrics.ms_v_tpms_pressure->SetElemValue(MS_V_TPMS_IDX_FL, value, PSI); - StdMetrics.ms_v_tpms_pressure->SetElemValue(MS_V_TPMS_IDX_FR, value, PSI); - StdMetrics.ms_v_tpms_pressure->SetElemValue(MS_V_TPMS_IDX_RL, value, PSI); - StdMetrics.ms_v_tpms_pressure->SetElemValue(MS_V_TPMS_IDX_RR, value, PSI); - */ - - uint8_t *data = p_frame->data.u8; - - switch (p_frame->MsgID) - { - case 0x250: - StdMetrics.ms_v_charge_inprogress->SetValue(CAN_BIT(7, 0)); - break; - // case 0x46a: - // StdMetrics.ms_v_door_fl->SetValue(CAN_BIT(0, 0)); - // StdMetrics.ms_v_door_fr->SetValue(CAN_BIT(0, 3)); - // StdMetrics.ms_v_door_rl->SetValue(CAN_BIT(0, 5)); - // StdMetrics.ms_v_door_rr->SetValue(CAN_BIT(0, 7)); - // StdMetrics.ms_v_door_trunk->SetValue(CAN_BIT(1, 1)); - // break; - case 0x3F1: - StdMetrics.ms_v_pos_odometer->SetValue(CAN_UINT24(0) / 10.0, Kilometers); - break; - case 0x125: - StdMetrics.ms_v_pos_speed->SetValue((CAN_BYTE(1) * 2) + (2 * (CAN_BYTE(2) - 1) / 250.0)); - break; - case 0x162: // awake, on, off and power - { - StdMetrics.ms_v_env_awake->SetValue(CAN_BIT(5, 0)); - StdMetrics.ms_v_env_on->SetValue(CAN_BIT(3, 7) && CAN_BIT(5, 0)); - StdMetrics.ms_v_bat_power->SetValue(CAN_BYTE(4) - 100); - - auto usingCcsCharger = StdMetrics.ms_v_bat_power->AsFloat(0, kW) < -15; - StdMetrics.ms_v_charge_type->SetValue(usingCcsCharger ? "ccs" : "type2"); - break; - } - case 0x2F4: // Charge state - StdMetrics.ms_v_bat_soc->SetValue((100 * CAN_BYTE(1)) / 255, Percentage); - break; - case 0x235: - StdMetrics.ms_v_env_aux12v->SetValue((CAN_BYTE(7) + 67)/15); - break; - case 0x284: - { - StdMetrics.ms_v_door_trunk->SetValue(CAN_BIT(1, 2)); - break; - } - case 0x285: - { - StdMetrics.ms_v_door_fl->SetValue(CAN_BIT(4, 0)); - StdMetrics.ms_v_door_rl->SetValue(CAN_BIT(4, 1)); - - /* It's unclear which bit is associated with which door. - * However this doesn't matter since to consider the - * vehicle locked, all must be locked. */ - m_door_lock_status[0] = CAN_BIT(4, 2); - m_door_lock_status[1] = CAN_BIT(4, 4); - - auto vehicle_locked = std::accumulate( - m_door_lock_status.begin(), - m_door_lock_status.end(), - true, - [](bool a, bool b) - { return a && b; }); - - StdMetrics.ms_v_env_locked->SetValue(vehicle_locked); - break; - } - case 0x286: - { - StdMetrics.ms_v_door_fr->SetValue(CAN_BIT(4, 0)); - StdMetrics.ms_v_door_rr->SetValue(CAN_BIT(4, 1)); - - /* It's unclear which bit is associated with which door. - * However this doesn't matter since to consider the - * vehicle locked, all must be locked. */ - m_door_lock_status[2] = CAN_BIT(4, 2); - m_door_lock_status[3] = CAN_BIT(4, 4); - - auto vehicle_locked = std::accumulate( - m_door_lock_status.begin(), - m_door_lock_status.end(), - true, - [](bool a, bool b) - { return a && b; }); - - StdMetrics.ms_v_env_locked->SetValue(vehicle_locked); - break; - } - } + uint8_t *d = p_frame->data.u8; + + // Check if response is from synchronous can message + if (send_can_buffer.status == 0xff && p_frame->MsgID == (send_can_buffer.id + 0x08)) + { + // Store message bytes so that the async method can continue + send_can_buffer.status = 3; + + send_can_buffer.byte[0] = d[0]; + send_can_buffer.byte[1] = d[1]; + send_can_buffer.byte[2] = d[2]; + send_can_buffer.byte[3] = d[3]; + send_can_buffer.byte[4] = d[4]; + send_can_buffer.byte[5] = d[5]; + send_can_buffer.byte[6] = d[6]; + send_can_buffer.byte[7] = d[7]; + } + + /* + BASIC METRICS + StdMetrics.ms_v_pos_speed ok + StdMetrics.ms_v_bat_soc ok + StdMetrics.ms_v_pos_odometer ok + + StdMetrics.ms_v_door_fl rev + StdMetrics.ms_v_door_fr rev + StdMetrics.ms_v_door_rl rev + StdMetrics.ms_v_door_rr rev + StdMetrics.ms_v_env_locked no + + StdMetrics.ms_v_env_onepedal NA + StdMetrics.ms_v_env_efficiencymode ok + StdMetrics.ms_v_env_regenlevel Percentage ok + + StdMetrics.ms_v_bat_current NA + StdMetrics.ms_v_bat_voltage NA + StdMetrics.ms_v_bat_power ok + + StdMetrics.ms_v_charge_inprogress rev + + StdMetrics.ms_v_env_on ok + StdMetrics.ms_v_env_awake ok + + StdMetrics.ms_v_env_aux12v rev + + StdMetrics.ms_v_tpms_pressure->SetElemValue(MS_V_TPMS_IDX_FL, value, PSI); + StdMetrics.ms_v_tpms_pressure->SetElemValue(MS_V_TPMS_IDX_FR, value, PSI); + StdMetrics.ms_v_tpms_pressure->SetElemValue(MS_V_TPMS_IDX_RL, value, PSI); + StdMetrics.ms_v_tpms_pressure->SetElemValue(MS_V_TPMS_IDX_RR, value, PSI); + */ + + uint8_t *data = p_frame->data.u8; + + switch (p_frame->MsgID) + { + case 0x250: + StdMetrics.ms_v_charge_inprogress->SetValue(CAN_BIT(7, 0)); + break; + // case 0x46a: + // StdMetrics.ms_v_door_fl->SetValue(CAN_BIT(0, 0)); + // StdMetrics.ms_v_door_fr->SetValue(CAN_BIT(0, 3)); + // StdMetrics.ms_v_door_rl->SetValue(CAN_BIT(0, 5)); + // StdMetrics.ms_v_door_rr->SetValue(CAN_BIT(0, 7)); + // StdMetrics.ms_v_door_trunk->SetValue(CAN_BIT(1, 1)); + // break; + case 0x3F1: + StdMetrics.ms_v_pos_odometer->SetValue(CAN_UINT24(0) / 10.0, Kilometers); + break; + case 0x125: + StdMetrics.ms_v_pos_speed->SetValue((CAN_BYTE(1) * 2) + (2 * (CAN_BYTE(2) - 1) / 250.0)); + break; + case 0x162: // awake, on, off and power + { + StdMetrics.ms_v_env_awake->SetValue(CAN_BIT(5, 0)); + StdMetrics.ms_v_env_on->SetValue(CAN_BIT(3, 7) && CAN_BIT(5, 0)); + StdMetrics.ms_v_bat_power->SetValue(CAN_BYTE(4) - 100); + + auto usingCcsCharger = StdMetrics.ms_v_bat_power->AsFloat(0, kW) < -15; + StdMetrics.ms_v_charge_type->SetValue(usingCcsCharger ? "ccs" : "type2"); + break; + } + case 0x2F4: // Charge state + StdMetrics.ms_v_bat_soc->SetValue((100 * CAN_BYTE(1)) / 255, Percentage); + break; + case 0x235: + StdMetrics.ms_v_env_aux12v->SetValue((CAN_BYTE(7) + 67)/15); + break; + case 0x284: + { + StdMetrics.ms_v_door_trunk->SetValue(CAN_BIT(1, 2)); + break; + } + case 0x285: + { + StdMetrics.ms_v_door_fl->SetValue(CAN_BIT(4, 0)); + StdMetrics.ms_v_door_rl->SetValue(CAN_BIT(4, 1)); + + /* It's unclear which bit is associated with which door. + * However this doesn't matter since to consider the + * vehicle locked, all must be locked. */ + m_door_lock_status[0] = CAN_BIT(4, 2); + m_door_lock_status[1] = CAN_BIT(4, 4); + + auto vehicle_locked = std::accumulate( + m_door_lock_status.begin(), + m_door_lock_status.end(), + true, + [](bool a, bool b) + { return a && b; }); + + StdMetrics.ms_v_env_locked->SetValue(vehicle_locked); + break; + } + case 0x286: + { + StdMetrics.ms_v_door_fr->SetValue(CAN_BIT(4, 0)); + StdMetrics.ms_v_door_rr->SetValue(CAN_BIT(4, 1)); + + /* It's unclear which bit is associated with which door. + * However this doesn't matter since to consider the + * vehicle locked, all must be locked. */ + m_door_lock_status[2] = CAN_BIT(4, 2); + m_door_lock_status[3] = CAN_BIT(4, 4); + + auto vehicle_locked = std::accumulate( + m_door_lock_status.begin(), + m_door_lock_status.end(), + true, + [](bool a, bool b) + { return a && b; }); + + StdMetrics.ms_v_env_locked->SetValue(vehicle_locked); + break; + } + } } class OvmsVehicleMaple60SInit { - public: - OvmsVehicleMaple60SInit(); + public: + OvmsVehicleMaple60SInit(); } MyOvmsVehicleMaple60SInit __attribute__((init_priority(9000))); OvmsVehicleMaple60SInit::OvmsVehicleMaple60SInit() { - ESP_LOGI(TAG, "Registering Vehicle: Maple 60S (9000)"); - MyVehicleFactory.RegisterVehicle("MPL60S", "Maple 60S"); + ESP_LOGI(TAG, "Registering Vehicle: Maple 60S (9000)"); + MyVehicleFactory.RegisterVehicle("MPL60S", "Maple 60S"); } From b966720b6f340eb27960ff792df7dcdee6d4c2f9 Mon Sep 17 00:00:00 2001 From: axel troncoso Date: Mon, 19 Aug 2024 15:36:25 -0400 Subject: [PATCH 16/45] Refactor(allign-table) --- .../src/vehicle_maple_60s.cpp | 44 ++++++------------- 1 file changed, 14 insertions(+), 30 deletions(-) diff --git a/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.cpp b/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.cpp index f833860d0..71d9238a0 100644 --- a/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.cpp +++ b/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.cpp @@ -109,35 +109,26 @@ void OvmsVehicleMaple60S::IncomingFrameCan1(CAN_frame_t *p_frame) /* BASIC METRICS - StdMetrics.ms_v_pos_speed ok + StdMetrics.ms_v_pos_speed ok StdMetrics.ms_v_bat_soc ok - StdMetrics.ms_v_pos_odometer ok + StdMetrics.ms_v_pos_odometer ok - StdMetrics.ms_v_door_fl rev - StdMetrics.ms_v_door_fr rev - StdMetrics.ms_v_door_rl rev - StdMetrics.ms_v_door_rr rev - StdMetrics.ms_v_env_locked no + StdMetrics.ms_v_door_fl ok + StdMetrics.ms_v_door_fr ok + StdMetrics.ms_v_door_rl ok + StdMetrics.ms_v_door_rr ok + StdMetrics.ms_v_env_locked ok - StdMetrics.ms_v_env_onepedal NA - StdMetrics.ms_v_env_efficiencymode ok - StdMetrics.ms_v_env_regenlevel Percentage ok + StdMetrics.ms_v_bat_current NA + StdMetrics.ms_v_bat_voltage NA + StdMetrics.ms_v_bat_power ok - StdMetrics.ms_v_bat_current NA - StdMetrics.ms_v_bat_voltage NA - StdMetrics.ms_v_bat_power ok + StdMetrics.ms_v_charge_inprogress rev - StdMetrics.ms_v_charge_inprogress rev + StdMetrics.ms_v_env_on ok + StdMetrics.ms_v_env_awake ok - StdMetrics.ms_v_env_on ok - StdMetrics.ms_v_env_awake ok - - StdMetrics.ms_v_env_aux12v rev - - StdMetrics.ms_v_tpms_pressure->SetElemValue(MS_V_TPMS_IDX_FL, value, PSI); - StdMetrics.ms_v_tpms_pressure->SetElemValue(MS_V_TPMS_IDX_FR, value, PSI); - StdMetrics.ms_v_tpms_pressure->SetElemValue(MS_V_TPMS_IDX_RL, value, PSI); - StdMetrics.ms_v_tpms_pressure->SetElemValue(MS_V_TPMS_IDX_RR, value, PSI); + StdMetrics.ms_v_env_aux12v rev */ uint8_t *data = p_frame->data.u8; @@ -147,13 +138,6 @@ void OvmsVehicleMaple60S::IncomingFrameCan1(CAN_frame_t *p_frame) case 0x250: StdMetrics.ms_v_charge_inprogress->SetValue(CAN_BIT(7, 0)); break; - // case 0x46a: - // StdMetrics.ms_v_door_fl->SetValue(CAN_BIT(0, 0)); - // StdMetrics.ms_v_door_fr->SetValue(CAN_BIT(0, 3)); - // StdMetrics.ms_v_door_rl->SetValue(CAN_BIT(0, 5)); - // StdMetrics.ms_v_door_rr->SetValue(CAN_BIT(0, 7)); - // StdMetrics.ms_v_door_trunk->SetValue(CAN_BIT(1, 1)); - // break; case 0x3F1: StdMetrics.ms_v_pos_odometer->SetValue(CAN_UINT24(0) / 10.0, Kilometers); break; From 81d228925dc5eb03c76961d7a1684e8c077bf4c0 Mon Sep 17 00:00:00 2001 From: axel troncoso Date: Mon, 19 Aug 2024 15:41:33 -0400 Subject: [PATCH 17/45] Refactor(general) --- .../components/vehicle_maple60s/src/vehicle_maple_60s.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.cpp b/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.cpp index 71d9238a0..ab4182924 100644 --- a/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.cpp +++ b/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.cpp @@ -65,7 +65,6 @@ OvmsVehicleMaple60S::OvmsVehicleMaple60S() StdMetrics.ms_v_bat_12v_voltage->SetValue(12.5, Volts); StdMetrics.ms_v_charge_inprogress->SetValue(false); StdMetrics.ms_v_env_on->SetValue(false); - StdMetrics.ms_v_bat_temp->SetValue(20, Celcius); StdMetrics.ms_v_env_locked->SetValue(false); // Require GPS. From a7ee700e18b1852b5f4503e80642c2406ed21a10 Mon Sep 17 00:00:00 2001 From: axel troncoso Date: Mon, 19 Aug 2024 15:51:27 -0400 Subject: [PATCH 18/45] Refactor(replacing-tabs-for-spaces) --- .../vehicle_maxus_euniq6/src/vehicle_me6.cpp | 227 +++++++++--------- .../vehicle_maxus_euniq6/src/vehicle_me6.h | 32 +-- 2 files changed, 127 insertions(+), 132 deletions(-) diff --git a/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.cpp b/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.cpp index 166182d93..26070c119 100644 --- a/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.cpp +++ b/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.cpp @@ -34,7 +34,6 @@ static const char *TAG = "v-maxe6"; #include #include "vehicle_me6.h" -#include "me56_pids.h" #include "ovms_notify.h" #include #include "metrics_standard.h" @@ -51,7 +50,7 @@ static const char *TAG = "v-maxe6"; #define CAN_BIT(b,pos) !!(data[b] & (1<<(pos))) OvmsVehicleMaxe6::OvmsVehicleMaxe6() - { +{ ESP_LOGI(TAG, "Start Maxus Euniq 6 vehicle module"); // Init CAN: @@ -77,124 +76,120 @@ OvmsVehicleMaxe6::OvmsVehicleMaxe6() // Require GPS: MyEvents.SignalEvent("vehicle.require.gps", NULL); MyEvents.SignalEvent("vehicle.require.gpstime", NULL); - } +} OvmsVehicleMaxe6::~OvmsVehicleMaxe6() - { +{ ESP_LOGI(TAG, "Stop Euniq 6 vehicle module"); - } +} void OvmsVehicleMaxe6::IncomingFrameCan1(CAN_frame_t *p_frame) { - uint8_t *d = p_frame->data.u8; + uint8_t *d = p_frame->data.u8; - // Check if response is from synchronous can message - if (send_can_buffer.status == 0xff && p_frame->MsgID == (send_can_buffer.id + 0x08)) - { - // Store message bytes so that the async method can continue - send_can_buffer.status = 3; - - send_can_buffer.byte[0] = d[0]; - send_can_buffer.byte[1] = d[1]; - send_can_buffer.byte[2] = d[2]; - send_can_buffer.byte[3] = d[3]; - send_can_buffer.byte[4] = d[4]; - send_can_buffer.byte[5] = d[5]; - send_can_buffer.byte[6] = d[6]; - send_can_buffer.byte[7] = d[7]; - } - - /* - BASIC METRICS - StdMetrics.ms_v_pos_speed ok - StdMetrics.ms_v_bat_soc ok - StdMetrics.ms_v_pos_odometer ok - - StdMetrics.ms_v_door_fl ok; yes when open, no when closed - StdMetrics.ms_v_door_fr ok - StdMetrics.ms_v_door_rl ok - StdMetrics.ms_v_door_rr ok - StdMetrics.ms_v_trunk ok - StdMetrics.ms_v_env_locked ok - - StdMetrics.ms_v_env_onepedal - - StdMetrics.ms_v_env_efficiencymode - - StdMetrics.ms_v_env_regenlevel Percentage - - - StdMetrics.ms_v_bat_current - - StdMetrics.ms_v_bat_voltage - - StdMetrics.ms_v_bat_power wip esta en porcentaje - - StdMetrics.ms_v_charge_inprogress ok - - StdMetrics.ms_v_env_on ok - StdMetrics.ms_v_env_awake ok - - StdMetrics.ms_v_env_aux12v ok - - StdMetrics.ms_v_tpms_pressure->SetElemValue(MS_V_TPMS_IDX_FL, value, PSI); - StdMetrics.ms_v_tpms_pressure->SetElemValue(MS_V_TPMS_IDX_FR, value, PSI); - StdMetrics.ms_v_tpms_pressure->SetElemValue(MS_V_TPMS_IDX_RL, value, PSI); - StdMetrics.ms_v_tpms_pressure->SetElemValue(MS_V_TPMS_IDX_RR, value, PSI); - */ - - uint8_t *data = p_frame->data.u8; - - switch (p_frame->MsgID) - { - case 0x0c9: - { - StdMetrics.ms_v_charge_inprogress->SetValue( - CAN_BIT(2,0) && CAN_BIT(2,1) && CAN_BIT(2,2) - ); - break; - } - case 0x281: - { - StdMetrics.ms_v_env_locked->SetValue( - CAN_BIT(1,0) && CAN_BIT(1,2) && CAN_BIT(1,4) && CAN_BIT(1,6) && - !StdMetrics.ms_v_door_fl->AsBool() && - !StdMetrics.ms_v_door_fr->AsBool() && - !StdMetrics.ms_v_door_rl->AsBool() && - !StdMetrics.ms_v_door_rr->AsBool() && - !StdMetrics.ms_v_door_trunk->AsBool()); - break; - } - case 0x46a: - { - StdMetrics.ms_v_door_fl->SetValue(CAN_BIT(0, 0)); - StdMetrics.ms_v_door_fr->SetValue(CAN_BIT(0, 3)); - StdMetrics.ms_v_door_rr->SetValue(CAN_BIT(0, 5)); - StdMetrics.ms_v_door_rl->SetValue(CAN_BIT(0, 7)); - StdMetrics.ms_v_door_trunk->SetValue(CAN_BIT(1, 1)); - break; - } - case 0x540: - { - StdMetrics.ms_v_pos_odometer->SetValue(CAN_UINT24(0)); - break; - } - case 0x6f0: - { - StdMetrics.ms_v_pos_speed->SetValue(CAN_BYTE(4)); - break; - } - case 0x6f1: - { - StdMetrics.ms_v_env_awake->SetValue(CAN_BIT(4,7)); - StdMetrics.ms_v_env_on->SetValue(CAN_BIT(1,4) && CAN_BIT(4,7)); - break; - } - case 0x6f2: + // Check if response is from synchronous can message + if (send_can_buffer.status == 0xff && p_frame->MsgID == (send_can_buffer.id + 0x08)) + { + // Store message bytes so that the async method can continue + send_can_buffer.status = 3; + + send_can_buffer.byte[0] = d[0]; + send_can_buffer.byte[1] = d[1]; + send_can_buffer.byte[2] = d[2]; + send_can_buffer.byte[3] = d[3]; + send_can_buffer.byte[4] = d[4]; + send_can_buffer.byte[5] = d[5]; + send_can_buffer.byte[6] = d[6]; + send_can_buffer.byte[7] = d[7]; + } + + /* + BASIC METRICS + StdMetrics.ms_v_pos_speed ok + StdMetrics.ms_v_bat_soc ok + StdMetrics.ms_v_pos_odometer ok + + StdMetrics.ms_v_door_fl ok; yes when open, no when closed + StdMetrics.ms_v_door_fr ok + StdMetrics.ms_v_door_rl ok + StdMetrics.ms_v_door_rr ok + StdMetrics.ms_v_trunk ok + StdMetrics.ms_v_env_locked ok + + StdMetrics.ms_v_env_onepedal - + StdMetrics.ms_v_env_efficiencymode - + StdMetrics.ms_v_env_regenlevel Percentage - + + StdMetrics.ms_v_bat_current - + StdMetrics.ms_v_bat_voltage - + StdMetrics.ms_v_bat_power wip esta en porcentaje + + StdMetrics.ms_v_charge_inprogress ok + + StdMetrics.ms_v_env_on ok + StdMetrics.ms_v_env_awake ok + + StdMetrics.ms_v_env_aux12v ok + */ + + uint8_t *data = p_frame->data.u8; + + switch (p_frame->MsgID) { - StdMetrics.ms_v_bat_soc->SetValue(CAN_BYTE(1)); - StdMetrics.ms_v_bat_power->SetValue((CAN_BYTE(2) - 100) * 120, kW); // es porcentaje - break; - } - default: - break; - } + case 0x0c9: + { + StdMetrics.ms_v_charge_inprogress->SetValue( + CAN_BIT(2,0) && CAN_BIT(2,1) && CAN_BIT(2,2) + ); + break; + } + case 0x281: + { + StdMetrics.ms_v_env_locked->SetValue( + CAN_BIT(1,0) && CAN_BIT(1,2) && CAN_BIT(1,4) && CAN_BIT(1,6) && + !StdMetrics.ms_v_door_fl->AsBool() && + !StdMetrics.ms_v_door_fr->AsBool() && + !StdMetrics.ms_v_door_rl->AsBool() && + !StdMetrics.ms_v_door_rr->AsBool() && + !StdMetrics.ms_v_door_trunk->AsBool()); + break; + } + case 0x46a: + { + StdMetrics.ms_v_door_fl->SetValue(CAN_BIT(0, 0)); + StdMetrics.ms_v_door_fr->SetValue(CAN_BIT(0, 3)); + StdMetrics.ms_v_door_rr->SetValue(CAN_BIT(0, 5)); + StdMetrics.ms_v_door_rl->SetValue(CAN_BIT(0, 7)); + StdMetrics.ms_v_door_trunk->SetValue(CAN_BIT(1, 1)); + break; + } + case 0x540: + { + StdMetrics.ms_v_pos_odometer->SetValue(CAN_UINT24(0)); + break; + } + case 0x6f0: + { + StdMetrics.ms_v_pos_speed->SetValue(CAN_BYTE(4)); + break; + } + case 0x6f1: + { + StdMetrics.ms_v_env_awake->SetValue(CAN_BIT(4,7)); + StdMetrics.ms_v_env_on->SetValue(CAN_BIT(1,4) && CAN_BIT(4,7)); + break; + } + case 0x6f2: + { + StdMetrics.ms_v_bat_soc->SetValue(CAN_BYTE(1)); + // Units percentage. + StdMetrics.ms_v_bat_power->SetValue((CAN_BYTE(2) - 100) * 120, kW); + break; + } + default: + break; + } } void OvmsVehicleMaxe6::Ticker1(uint32_t ticker) @@ -202,13 +197,13 @@ void OvmsVehicleMaxe6::Ticker1(uint32_t ticker) } class OvmsVehicleMaxe6Init - { - public: OvmsVehicleMaxe6Init(); - } OvmsVehicleMaxe6Init __attribute__ ((init_priority (9000))); +{ +public: OvmsVehicleMaxe6Init(); +} OvmsVehicleMaxe6Init __attribute__ ((init_priority (9000))); OvmsVehicleMaxe6Init::OvmsVehicleMaxe6Init() - { +{ ESP_LOGI(TAG, "Registering Vehicle: Maxus Euniq 6 (9000)"); MyVehicleFactory.RegisterVehicle("ME56","Maxus Euniq 6"); - } +} diff --git a/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.h b/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.h index 7cd27201b..3415faf5e 100644 --- a/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.h +++ b/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.h @@ -41,24 +41,24 @@ using namespace std; class OvmsVehicleMaxe6 : public OvmsVehicle - { - public: +{ +public: - OvmsVehicleMaxe6(); - ~OvmsVehicleMaxe6(); + OvmsVehicleMaxe6(); + ~OvmsVehicleMaxe6(); - protected: - void Ticker1(uint32_t ticker) override; - - private: - void IncomingFrameCan1(CAN_frame_t* p_frame) override; - - struct { - uint8_t byte[8]; - uint8_t status; - uint16_t id; - } send_can_buffer; - }; +protected: + void Ticker1(uint32_t ticker) override; + +private: + void IncomingFrameCan1(CAN_frame_t* p_frame) override; + + struct { + uint8_t byte[8]; + uint8_t status; + uint16_t id; + } send_can_buffer; +}; #endif //#ifndef __VEHICLE_ME6_H__ From 05adc76e5ca2202148a79c73212ccfd10851bc26 Mon Sep 17 00:00:00 2001 From: axel troncoso Date: Mon, 19 Aug 2024 15:59:12 -0400 Subject: [PATCH 19/45] Refactor(replacing-tabs-for-spaces) --- .../vehicle_maxus_euniq6/src/vehicle_me6.cpp | 106 +++++++++--------- 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.cpp b/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.cpp index 26070c119..d911ffa64 100644 --- a/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.cpp +++ b/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.cpp @@ -136,59 +136,59 @@ void OvmsVehicleMaxe6::IncomingFrameCan1(CAN_frame_t *p_frame) uint8_t *data = p_frame->data.u8; switch (p_frame->MsgID) - { - case 0x0c9: - { - StdMetrics.ms_v_charge_inprogress->SetValue( - CAN_BIT(2,0) && CAN_BIT(2,1) && CAN_BIT(2,2) - ); - break; - } - case 0x281: - { - StdMetrics.ms_v_env_locked->SetValue( - CAN_BIT(1,0) && CAN_BIT(1,2) && CAN_BIT(1,4) && CAN_BIT(1,6) && - !StdMetrics.ms_v_door_fl->AsBool() && - !StdMetrics.ms_v_door_fr->AsBool() && - !StdMetrics.ms_v_door_rl->AsBool() && - !StdMetrics.ms_v_door_rr->AsBool() && - !StdMetrics.ms_v_door_trunk->AsBool()); - break; - } - case 0x46a: - { - StdMetrics.ms_v_door_fl->SetValue(CAN_BIT(0, 0)); - StdMetrics.ms_v_door_fr->SetValue(CAN_BIT(0, 3)); - StdMetrics.ms_v_door_rr->SetValue(CAN_BIT(0, 5)); - StdMetrics.ms_v_door_rl->SetValue(CAN_BIT(0, 7)); - StdMetrics.ms_v_door_trunk->SetValue(CAN_BIT(1, 1)); - break; - } - case 0x540: - { - StdMetrics.ms_v_pos_odometer->SetValue(CAN_UINT24(0)); - break; - } - case 0x6f0: - { - StdMetrics.ms_v_pos_speed->SetValue(CAN_BYTE(4)); - break; - } - case 0x6f1: - { - StdMetrics.ms_v_env_awake->SetValue(CAN_BIT(4,7)); - StdMetrics.ms_v_env_on->SetValue(CAN_BIT(1,4) && CAN_BIT(4,7)); - break; - } - case 0x6f2: - { - StdMetrics.ms_v_bat_soc->SetValue(CAN_BYTE(1)); - // Units percentage. - StdMetrics.ms_v_bat_power->SetValue((CAN_BYTE(2) - 100) * 120, kW); - break; - } - default: - break; + { + case 0x0c9: + { + StdMetrics.ms_v_charge_inprogress->SetValue( + CAN_BIT(2,0) && CAN_BIT(2,1) && CAN_BIT(2,2) + ); + break; + } + case 0x281: + { + StdMetrics.ms_v_env_locked->SetValue( + CAN_BIT(1,0) && CAN_BIT(1,2) && CAN_BIT(1,4) && CAN_BIT(1,6) && + !StdMetrics.ms_v_door_fl->AsBool() && + !StdMetrics.ms_v_door_fr->AsBool() && + !StdMetrics.ms_v_door_rl->AsBool() && + !StdMetrics.ms_v_door_rr->AsBool() && + !StdMetrics.ms_v_door_trunk->AsBool()); + break; + } + case 0x46a: + { + StdMetrics.ms_v_door_fl->SetValue(CAN_BIT(0, 0)); + StdMetrics.ms_v_door_fr->SetValue(CAN_BIT(0, 3)); + StdMetrics.ms_v_door_rr->SetValue(CAN_BIT(0, 5)); + StdMetrics.ms_v_door_rl->SetValue(CAN_BIT(0, 7)); + StdMetrics.ms_v_door_trunk->SetValue(CAN_BIT(1, 1)); + break; + } + case 0x540: + { + StdMetrics.ms_v_pos_odometer->SetValue(CAN_UINT24(0)); + break; + } + case 0x6f0: + { + StdMetrics.ms_v_pos_speed->SetValue(CAN_BYTE(4)); + break; + } + case 0x6f1: + { + StdMetrics.ms_v_env_awake->SetValue(CAN_BIT(4,7)); + StdMetrics.ms_v_env_on->SetValue(CAN_BIT(1,4) && CAN_BIT(4,7)); + break; + } + case 0x6f2: + { + StdMetrics.ms_v_bat_soc->SetValue(CAN_BYTE(1)); + // Units percentage. + StdMetrics.ms_v_bat_power->SetValue((CAN_BYTE(2) - 100) * 120, kW); + break; + } + default: + break; } } From fdd6f7ca17a9668c61293153f99474bd4f6eb679 Mon Sep 17 00:00:00 2001 From: axel troncoso Date: Mon, 19 Aug 2024 16:01:07 -0400 Subject: [PATCH 20/45] Feat(Refactor-allign-table) --- .../vehicle_maxus_euniq6/src/vehicle_me6.cpp | 26 ++++++++----------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.cpp b/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.cpp index d911ffa64..7062656ac 100644 --- a/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.cpp +++ b/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.cpp @@ -106,31 +106,27 @@ void OvmsVehicleMaxe6::IncomingFrameCan1(CAN_frame_t *p_frame) /* BASIC METRICS - StdMetrics.ms_v_pos_speed ok + StdMetrics.ms_v_pos_speed ok StdMetrics.ms_v_bat_soc ok - StdMetrics.ms_v_pos_odometer ok + StdMetrics.ms_v_pos_odometer ok - StdMetrics.ms_v_door_fl ok; yes when open, no when closed + StdMetrics.ms_v_door_fl ok StdMetrics.ms_v_door_fr ok StdMetrics.ms_v_door_rl ok StdMetrics.ms_v_door_rr ok StdMetrics.ms_v_trunk ok - StdMetrics.ms_v_env_locked ok + StdMetrics.ms_v_env_locked ok - StdMetrics.ms_v_env_onepedal - - StdMetrics.ms_v_env_efficiencymode - - StdMetrics.ms_v_env_regenlevel Percentage - + StdMetrics.ms_v_bat_current - + StdMetrics.ms_v_bat_voltage - + StdMetrics.ms_v_bat_power wip (percentage units) - StdMetrics.ms_v_bat_current - - StdMetrics.ms_v_bat_voltage - - StdMetrics.ms_v_bat_power wip esta en porcentaje + StdMetrics.ms_v_charge_inprogress ok - StdMetrics.ms_v_charge_inprogress ok + StdMetrics.ms_v_env_on ok + StdMetrics.ms_v_env_awake ok - StdMetrics.ms_v_env_on ok - StdMetrics.ms_v_env_awake ok - - StdMetrics.ms_v_env_aux12v ok + StdMetrics.ms_v_env_aux12v ok */ uint8_t *data = p_frame->data.u8; From 10b7d5cdc14eef82b2b72ada4173d07001aeadc3 Mon Sep 17 00:00:00 2001 From: axel troncoso Date: Mon, 19 Aug 2024 16:40:21 -0400 Subject: [PATCH 21/45] Refactor(removing-unnecessary-data-buffer) --- .../src/vehicle_maple_60s.cpp | 23 ------------------- .../vehicle_maple60s/src/vehicle_maple_60s.h | 6 ----- 2 files changed, 29 deletions(-) diff --git a/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.cpp b/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.cpp index ab4182924..bbf292853 100644 --- a/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.cpp +++ b/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.cpp @@ -55,11 +55,6 @@ OvmsVehicleMaple60S::OvmsVehicleMaple60S() { ESP_LOGI(TAG, "Maple 60s vehicle module"); - send_can_buffer.id = 0; - send_can_buffer.status = 0; - - memset(send_can_buffer.byte, 0, sizeof(send_can_buffer.byte)); - m_door_lock_status.fill(false); StdMetrics.ms_v_bat_12v_voltage->SetValue(12.5, Volts); @@ -88,24 +83,6 @@ void OvmsVehicleMaple60S::Ticker1(uint32_t ticker) void OvmsVehicleMaple60S::IncomingFrameCan1(CAN_frame_t *p_frame) { - uint8_t *d = p_frame->data.u8; - - // Check if response is from synchronous can message - if (send_can_buffer.status == 0xff && p_frame->MsgID == (send_can_buffer.id + 0x08)) - { - // Store message bytes so that the async method can continue - send_can_buffer.status = 3; - - send_can_buffer.byte[0] = d[0]; - send_can_buffer.byte[1] = d[1]; - send_can_buffer.byte[2] = d[2]; - send_can_buffer.byte[3] = d[3]; - send_can_buffer.byte[4] = d[4]; - send_can_buffer.byte[5] = d[5]; - send_can_buffer.byte[6] = d[6]; - send_can_buffer.byte[7] = d[7]; - } - /* BASIC METRICS StdMetrics.ms_v_pos_speed ok diff --git a/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.h b/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.h index 9b7f97513..945638ac6 100644 --- a/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.h +++ b/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.h @@ -45,12 +45,6 @@ class OvmsVehicleMaple60S : public OvmsVehicle void Ticker1(uint32_t ticker) override; private: - struct { - uint8_t byte[8]; - uint8_t status; - uint16_t id; - } send_can_buffer; - std::array m_door_lock_status; }; From 9616f0dc69e8fb9204d7f5aa2f59319e1df63995 Mon Sep 17 00:00:00 2001 From: axel troncoso Date: Mon, 19 Aug 2024 16:42:17 -0400 Subject: [PATCH 22/45] Refactor(removing-unnecessary-data-buffer) --- .../components/vehicle_maple60s/src/vehicle_maple_60s.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.cpp b/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.cpp index bbf292853..08acae91a 100644 --- a/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.cpp +++ b/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.cpp @@ -57,7 +57,6 @@ OvmsVehicleMaple60S::OvmsVehicleMaple60S() m_door_lock_status.fill(false); - StdMetrics.ms_v_bat_12v_voltage->SetValue(12.5, Volts); StdMetrics.ms_v_charge_inprogress->SetValue(false); StdMetrics.ms_v_env_on->SetValue(false); StdMetrics.ms_v_env_locked->SetValue(false); @@ -69,9 +68,6 @@ OvmsVehicleMaple60S::OvmsVehicleMaple60S() RegisterCanBus(1, CAN_MODE_LISTEN, CAN_SPEED_500KBPS); } -/** - * Destructor - */ OvmsVehicleMaple60S::~OvmsVehicleMaple60S() { ESP_LOGI(TAG, "Shutdown Maple 60S vehicle module"); From 2649e38bd8d727ac3b08bdd8a3507db4fe03c927 Mon Sep 17 00:00:00 2001 From: axel troncoso Date: Mon, 19 Aug 2024 16:51:50 -0400 Subject: [PATCH 23/45] Refactor(remove-unnecessary-buffer) --- .../vehicle_maxus_euniq6/src/vehicle_me6.cpp | 39 ++----------------- .../vehicle_maxus_euniq6/src/vehicle_me6.h | 6 --- 2 files changed, 3 insertions(+), 42 deletions(-) diff --git a/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.cpp b/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.cpp index 7062656ac..1d026f503 100644 --- a/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.cpp +++ b/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.cpp @@ -55,23 +55,9 @@ OvmsVehicleMaxe6::OvmsVehicleMaxe6() // Init CAN: RegisterCanBus(1,CAN_MODE_ACTIVE,CAN_SPEED_500KBPS); - - // Init CAN buffer: - send_can_buffer.id = 0; - send_can_buffer.status = 0; - memset(send_can_buffer.byte, 0, sizeof(send_can_buffer.byte)); - - // Init BMS: - BmsSetCellArrangementVoltage(96, 16); - BmsSetCellArrangementTemperature(16, 1); - BmsSetCellLimitsVoltage(2.0, 5.0); - BmsSetCellLimitsTemperature(-39, 200); - BmsSetCellDefaultThresholdsVoltage(0.020, 0.030); - BmsSetCellDefaultThresholdsTemperature(2.0, 3.0); // Init Energy: StdMetrics.ms_v_charge_mode->SetValue("standard"); - StdMetrics.ms_v_env_ctrl_login->SetValue(true); // Require GPS: MyEvents.SignalEvent("vehicle.require.gps", NULL); @@ -85,25 +71,6 @@ OvmsVehicleMaxe6::~OvmsVehicleMaxe6() void OvmsVehicleMaxe6::IncomingFrameCan1(CAN_frame_t *p_frame) { - - uint8_t *d = p_frame->data.u8; - - // Check if response is from synchronous can message - if (send_can_buffer.status == 0xff && p_frame->MsgID == (send_can_buffer.id + 0x08)) - { - // Store message bytes so that the async method can continue - send_can_buffer.status = 3; - - send_can_buffer.byte[0] = d[0]; - send_can_buffer.byte[1] = d[1]; - send_can_buffer.byte[2] = d[2]; - send_can_buffer.byte[3] = d[3]; - send_can_buffer.byte[4] = d[4]; - send_can_buffer.byte[5] = d[5]; - send_can_buffer.byte[6] = d[6]; - send_can_buffer.byte[7] = d[7]; - } - /* BASIC METRICS StdMetrics.ms_v_pos_speed ok @@ -121,12 +88,12 @@ void OvmsVehicleMaxe6::IncomingFrameCan1(CAN_frame_t *p_frame) StdMetrics.ms_v_bat_voltage - StdMetrics.ms_v_bat_power wip (percentage units) - StdMetrics.ms_v_charge_inprogress ok + StdMetrics.ms_v_charge_inprogress rev StdMetrics.ms_v_env_on ok StdMetrics.ms_v_env_awake ok - StdMetrics.ms_v_env_aux12v ok + StdMetrics.ms_v_env_aux12v rev */ uint8_t *data = p_frame->data.u8; @@ -178,8 +145,8 @@ void OvmsVehicleMaxe6::IncomingFrameCan1(CAN_frame_t *p_frame) } case 0x6f2: { - StdMetrics.ms_v_bat_soc->SetValue(CAN_BYTE(1)); // Units percentage. + StdMetrics.ms_v_bat_soc->SetValue(CAN_BYTE(1)); StdMetrics.ms_v_bat_power->SetValue((CAN_BYTE(2) - 100) * 120, kW); break; } diff --git a/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.h b/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.h index 3415faf5e..18f11bc99 100644 --- a/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.h +++ b/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.h @@ -52,12 +52,6 @@ class OvmsVehicleMaxe6 : public OvmsVehicle private: void IncomingFrameCan1(CAN_frame_t* p_frame) override; - - struct { - uint8_t byte[8]; - uint8_t status; - uint16_t id; - } send_can_buffer; }; #endif //#ifndef __VEHICLE_ME6_H__ From 5ffdf930755a4b940914e88886268f71f724f4eb Mon Sep 17 00:00:00 2001 From: Jaime Date: Mon, 19 Aug 2024 18:25:21 -0400 Subject: [PATCH 24/45] rename functions --- .../components/esp32wifi/src/esp32wifi.cpp | 4 +- .../ovms_server_v3/src/ovms_server_v3.cpp | 44 ++++++++----------- .../ovms_server_v3/src/ovms_server_v3.h | 3 +- vehicle/OVMS.V3/main/ovms_netmanager.cpp | 39 +++++++++------- vehicle/OVMS.V3/main/ovms_netmanager.h | 2 +- 5 files changed, 45 insertions(+), 47 deletions(-) diff --git a/vehicle/OVMS.V3/components/esp32wifi/src/esp32wifi.cpp b/vehicle/OVMS.V3/components/esp32wifi/src/esp32wifi.cpp index 31eb47613..30ccb1c22 100644 --- a/vehicle/OVMS.V3/components/esp32wifi/src/esp32wifi.cpp +++ b/vehicle/OVMS.V3/components/esp32wifi/src/esp32wifi.cpp @@ -1022,11 +1022,11 @@ void esp32wifi::EventWifiGotIp(std::string event, void* data) } bool esp32wifi::WifiHasIp() -{ + { char numstr[150]; sprintf(numstr, IPSTR, IP2STR(&m_ip_info_sta.ip)); return strcmp(numstr, "0.0.0.0") == 1; -} + } void esp32wifi::EventWifiLostIp(std::string event, void* data) { diff --git a/vehicle/OVMS.V3/components/ovms_server_v3/src/ovms_server_v3.cpp b/vehicle/OVMS.V3/components/ovms_server_v3/src/ovms_server_v3.cpp index 88160a8d2..e99cf3647 100644 --- a/vehicle/OVMS.V3/components/ovms_server_v3/src/ovms_server_v3.cpp +++ b/vehicle/OVMS.V3/components/ovms_server_v3/src/ovms_server_v3.cpp @@ -94,7 +94,7 @@ static void OvmsServerV3MongooseCallback(struct mg_connection *nc, int ev, void StandardMetrics.ms_s_v3_connected->SetValue(false); StandardMetrics.ms_s_v3_peers->SetValue(0); MyOvmsServerV3->SetStatus("Error: Connection failed", true, OvmsServerV3::WaitReconnect); - MyOvmsServerV3->m_connretry = 30; + MyOvmsServerV3->m_connretry = 60; } } } @@ -107,7 +107,7 @@ static void OvmsServerV3MongooseCallback(struct mg_connection *nc, int ev, void if (MyOvmsServerV3) { MyOvmsServerV3->Disconnect(); - MyOvmsServerV3->m_connretry = 30; + MyOvmsServerV3->m_connretry = 60; } } else @@ -137,13 +137,9 @@ static void OvmsServerV3MongooseCallback(struct mg_connection *nc, int ev, void msg->topic.p, (int) msg->payload.len, msg->payload.p); if (MyOvmsServerV3) { - if (MyOvmsServerV3->accept_command == 0) - { - MyOvmsServerV3->accept_command = 2; - MyOvmsServerV3->IncomingMsg( - std::string(msg->topic.p,msg->topic.len), - std::string(msg->payload.p,msg->payload.len)); - } + MyOvmsServerV3->IncomingMsg( + std::string(msg->topic.p,msg->topic.len), + std::string(msg->payload.p,msg->payload.len)); } if (msg->qos == 1) { @@ -215,8 +211,7 @@ OvmsServerV3::OvmsServerV3(const char* name) m_notify_data_waitcomp = 0; m_notify_data_waittype = NULL; m_notify_data_waitentry = NULL; - accept_command = 0; - connection_available = false; + m_connection_available = false; ESP_LOGI(TAG, "OVMS Server v3 running"); @@ -632,12 +627,12 @@ void OvmsServerV3::CountClients() void OvmsServerV3::Connect() { - if (!connection_available) - { - ESP_LOGE(TAG, "No connection available, waiting for network"); - m_connretry = 10; - return; - } + if (!m_connection_available) + { + ESP_LOGE(TAG, "No connection available, waiting for network"); + m_connretry = 10; + return; + } m_msgid = 1; m_vehicleid = MyConfig.GetParamValue("vehicle", "id"); m_server = MyConfig.GetParamValue("server.v3", "server"); @@ -890,21 +885,18 @@ void OvmsServerV3::NetmanStop(std::string event, void* data) void OvmsServerV3::Ticker1(std::string event, void* data) { - connection_available = StdMetrics.ms_m_net_connected->AsBool() && + m_connection_available = StdMetrics.ms_m_net_connected->AsBool() && StdMetrics.ms_m_net_ip->AsBool(); - if (accept_command != 0) - { - accept_command--; - } - if (!connection_available && m_mgconn) + + if (!m_connection_available && m_mgconn) { - Disconnect(); - m_connretry = 10; + Disconnect(); + m_connretry = 10; } if (m_connretry > 0) { - if (connection_available) + if (m_connection_available) { m_connretry--; if (m_connretry == 0) diff --git a/vehicle/OVMS.V3/components/ovms_server_v3/src/ovms_server_v3.h b/vehicle/OVMS.V3/components/ovms_server_v3/src/ovms_server_v3.h index 80fcc241d..812f0791c 100644 --- a/vehicle/OVMS.V3/components/ovms_server_v3/src/ovms_server_v3.h +++ b/vehicle/OVMS.V3/components/ovms_server_v3/src/ovms_server_v3.h @@ -96,7 +96,6 @@ class OvmsServerV3 : public OvmsServer OvmsMutex m_mgconn_mutex; int m_connretry; bool m_sendall; - int accept_command; int m_msgid; int m_lasttx; int m_lasttx_sendall; @@ -109,7 +108,7 @@ class OvmsServerV3 : public OvmsServer int m_updatetime_charging; int m_updatetime_sendall; - bool connection_available; + bool m_connection_available; bool m_notify_info_pending; bool m_notify_error_pending; bool m_notify_alert_pending; diff --git a/vehicle/OVMS.V3/main/ovms_netmanager.cpp b/vehicle/OVMS.V3/main/ovms_netmanager.cpp index fe4c01693..ce366a389 100644 --- a/vehicle/OVMS.V3/main/ovms_netmanager.cpp +++ b/vehicle/OVMS.V3/main/ovms_netmanager.cpp @@ -344,7 +344,7 @@ void network_connections(int verbosity, OvmsWriter* writer, OvmsCommand* cmd, in OvmsNetManager::OvmsNetManager() { ESP_LOGI(TAG, "Initialising NETMANAGER (8999)"); - not_connected_counter = 0; + m_not_connected_counter = 0; m_connected_wifi = false; m_connected_modem = false; m_connected_any = false; @@ -659,40 +659,47 @@ void OvmsNetManager::WifiApStaDisconnect(std::string event, void* data) void OvmsNetManager::Ticker1(std::string event, void *data) { - if (!m_connected_any){ + if (!m_connected_any) + { StdMetrics.ms_m_net_ip->SetValue(false); StdMetrics.ms_m_net_connected->SetValue(false); - } + } else - { + { StdMetrics.ms_m_net_connected->SetValue(true); bool connected = false; // respect the priority of wifi over modem - if (m_connected_modem){ - if (MyPeripherals && MyPeripherals->m_cellular_modem) + if (m_connected_modem) { + if (MyPeripherals && MyPeripherals->m_cellular_modem) + { connected = MyPeripherals->m_cellular_modem->ModemIsNetMode() && MyPeripherals->m_cellular_modem->m_mux->IsMuxUp() && MyPeripherals->m_cellular_modem->m_ppp->m_connected; + } } - } - if (m_connected_wifi){ - if (MyPeripherals && MyPeripherals->m_esp32wifi) + if (m_connected_wifi) { + if (MyPeripherals && MyPeripherals->m_esp32wifi) + { connected = MyPeripherals->m_esp32wifi->WifiHasIp(); + } } - } StdMetrics.ms_m_net_ip->SetValue(connected); - if (m_connected_any && !connected){ - not_connected_counter++; - if (not_connected_counter > 300){ + if (m_connected_any && !connected) + { + m_not_connected_counter++; + if (m_not_connected_counter > 300) + { MyBoot.Restart(); + } + } + else + { + m_not_connected_counter = 0; } - } else { - not_connected_counter = 0; } } - } void OvmsNetManager::ModemUp(std::string event, void* data) { diff --git a/vehicle/OVMS.V3/main/ovms_netmanager.h b/vehicle/OVMS.V3/main/ovms_netmanager.h index c81cca2b5..e4d7c11ee 100644 --- a/vehicle/OVMS.V3/main/ovms_netmanager.h +++ b/vehicle/OVMS.V3/main/ovms_netmanager.h @@ -138,7 +138,7 @@ class OvmsNetManager void SetDNSServer(ip_addr_t* dnsstore); public: - int not_connected_counter; + int m_not_connected_counter; bool m_connected_wifi; bool m_connected_modem; bool m_connected_any; From 017c1d3f7e6dccea1cd4464a502d72ec8960cf6e Mon Sep 17 00:00:00 2001 From: Jaime Date: Tue, 20 Aug 2024 11:52:57 -0400 Subject: [PATCH 25/45] wifi ip via events --- .../OVMS.V3/components/ovms_cellular/src/ovms_cellular.cpp | 2 +- .../components/ovms_server_v3/src/ovms_server_v3.cpp | 7 +++---- vehicle/OVMS.V3/main/ovms_netmanager.cpp | 3 +-- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/vehicle/OVMS.V3/components/ovms_cellular/src/ovms_cellular.cpp b/vehicle/OVMS.V3/components/ovms_cellular/src/ovms_cellular.cpp index e477a3ea8..3445a008e 100644 --- a/vehicle/OVMS.V3/components/ovms_cellular/src/ovms_cellular.cpp +++ b/vehicle/OVMS.V3/components/ovms_cellular/src/ovms_cellular.cpp @@ -360,7 +360,7 @@ void modem::SetPowerMode(PowerMode powermode) bool modem::ModemIsNetMode() { - return m_state1 == NetMode; + return m_state1 == NetMode; } void modem::AutoInit() diff --git a/vehicle/OVMS.V3/components/ovms_server_v3/src/ovms_server_v3.cpp b/vehicle/OVMS.V3/components/ovms_server_v3/src/ovms_server_v3.cpp index e99cf3647..8ca4ebdb8 100644 --- a/vehicle/OVMS.V3/components/ovms_server_v3/src/ovms_server_v3.cpp +++ b/vehicle/OVMS.V3/components/ovms_server_v3/src/ovms_server_v3.cpp @@ -136,10 +136,9 @@ static void OvmsServerV3MongooseCallback(struct mg_connection *nc, int ev, void ESP_LOGI(TAG, "Incoming message %.*s: %.*s", (int) msg->topic.len, msg->topic.p, (int) msg->payload.len, msg->payload.p); if (MyOvmsServerV3) - { - MyOvmsServerV3->IncomingMsg( - std::string(msg->topic.p,msg->topic.len), - std::string(msg->payload.p,msg->payload.len)); + { + MyOvmsServerV3->IncomingMsg(std::string(msg->topic.p, msg->topic.len), + std::string(msg->payload.p, msg->payload.len)); } if (msg->qos == 1) { diff --git a/vehicle/OVMS.V3/main/ovms_netmanager.cpp b/vehicle/OVMS.V3/main/ovms_netmanager.cpp index ce366a389..efdc99856 100644 --- a/vehicle/OVMS.V3/main/ovms_netmanager.cpp +++ b/vehicle/OVMS.V3/main/ovms_netmanager.cpp @@ -415,6 +415,7 @@ OvmsNetManager::OvmsNetManager() // dns Space-separated list of DNS servers // wifi.sq.good Threshold for usable wifi signal [dBm], default -87 // wifi.sq.bad Threshold for unusable wifi signal [dBm], default -89 + StdMetrics.ms_m_net_ip->SetValue(false); #ifdef CONFIG_OVMS_COMP_WIFI MyMetrics.RegisterListener(TAG, MS_N_WIFI_SQ, std::bind(&OvmsNetManager::WifiStaCheckSQ, this, _1)); @@ -661,7 +662,6 @@ void OvmsNetManager::Ticker1(std::string event, void *data) { if (!m_connected_any) { - StdMetrics.ms_m_net_ip->SetValue(false); StdMetrics.ms_m_net_connected->SetValue(false); } else @@ -685,7 +685,6 @@ void OvmsNetManager::Ticker1(std::string event, void *data) connected = MyPeripherals->m_esp32wifi->WifiHasIp(); } } - StdMetrics.ms_m_net_ip->SetValue(connected); if (m_connected_any && !connected) { m_not_connected_counter++; From 31784d989918a8b5f815dd54382572ee26ac248f Mon Sep 17 00:00:00 2001 From: axel troncoso Date: Tue, 20 Aug 2024 15:15:37 -0400 Subject: [PATCH 26/45] Feat(rename-id-for-maxus-euniq6-to-not-conflict-with-existing) --- .../OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.cpp b/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.cpp index 1d026f503..6d748a478 100644 --- a/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.cpp +++ b/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.cpp @@ -168,5 +168,5 @@ OvmsVehicleMaxe6Init::OvmsVehicleMaxe6Init() { ESP_LOGI(TAG, "Registering Vehicle: Maxus Euniq 6 (9000)"); - MyVehicleFactory.RegisterVehicle("ME56","Maxus Euniq 6"); + MyVehicleFactory.RegisterVehicle("ME6","Maxus Euniq 6"); } From e8fb879fd0df8065c6d02ecad24a9963ec774faa Mon Sep 17 00:00:00 2001 From: Jaime Date: Wed, 21 Aug 2024 15:00:09 -0400 Subject: [PATCH 27/45] reboot if no ip and good connection signal --- .../components/esp32wifi/src/esp32wifi.cpp | 35 ++++++++++++--- .../components/esp32wifi/src/esp32wifi.h | 4 ++ .../ovms_cellular/src/ovms_cellular.cpp | 26 ++++++++++- .../ovms_cellular/src/ovms_cellular.h | 4 ++ vehicle/OVMS.V3/main/metrics_standard.cpp | 5 ++- vehicle/OVMS.V3/main/metrics_standard.h | 6 ++- vehicle/OVMS.V3/main/ovms_netmanager.cpp | 43 ++++++------------- vehicle/OVMS.V3/main/ovms_netmanager.h | 2 + 8 files changed, 83 insertions(+), 42 deletions(-) diff --git a/vehicle/OVMS.V3/components/esp32wifi/src/esp32wifi.cpp b/vehicle/OVMS.V3/components/esp32wifi/src/esp32wifi.cpp index 30ccb1c22..50ef7edd4 100644 --- a/vehicle/OVMS.V3/components/esp32wifi/src/esp32wifi.cpp +++ b/vehicle/OVMS.V3/components/esp32wifi/src/esp32wifi.cpp @@ -375,6 +375,7 @@ esp32wifi::esp32wifi(const char* name) m_sta_reconnect = 0; m_sta_connected = false; m_sta_rssi = -1270; + m_good_signal = false; memset(&m_wifi_ap_cfg,0,sizeof(m_wifi_ap_cfg)); memset(&m_wifi_sta_cfg,0,sizeof(m_wifi_sta_cfg)); memset(&m_mac_ap,0,sizeof(m_mac_ap)); @@ -399,6 +400,9 @@ esp32wifi::esp32wifi(const char* name) MyEvents.RegisterEvent(TAG,"system.wifi.ap.sta.connected",std::bind(&esp32wifi::EventWifiApUpdate, this, _1, _2)); MyEvents.RegisterEvent(TAG,"system.wifi.ap.sta.disconnected",std::bind(&esp32wifi::EventWifiApUpdate, this, _1, _2)); MyEvents.RegisterEvent(TAG,"system.shuttingdown",std::bind(&esp32wifi::EventSystemShuttingDown, this, _1, _2)); + MyEvents.RegisterEvent(TAG,"config.mounted", std::bind(&esp32wifi::ConfigChanged, this, _1, _2)); + MyEvents.RegisterEvent(TAG,"config.changed", std::bind(&esp32wifi::ConfigChanged, this, _1, _2)); + ConfigChanged("config.mounted", NULL); } esp32wifi::~esp32wifi() @@ -996,13 +1000,19 @@ void esp32wifi::UpdateNetMetrics() m_sta_rssi = -1270; } - StdMetrics.ms_m_net_wifi_network->SetValue(GetSSID()); - StdMetrics.ms_m_net_wifi_sq->SetValue((float)m_sta_rssi/10, dbm); - if (StdMetrics.ms_m_net_type->AsString() == "wifi") - { - StdMetrics.ms_m_net_provider->SetValue(GetSSID()); - StdMetrics.ms_m_net_sq->SetValue((int)(m_sta_rssi-5)/10, dbm); - } + float current_dbm = (float)m_sta_rssi / 10; + StdMetrics.ms_m_net_wifi_network->SetValue(GetSSID()); + StdMetrics.ms_m_net_wifi_sq->SetValue(current_dbm, dbm); + if (StdMetrics.ms_m_net_type->AsString() == "wifi") + { + StdMetrics.ms_m_net_provider->SetValue(GetSSID()); + StdMetrics.ms_m_net_sq->SetValue((int)(m_sta_rssi-5)/10, dbm); + if (m_good_signal && current_dbm < m_bad_dbm) + m_good_signal = false; + if (!m_good_signal && current_dbm > m_good_dbm) + m_good_signal = true; + StdMetrics.ms_m_net_good_sq->SetValue(m_good_signal); + } } void esp32wifi::EventWifiGotIp(std::string event, void* data) @@ -1400,6 +1410,17 @@ void esp32wifi::OutputStatus(int verbosity, OvmsWriter* writer) } } +void esp32wifi::ConfigChanged(std::string event, void* data) + { + OvmsConfigParam* param = (OvmsConfigParam*)data; + if (event == "config.mounted" || !param || param->GetName() == "network") + { + // Network config has been changed, apply: + m_good_dbm = MyConfig.GetParamValueFloat("network", "wifi.sq.good", -87); + m_bad_dbm = MyConfig.GetParamValueFloat("network", "wifi.sq.bad", -89); + } + } + void esp32wifi::StartDhcpClient() { if (m_mode == ESP32WIFI_MODE_CLIENT || m_mode == ESP32WIFI_MODE_APCLIENT) diff --git a/vehicle/OVMS.V3/components/esp32wifi/src/esp32wifi.h b/vehicle/OVMS.V3/components/esp32wifi/src/esp32wifi.h index 685d8b55f..6d6d8fb90 100644 --- a/vehicle/OVMS.V3/components/esp32wifi/src/esp32wifi.h +++ b/vehicle/OVMS.V3/components/esp32wifi/src/esp32wifi.h @@ -101,6 +101,7 @@ class esp32wifi : public pcp, public InternalRamAllocated void EventWifiScanDone(std::string event, void* data); void EventSystemShuttingDown(std::string event, void* data); void OutputStatus(int verbosity, OvmsWriter* writer); + void ConfigChanged(std::string event, void *data); protected: bool m_poweredup; @@ -133,6 +134,9 @@ class esp32wifi : public pcp, public InternalRamAllocated uint32_t m_sta_reconnect; wifi_ap_record_t m_sta_ap_info; int m_sta_rssi; // smoothed RSSI [dBm/10] + float m_good_dbm; + float m_bad_dbm; + bool m_good_signal; }; #endif //#ifndef __ESP32WIFI_H__ diff --git a/vehicle/OVMS.V3/components/ovms_cellular/src/ovms_cellular.cpp b/vehicle/OVMS.V3/components/ovms_cellular/src/ovms_cellular.cpp index 3445a008e..b73b8774f 100644 --- a/vehicle/OVMS.V3/components/ovms_cellular/src/ovms_cellular.cpp +++ b/vehicle/OVMS.V3/components/ovms_cellular/src/ovms_cellular.cpp @@ -41,6 +41,7 @@ static const char *TAG = "cellular"; #include "ovms_events.h" #include "ovms_notify.h" #include "ovms_boot.h" +#include "ovms_config.h" //////////////////////////////////////////////////////////////////////////////// // Global convenience variables @@ -292,6 +293,7 @@ modem::modem(const char* name, uart_port_t uartnum, int baud, int rxpin, int txp for (size_t k=0; kGetName() == "network") + { + // Network config has been changed, apply: + m_good_dbm = MyConfig.GetParamValueFloat("network", "modem.sq.good", -95); + m_bad_dbm = MyConfig.GetParamValueFloat("network", "modem.sq.bad", -93); + } + } + void modem::IncomingMuxData(GsmMuxChannel* channel) { // The MUX has indicated there is data on the specified channel @@ -1621,10 +1638,16 @@ void modem::SetSignalQuality(int newsq) { m_sq = newsq; ESP_LOGD(TAG, "Signal Quality is: %d (%d dBm)", m_sq, UnitConvert(sq, dbm, m_sq)); + float current_dbm = UnitConvert(sq, dbm, m_sq); StdMetrics.ms_m_net_mdm_sq->SetValue(m_sq, sq); if (StdMetrics.ms_m_net_type->AsString() == "modem") { StdMetrics.ms_m_net_sq->SetValue(m_sq, sq); + if (m_good_signal && current_dbm < m_bad_dbm) + m_good_signal = false; + if (!m_good_signal && current_dbm > m_good_dbm) + m_good_signal = true; + StdMetrics.ms_m_net_good_sq->SetValue(m_good_signal); } } } @@ -1639,6 +1662,7 @@ void modem::ClearNetMetrics() StdMetrics.ms_m_net_mdm_network->Clear(); m_sq = 99; + m_good_signal = false; StdMetrics.ms_m_net_mdm_sq->Clear(); if (StdMetrics.ms_m_net_type->AsString() == "modem") diff --git a/vehicle/OVMS.V3/components/ovms_cellular/src/ovms_cellular.h b/vehicle/OVMS.V3/components/ovms_cellular/src/ovms_cellular.h index a47ac0a4a..2bc3e5204 100644 --- a/vehicle/OVMS.V3/components/ovms_cellular/src/ovms_cellular.h +++ b/vehicle/OVMS.V3/components/ovms_cellular/src/ovms_cellular.h @@ -65,6 +65,9 @@ class modem : public pcp, public InternalRamAllocated int m_txpin; int m_pwregpio; int m_dtregpio; + float m_good_dbm; + float m_bad_dbm; + bool m_good_signal; public: typedef enum @@ -212,6 +215,7 @@ class modem : public pcp, public InternalRamAllocated void Task(); void Ticker(std::string event, void* data); void EventListener(std::string event, void* data); + void ConfigChanged(std::string event, void *data); void IncomingMuxData(GsmMuxChannel* channel); void SendSetState1(modem_state1_t newstate); bool IsStarted(); diff --git a/vehicle/OVMS.V3/main/metrics_standard.cpp b/vehicle/OVMS.V3/main/metrics_standard.cpp index c11c6c175..840181aaf 100644 --- a/vehicle/OVMS.V3/main/metrics_standard.cpp +++ b/vehicle/OVMS.V3/main/metrics_standard.cpp @@ -48,6 +48,9 @@ MetricsStandard::MetricsStandard() ms_m_net_type = new OvmsMetricString(MS_N_TYPE, SM_STALE_MAX); ms_m_net_sq = new OvmsMetricInt(MS_N_SQ, SM_STALE_MAX, dbm); ms_m_net_provider = new OvmsMetricString(MS_N_PROVIDER, SM_STALE_MAX); + ms_m_net_connected = new OvmsMetricBool(MS_N_CONNECTED); + ms_m_net_ip = new OvmsMetricBool(MS_N_IP); + ms_m_net_good_sq = new OvmsMetricBool(MS_N_GOOD_SQ); ms_m_net_wifi_sq = new OvmsMetricFloat(MS_N_WIFI_SQ, SM_STALE_MAX, dbm); ms_m_net_wifi_network = new OvmsMetricString(MS_N_WIFI_NETWORK, SM_STALE_MAX); ms_m_net_mdm_sq = new OvmsMetricFloat(MS_N_MDM_SQ, SM_STALE_MAX, dbm); @@ -56,8 +59,6 @@ MetricsStandard::MetricsStandard() ms_m_net_mdm_iccid = new OvmsMetricString(MS_N_MDM_ICCID, SM_STALE_MAX); ms_m_net_mdm_model = new OvmsMetricString(MS_N_MDM_MODEL, SM_STALE_MAX); ms_m_net_mdm_mode = new OvmsMetricString(MS_N_MDM_MODE, SM_STALE_MAX); - ms_m_net_connected = new OvmsMetricBool(MS_N_CONNECTED); - ms_m_net_ip = new OvmsMetricBool(MS_N_IP); #ifdef CONFIG_OVMS_COMP_MAX7317 ms_m_egpio_input = new OvmsMetricBitset<10,0>(MS_M_EGPIO_INPUT, SM_STALE_MAX); diff --git a/vehicle/OVMS.V3/main/metrics_standard.h b/vehicle/OVMS.V3/main/metrics_standard.h index 0ae98969b..9fd00e54f 100644 --- a/vehicle/OVMS.V3/main/metrics_standard.h +++ b/vehicle/OVMS.V3/main/metrics_standard.h @@ -50,6 +50,9 @@ #define MS_N_TYPE "m.net.type" #define MS_N_SQ "m.net.sq" +#define MS_N_CONNECTED "m.net.connected" +#define MS_N_IP "m.net.ip" +#define MS_N_GOOD_SQ "m.net.good.sq" #define MS_N_PROVIDER "m.net.provider" #define MS_N_MDM_ICCID "m.net.mdm.iccid" #define MS_N_MDM_MODEL "m.net.mdm.model" @@ -59,8 +62,6 @@ #define MS_N_MDM_MODE "m.net.mdm.mode" #define MS_N_WIFI_NETWORK "m.net.wifi.network" #define MS_N_WIFI_SQ "m.net.wifi.sq" -#define MS_N_CONNECTED "m.net.connected" -#define MS_N_IP "m.net.ip" #ifdef CONFIG_OVMS_COMP_MAX7317 #define MS_M_EGPIO_INPUT "m.egpio.input" @@ -301,6 +302,7 @@ class MetricsStandard OvmsMetricString* ms_m_net_mdm_mode; // Cellular connection mode and status OvmsMetricBool* ms_m_net_connected; // True = connected_any is true OvmsMetricBool* ms_m_net_ip; // True = device has ip available + OvmsMetricBool* ms_m_net_good_sq; // True = sq is above the configured threshold for sq usability #ifdef CONFIG_OVMS_COMP_MAX7317 OvmsMetricBitset<10,0>* ms_m_egpio_input; // EGPIO (MAX7317) input port state (ports 0…9) diff --git a/vehicle/OVMS.V3/main/ovms_netmanager.cpp b/vehicle/OVMS.V3/main/ovms_netmanager.cpp index efdc99856..8153c08c7 100644 --- a/vehicle/OVMS.V3/main/ovms_netmanager.cpp +++ b/vehicle/OVMS.V3/main/ovms_netmanager.cpp @@ -415,7 +415,6 @@ OvmsNetManager::OvmsNetManager() // dns Space-separated list of DNS servers // wifi.sq.good Threshold for usable wifi signal [dBm], default -87 // wifi.sq.bad Threshold for unusable wifi signal [dBm], default -89 - StdMetrics.ms_m_net_ip->SetValue(false); #ifdef CONFIG_OVMS_COMP_WIFI MyMetrics.RegisterListener(TAG, MS_N_WIFI_SQ, std::bind(&OvmsNetManager::WifiStaCheckSQ, this, _1)); @@ -503,7 +502,6 @@ void OvmsNetManager::WifiDisconnect() void OvmsNetManager::WifiStaGotIP(std::string event, void* data) { m_wifi_sta = true; - StdMetrics.ms_m_net_ip->SetValue(true); ESP_LOGI(TAG, "WIFI client got IP"); SaveDNSServer(m_dns_wifi); @@ -523,7 +521,6 @@ void OvmsNetManager::WifiStaLostIP(std::string event, void* data) // Re-prioritise, just in case, as Wifi stack seems to mess with this // (in particular if an AP interface is up, and STA goes down, Wifi // stack seems to switch default interface to AP) - StdMetrics.ms_m_net_ip->SetValue(false); PrioritiseAndIndicate(); #ifdef CONFIG_OVMS_SC_GPL_MONGOOSE ScheduleCleanup(); @@ -660,32 +657,9 @@ void OvmsNetManager::WifiApStaDisconnect(std::string event, void* data) void OvmsNetManager::Ticker1(std::string event, void *data) { - if (!m_connected_any) + if (m_cfg_reboot_no_connection) { - StdMetrics.ms_m_net_connected->SetValue(false); - } - else - { - StdMetrics.ms_m_net_connected->SetValue(true); - bool connected = false; - // respect the priority of wifi over modem - if (m_connected_modem) - { - if (MyPeripherals && MyPeripherals->m_cellular_modem) - { - connected = MyPeripherals->m_cellular_modem->ModemIsNetMode() && - MyPeripherals->m_cellular_modem->m_mux->IsMuxUp() && - MyPeripherals->m_cellular_modem->m_ppp->m_connected; - } - } - if (m_connected_wifi) - { - if (MyPeripherals && MyPeripherals->m_esp32wifi) - { - connected = MyPeripherals->m_esp32wifi->WifiHasIp(); - } - } - if (m_connected_any && !connected) + if (m_connected_any && !m_has_ip && StdMetrics.ms_m_net_good_sq->AsBool()) { m_not_connected_counter++; if (m_not_connected_counter > 300) @@ -771,8 +745,9 @@ void OvmsNetManager::ConfigChanged(std::string event, void* data) if (!param || param->GetName() == "network") { // Network config has been changed, apply: + m_cfg_reboot_no_connection = MyConfig.GetParamValueBool("network", "reboot.no.connection", false); m_cfg_wifi_sq_good = MyConfig.GetParamValueFloat("network", "wifi.sq.good", -87); - m_cfg_wifi_sq_bad = MyConfig.GetParamValueFloat("network", "wifi.sq.bad", -89); + m_cfg_wifi_sq_bad = MyConfig.GetParamValueFloat("network", "wifi.sq.bad", -89); if (m_cfg_wifi_sq_good < m_cfg_wifi_sq_bad) { float x = m_cfg_wifi_sq_good; @@ -896,12 +871,15 @@ void OvmsNetManager::PrioritiseAndIndicate() void OvmsNetManager::DoSafePrioritiseAndIndicate() { + ESP_LOGE(TAG, "DoSafePrioritiseAndIndicate"); const char *search = NULL; ip_addr_t* dns = NULL; // A convenient place to keep track of connectivity in general m_connected_any = m_connected_wifi || m_connected_modem; m_network_any = m_connected_wifi || m_connected_modem || m_wifi_ap; + StdMetrics.ms_m_net_connected->SetValue(m_connected_any); + // Priority order... if (m_connected_wifi) @@ -910,6 +888,7 @@ void OvmsNetManager::DoSafePrioritiseAndIndicate() SetNetType("wifi"); search = "st"; dns = m_dns_wifi; + m_has_ip = MyPeripherals->m_esp32wifi->WifiHasIp(); } else if (m_connected_modem) { @@ -917,9 +896,13 @@ void OvmsNetManager::DoSafePrioritiseAndIndicate() SetNetType("modem"); search = "pp"; dns = m_dns_modem; + m_has_ip = MyPeripherals->m_cellular_modem->ModemIsNetMode() && + MyPeripherals->m_cellular_modem->m_mux->IsMuxUp() && + MyPeripherals->m_cellular_modem->m_ppp->m_connected; } + StdMetrics.ms_m_net_ip->SetValue(m_has_ip); - if (search == NULL) + if (search == NULL) { SetNetType("none"); return; diff --git a/vehicle/OVMS.V3/main/ovms_netmanager.h b/vehicle/OVMS.V3/main/ovms_netmanager.h index e4d7c11ee..da329ceea 100644 --- a/vehicle/OVMS.V3/main/ovms_netmanager.h +++ b/vehicle/OVMS.V3/main/ovms_netmanager.h @@ -142,6 +142,7 @@ class OvmsNetManager bool m_connected_wifi; bool m_connected_modem; bool m_connected_any; + bool m_has_ip; bool m_wifi_sta; bool m_wifi_good; bool m_wifi_ap; @@ -152,6 +153,7 @@ class OvmsNetManager char m_previous_name[2]; protected: + bool m_cfg_reboot_no_connection; float m_cfg_wifi_sq_good; // config network wifi.sq.good [dBm] default -87 float m_cfg_wifi_sq_bad; // config network wifi.sq.bad [dBm] default -89 From 18cfb8a34929ee6356ae1e541c12e0dad17838d7 Mon Sep 17 00:00:00 2001 From: Jaime Date: Wed, 21 Aug 2024 15:27:56 -0400 Subject: [PATCH 28/45] server v3 connection takes into account usable signal quality --- .../OVMS.V3/components/ovms_cellular/src/ovms_cellular.cpp | 1 - .../components/ovms_server_v3/src/ovms_server_v3.cpp | 7 ++++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/vehicle/OVMS.V3/components/ovms_cellular/src/ovms_cellular.cpp b/vehicle/OVMS.V3/components/ovms_cellular/src/ovms_cellular.cpp index b73b8774f..e88fda2f3 100644 --- a/vehicle/OVMS.V3/components/ovms_cellular/src/ovms_cellular.cpp +++ b/vehicle/OVMS.V3/components/ovms_cellular/src/ovms_cellular.cpp @@ -1520,7 +1520,6 @@ void modem::EventListener(std::string event, void* data) void modem::ConfigChanged(std::string event, void* data) { - ESP_LOGE(TAG, "Network config has been changed, reconfiguring modem"); OvmsConfigParam* param = (OvmsConfigParam*)data; if (event == "config.mounted" || !param || param->GetName() == "network") { diff --git a/vehicle/OVMS.V3/components/ovms_server_v3/src/ovms_server_v3.cpp b/vehicle/OVMS.V3/components/ovms_server_v3/src/ovms_server_v3.cpp index 8ca4ebdb8..c73927b0f 100644 --- a/vehicle/OVMS.V3/components/ovms_server_v3/src/ovms_server_v3.cpp +++ b/vehicle/OVMS.V3/components/ovms_server_v3/src/ovms_server_v3.cpp @@ -137,8 +137,8 @@ static void OvmsServerV3MongooseCallback(struct mg_connection *nc, int ev, void msg->topic.p, (int) msg->payload.len, msg->payload.p); if (MyOvmsServerV3) { - MyOvmsServerV3->IncomingMsg(std::string(msg->topic.p, msg->topic.len), - std::string(msg->payload.p, msg->payload.len)); + MyOvmsServerV3->IncomingMsg(std::string(msg->topic.p,msg->topic.len), + std::string(msg->payload.p,msg->payload.len)); } if (msg->qos == 1) { @@ -885,7 +885,8 @@ void OvmsServerV3::NetmanStop(std::string event, void* data) void OvmsServerV3::Ticker1(std::string event, void* data) { m_connection_available = StdMetrics.ms_m_net_connected->AsBool() && - StdMetrics.ms_m_net_ip->AsBool(); + StdMetrics.ms_m_net_ip->AsBool() && + !StdMetrics.ms_m_net_good_sq->AsBool(); if (!m_connection_available && m_mgconn) { From 7e7e1a31bf66df626be8076e2b6a0ba5e907f2d6 Mon Sep 17 00:00:00 2001 From: Jaime Date: Wed, 21 Aug 2024 15:38:51 -0400 Subject: [PATCH 29/45] fix code style --- vehicle/OVMS.V3/main/ovms_netmanager.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/vehicle/OVMS.V3/main/ovms_netmanager.cpp b/vehicle/OVMS.V3/main/ovms_netmanager.cpp index 8153c08c7..54c2a00de 100644 --- a/vehicle/OVMS.V3/main/ovms_netmanager.cpp +++ b/vehicle/OVMS.V3/main/ovms_netmanager.cpp @@ -871,7 +871,6 @@ void OvmsNetManager::PrioritiseAndIndicate() void OvmsNetManager::DoSafePrioritiseAndIndicate() { - ESP_LOGE(TAG, "DoSafePrioritiseAndIndicate"); const char *search = NULL; ip_addr_t* dns = NULL; @@ -900,9 +899,9 @@ void OvmsNetManager::DoSafePrioritiseAndIndicate() MyPeripherals->m_cellular_modem->m_mux->IsMuxUp() && MyPeripherals->m_cellular_modem->m_ppp->m_connected; } - StdMetrics.ms_m_net_ip->SetValue(m_has_ip); + StdMetrics.ms_m_net_ip->SetValue(m_has_ip); - if (search == NULL) + if (search == NULL) { SetNetType("none"); return; From 8197229fac45c96de8c29dc0ae0efa13e1f97dea Mon Sep 17 00:00:00 2001 From: axel troncoso Date: Wed, 24 Jul 2024 16:27:27 -0400 Subject: [PATCH 30/45] Feat(support-dong-feng-e60) --- .../vehicle_dongfeng_e60/CMakeLists.txt | 13 ++ .../vehicle_dongfeng_e60/component.mk | 14 ++ .../vehicle_dongfeng_e60/docs/index.rst | 34 +++ .../src/vehicle_dongfeng_e60.cpp | 213 ++++++++++++++++++ .../src/vehicle_dongfeng_e60.h | 56 +++++ vehicle/OVMS.V3/main/Kconfig | 8 + 6 files changed, 338 insertions(+) create mode 100644 vehicle/OVMS.V3/components/vehicle_dongfeng_e60/CMakeLists.txt create mode 100644 vehicle/OVMS.V3/components/vehicle_dongfeng_e60/component.mk create mode 100644 vehicle/OVMS.V3/components/vehicle_dongfeng_e60/docs/index.rst create mode 100644 vehicle/OVMS.V3/components/vehicle_dongfeng_e60/src/vehicle_dongfeng_e60.cpp create mode 100644 vehicle/OVMS.V3/components/vehicle_dongfeng_e60/src/vehicle_dongfeng_e60.h diff --git a/vehicle/OVMS.V3/components/vehicle_dongfeng_e60/CMakeLists.txt b/vehicle/OVMS.V3/components/vehicle_dongfeng_e60/CMakeLists.txt new file mode 100644 index 000000000..fe0f81048 --- /dev/null +++ b/vehicle/OVMS.V3/components/vehicle_dongfeng_e60/CMakeLists.txt @@ -0,0 +1,13 @@ +set(srcs) +set(include_dirs) + +if (CONFIG_OVMS_VEHICLE_DONGFENG_E60) + list(APPEND srcs "src/vehicle_dongfeng_e60.cpp") + list(APPEND include_dirs "src") +endif () + +# requirements can't depend on config +idf_component_register(SRCS ${srcs} + INCLUDE_DIRS ${include_dirs} + PRIV_REQUIRES "main" + WHOLE_ARCHIVE) diff --git a/vehicle/OVMS.V3/components/vehicle_dongfeng_e60/component.mk b/vehicle/OVMS.V3/components/vehicle_dongfeng_e60/component.mk new file mode 100644 index 000000000..f19be954f --- /dev/null +++ b/vehicle/OVMS.V3/components/vehicle_dongfeng_e60/component.mk @@ -0,0 +1,14 @@ +# +# Main component makefile. +# +# This Makefile can be left empty. By default, it will take the sources in the +# src/ directory, compile them and link them into lib(subdirectory_name).a +# in the build directory. This behaviour is entirely configurable, +# please read the ESP-IDF documents if you need to do this. +# + +ifdef CONFIG_OVMS_VEHICLE_DONGFENG_E60 +COMPONENT_ADD_INCLUDEDIRS:=src +COMPONENT_SRCDIRS:=src +COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive +endif diff --git a/vehicle/OVMS.V3/components/vehicle_dongfeng_e60/docs/index.rst b/vehicle/OVMS.V3/components/vehicle_dongfeng_e60/docs/index.rst new file mode 100644 index 000000000..74ba4e1eb --- /dev/null +++ b/vehicle/OVMS.V3/components/vehicle_dongfeng_e60/docs/index.rst @@ -0,0 +1,34 @@ +======================= +Dong Feng E60 +======================= + +Vehicle Type: **DFE60** + +The Dong Feng E60 will be documented here. + +---------------- +Support Overview +---------------- + +=========================== ============== +Function Support Status +=========================== ============== +Hardware OVMS v3 (or later) +Vehicle Cable - +GSM Antenna - +GPS Antenna - +SOC Display No +Range Display No +GPS Location No +Speed Display No +Temperature Display No +BMS v+t Display No +TPMS Display No +Charge Status Display No +Charge Interruption Alerts No +Charge Control No +Cabin Pre-heat/cool Control No +Lock/Unlock Vehicle Yes +Valet Mode Control No +Others +=========================== ============== diff --git a/vehicle/OVMS.V3/components/vehicle_dongfeng_e60/src/vehicle_dongfeng_e60.cpp b/vehicle/OVMS.V3/components/vehicle_dongfeng_e60/src/vehicle_dongfeng_e60.cpp new file mode 100644 index 000000000..712a672e7 --- /dev/null +++ b/vehicle/OVMS.V3/components/vehicle_dongfeng_e60/src/vehicle_dongfeng_e60.cpp @@ -0,0 +1,213 @@ +/* +; Project: Open Vehicle Monitor System +; Date: 21th January 2019 +; +; Changes: +; 0.0.1 Initial stub +; - Ported from Kia Soul. Totally untested. +; +; 0.1.0 First version on par with Soul +; - First "complete" version. +; +; 0.1.1 06-apr-2019 - Geir Øyvind Vælidalo +; - Minor changes after proper real life testing +; - VIN is working +; - Removed more of the polling when car is off in order to prevent AUX battery drain +; +; 0.1.2 10-apr-2019 - Geir Øyvind Vælidalo +; - Fixed TPMS reading +; - Fixed xks aux +; - Estimated range show WLTP in lack of the actual displayed range +; - Door lock works even after ECU goes to sleep. +; +; 0.1.3 12-apr-2019 - Geir Øyvind Vælidalo +; - Fixed OBC temp reading +; - Removed a couple of pollings when car is off, in order to save AUX battery +; - Added range calculator for estimated range instead of WLTP. It now uses 20 last trips as a basis. +; +; 0.1.5 18-apr-2019 - Geir Øyvind Vælidalo +; - Changed poll frequencies to minimize the strain on the CAN-write function. +; +; 0.1.6 20-apr-2019 - Geir Øyvind Vælidalo +; - AUX Battery monitor.. +; +; (C) 2011 Michael Stegen / Stegen Electronics +; (C) 2011-2017 Mark Webb-Johnson +; (C) 2011 Sonny Chen @ EPRO/DX +; (C) 2019 Geir Øyvind Vælidalo +;; +; Permission is hereby granted, free of charge, to any person obtaining a copy +; of this software and associated documentation files (the "Software"), to deal +; in the Software without restriction, including without limitation the rights +; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +; copies of the Software, and to permit persons to whom the Software is +; furnished to do so, subject to the following conditions: +; +; The above copyright notice and this permission notice shall be included in +; all copies or substantial portions of the Software. +; +; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +; THE SOFTWARE. +*/ + +#include "vehicle_dongfeng_e60.h" + +#include "metrics_standard.h" + +#include "ovms_log.h" +#include "ovms_events.h" + +#define VERSION "0.1.6" + +// CAN buffer access macros: b=byte# 0..7 / n=nibble# 0..15 +#define CAN_BYTE(b) data[b] +#define CAN_INT(b) ((int16_t)CAN_UINT(b)) +#define CAN_UINT(b) (((UINT)CAN_BYTE(b) << 8) | CAN_BYTE(b+1)) +#define CAN_UINT24(b) (((uint32_t)CAN_BYTE(b) << 16) | ((UINT)CAN_BYTE(b+1) << 8) | CAN_BYTE(b+2)) +#define CAN_UINT32(b) (((uint32_t)CAN_BYTE(b) << 24) | ((uint32_t)CAN_BYTE(b+1) << 16) | ((UINT)CAN_BYTE(b+2) << 8) | CAN_BYTE(b+3)) +#define CAN_NIBL(b) (can_databuffer[b] & 0x0f) +#define CAN_NIBH(b) (can_databuffer[b] >> 4) +#define CAN_NIB(n) (((n)&1) ? CAN_NIBL((n)>>1) : CAN_NIBH((n)>>1)) +#define CAN_BIT(b,pos) !!(data[b] & (1<<(pos))) + +#define TO_CELCIUS(n) ((float)n-40) +#define TO_PSI(n) ((float)n/4.0) + +#define UDS_SID_IOCTRL_BY_ID 0x2F // InputOutputControlByCommonID +#define UDS_SID_IOCTRL_BY_LOC_ID 0x30 // InputOutputControlByLocalID +#define UDS_SID_TESTER_PRESENT 0x3E // TesterPresent + +#define UDS_DEFAULT_SESSION 0x01 +#define UDS_PROGRAMMING_SESSION 0x02 +#define UDS_EXTENDED_DIAGNOSTIC_SESSION 0x03 +#define UDS_SAFETY_SYSTEM_DIAGNOSTIC_SESSION 0x04 + +#define POLLSTATE_OFF PollSetState(0); +#define POLLSTATE_RUNNING PollSetState(1); +#define POLLSTATE_CHARGING PollSetState(2); + + +static const char *TAG = "v-dfe60"; + + +OvmsVehicleDFE60::OvmsVehicleDFE60() + { + ESP_LOGI(TAG, "Dongfeng E60 vehicle module"); + + StandardMetrics.ms_v_type->SetValue("DFE60"); + + StandardMetrics.ms_v_bat_12v_voltage->SetValue(12.5, Volts); + StandardMetrics.ms_v_charge_inprogress->SetValue(false); + StandardMetrics.ms_v_env_on->SetValue(false); + StandardMetrics.ms_v_bat_temp->SetValue(20, Celcius); + + can_message_buffer.id = 0; + can_message_buffer.status = 0; + + RegisterCanBus(1, CAN_MODE_ACTIVE, CAN_SPEED_500KBPS); + } + +OvmsVehicleDFE60::~OvmsVehicleDFE60() + { + ESP_LOGI(TAG, "Shutdown Dongfeng E60 vehicle module"); + } + +void OvmsVehicleDFE60::Ticker1(uint32_t ticker) + { + } + +void OvmsVehicleDFE60::Ticker300(uint32_t ticker) + { + } + +OvmsVehicle::vehicle_command_t OvmsVehicleDFE60::CommandLock(const char *pin) + { + return NotImplemented; + } + +OvmsVehicle::vehicle_command_t OvmsVehicleDFE60::CommandUnlock(const char *pin) + { + return NotImplemented; + } + +void OvmsVehicleDFE60::IncomingFrameCan1(CAN_frame_t *p_frame) + { + + const uint8_t (&data)[8] = p_frame->data.u8; + + // Check if response is from synchronous can message + if (can_message_buffer.status == 0xff && p_frame->MsgID == (can_message_buffer.id + 0x08)) + { + // Store message bytes so that the async method can continue + can_message_buffer.status = 3; + + std::copy(std::begin(data), std::end(data), std::begin(can_message_buffer.byte)); + } + + // set batt temp + switch (p_frame->MsgID) + { + case 0x488: + { + StdMetrics.ms_v_pos_odometer->SetValue((int)CAN_UINT24(0) / 10, Kilometers); + break; + } + case 0x347: + { + StdMetrics.ms_v_env_awake->SetValue(CAN_BIT(0, 6)); + break; + } + case 0x23a: + { + StdMetrics.ms_v_door_fl->SetValue(CAN_BIT(1, 3)); + StdMetrics.ms_v_door_fr->SetValue(CAN_BIT(1, 4)); + StdMetrics.ms_v_door_rr->SetValue(CAN_BIT(1, 5)); + StdMetrics.ms_v_door_rl->SetValue(CAN_BIT(1, 6)); + break; + } + case 0x380: + { + StdMetrics.ms_v_bat_soc->SetValue(CAN_BYTE(0), Percentage); + if (CAN_BIT(1, 2) && !CAN_BIT(1, 3)) + { + StdMetrics.ms_v_charge_inprogress->SetValue(true); + } + else + { + StdMetrics.ms_v_charge_inprogress->SetValue(false); + } + break; + } + case 0x490: + { + StdMetrics.ms_v_env_locked->SetValue(CAN_BIT(0, 2)); + break; + } + case 0x0a0: + { + // (it doesnt show the same speed as in the screen but it is close, a little less when going slow and a little more when going fast) + StdMetrics.ms_v_pos_speed->SetValue((int)CAN_UINT(6) / 93, Kph); + break; + } + default: + break; + } + + } + + +class OvmsVehicleDFE60Init + { + public: OvmsVehicleDFE60Init(); +} MyOvmsVehicleDFE60Init __attribute__((init_priority(9000))); + +OvmsVehicleDFE60Init::OvmsVehicleDFE60Init() + { + ESP_LOGI(TAG, "Registering Vehicle: DongFeng E60"); + MyVehicleFactory.RegisterVehicle("DFE60", "DongFeng E60"); + } diff --git a/vehicle/OVMS.V3/components/vehicle_dongfeng_e60/src/vehicle_dongfeng_e60.h b/vehicle/OVMS.V3/components/vehicle_dongfeng_e60/src/vehicle_dongfeng_e60.h new file mode 100644 index 000000000..7e7f32414 --- /dev/null +++ b/vehicle/OVMS.V3/components/vehicle_dongfeng_e60/src/vehicle_dongfeng_e60.h @@ -0,0 +1,56 @@ +/* +; Project: Open Vehicle Monitor System +; Date: 24th July 2024 +; +; Permission is hereby granted, free of charge, to any person obtaining a copy +; of this software and associated documentation files (the "Software"), to deal +; in the Software without restriction, including without limitation the rights +; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +; copies of the Software, and to permit persons to whom the Software is +; furnished to do so, subject to the following conditions: +; +; The above copyright notice and this permission notice shall be included in +; all copies or substantial portions of the Software. +; +; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +; THE SOFTWARE. +*/ + +#ifndef __VEHICLE_DONGFENGE60_H__ +#define __VEHICLE_DONGFENGE60_H__ + +#include "vehicle.h" + + +class OvmsVehicleDFE60 : public OvmsVehicle + { + public: + OvmsVehicleDFE60(); + ~OvmsVehicleDFE60(); + + public: + + void IncomingFrameCan1(CAN_frame_t *p_frame) override; + void Ticker1(uint32_t ticker) override; + void Ticker300(uint32_t ticker) override; + + vehicle_command_t CommandLock(const char *pin) override; + vehicle_command_t CommandUnlock(const char *pin) override; + + private: + + struct + { + uint8_t byte[8]; + uint8_t status; + uint16_t id; + } can_message_buffer; + + }; + +#endif // #ifndef __VEHICLE_DONGFENGE60_H__ diff --git a/vehicle/OVMS.V3/main/Kconfig b/vehicle/OVMS.V3/main/Kconfig index e37cd6fab..dfc753c1d 100644 --- a/vehicle/OVMS.V3/main/Kconfig +++ b/vehicle/OVMS.V3/main/Kconfig @@ -601,6 +601,14 @@ config OVMS_VEHICLE_BYD_ATTO3 help Enable support for BYD Atto 3 +config OVMS_VEHICLE_DONGFENG_E60 + bool "Include support for Dong Feng E60" + default y + depends on OVMS + depends on OVMS_COMP_POLLER + help + Enable support for Dong Feng E60 + config OVMS_VEHICLE_RXTASK_STACK int "Stack size for ISOTP Poller RX task" default 6144 From 119ee7470321a4cb83c49e54a2a6733fea742e7c Mon Sep 17 00:00:00 2001 From: axel troncoso Date: Wed, 7 Aug 2024 16:01:09 -0400 Subject: [PATCH 31/45] Feat(simplifying-dongfeng-e60-implementation) --- .../src/vehicle_dongfeng_e60.cpp | 42 +++---------------- .../src/vehicle_dongfeng_e60.h | 1 - 2 files changed, 5 insertions(+), 38 deletions(-) diff --git a/vehicle/OVMS.V3/components/vehicle_dongfeng_e60/src/vehicle_dongfeng_e60.cpp b/vehicle/OVMS.V3/components/vehicle_dongfeng_e60/src/vehicle_dongfeng_e60.cpp index 712a672e7..9c0560e1c 100644 --- a/vehicle/OVMS.V3/components/vehicle_dongfeng_e60/src/vehicle_dongfeng_e60.cpp +++ b/vehicle/OVMS.V3/components/vehicle_dongfeng_e60/src/vehicle_dongfeng_e60.cpp @@ -1,40 +1,12 @@ /* ; Project: Open Vehicle Monitor System -; Date: 21th January 2019 +; Date: 7th August 2024 ; ; Changes: -; 0.0.1 Initial stub -; - Ported from Kia Soul. Totally untested. +; 0.0.1 Initial submit. +; - DongFeng E60. Totally untested. ; -; 0.1.0 First version on par with Soul -; - First "complete" version. -; -; 0.1.1 06-apr-2019 - Geir Øyvind Vælidalo -; - Minor changes after proper real life testing -; - VIN is working -; - Removed more of the polling when car is off in order to prevent AUX battery drain -; -; 0.1.2 10-apr-2019 - Geir Øyvind Vælidalo -; - Fixed TPMS reading -; - Fixed xks aux -; - Estimated range show WLTP in lack of the actual displayed range -; - Door lock works even after ECU goes to sleep. -; -; 0.1.3 12-apr-2019 - Geir Øyvind Vælidalo -; - Fixed OBC temp reading -; - Removed a couple of pollings when car is off, in order to save AUX battery -; - Added range calculator for estimated range instead of WLTP. It now uses 20 last trips as a basis. -; -; 0.1.5 18-apr-2019 - Geir Øyvind Vælidalo -; - Changed poll frequencies to minimize the strain on the CAN-write function. -; -; 0.1.6 20-apr-2019 - Geir Øyvind Vælidalo -; - AUX Battery monitor.. -; -; (C) 2011 Michael Stegen / Stegen Electronics -; (C) 2011-2017 Mark Webb-Johnson -; (C) 2011 Sonny Chen @ EPRO/DX -; (C) 2019 Geir Øyvind Vælidalo +; (C) 2011 Axel Troncoso / Tucar ;; ; Permission is hereby granted, free of charge, to any person obtaining a copy ; of this software and associated documentation files (the "Software"), to deal @@ -92,7 +64,7 @@ #define POLLSTATE_CHARGING PollSetState(2); -static const char *TAG = "v-dfe60"; +static const char *TAG = "v-dongfengE60"; OvmsVehicleDFE60::OvmsVehicleDFE60() @@ -121,10 +93,6 @@ void OvmsVehicleDFE60::Ticker1(uint32_t ticker) { } -void OvmsVehicleDFE60::Ticker300(uint32_t ticker) - { - } - OvmsVehicle::vehicle_command_t OvmsVehicleDFE60::CommandLock(const char *pin) { return NotImplemented; diff --git a/vehicle/OVMS.V3/components/vehicle_dongfeng_e60/src/vehicle_dongfeng_e60.h b/vehicle/OVMS.V3/components/vehicle_dongfeng_e60/src/vehicle_dongfeng_e60.h index 7e7f32414..8de94c1c6 100644 --- a/vehicle/OVMS.V3/components/vehicle_dongfeng_e60/src/vehicle_dongfeng_e60.h +++ b/vehicle/OVMS.V3/components/vehicle_dongfeng_e60/src/vehicle_dongfeng_e60.h @@ -37,7 +37,6 @@ class OvmsVehicleDFE60 : public OvmsVehicle void IncomingFrameCan1(CAN_frame_t *p_frame) override; void Ticker1(uint32_t ticker) override; - void Ticker300(uint32_t ticker) override; vehicle_command_t CommandLock(const char *pin) override; vehicle_command_t CommandUnlock(const char *pin) override; From e50617da0517491b66304c998082d93c12f08c6b Mon Sep 17 00:00:00 2001 From: axel troncoso Date: Wed, 7 Aug 2024 16:25:37 -0400 Subject: [PATCH 32/45] Refactor(clean-to-contain-generic-minimalist) --- .../src/vehicle_dongfeng_e60.cpp | 71 ++----------------- 1 file changed, 5 insertions(+), 66 deletions(-) diff --git a/vehicle/OVMS.V3/components/vehicle_dongfeng_e60/src/vehicle_dongfeng_e60.cpp b/vehicle/OVMS.V3/components/vehicle_dongfeng_e60/src/vehicle_dongfeng_e60.cpp index 9c0560e1c..f026ec2de 100644 --- a/vehicle/OVMS.V3/components/vehicle_dongfeng_e60/src/vehicle_dongfeng_e60.cpp +++ b/vehicle/OVMS.V3/components/vehicle_dongfeng_e60/src/vehicle_dongfeng_e60.cpp @@ -48,15 +48,15 @@ #define CAN_BIT(b,pos) !!(data[b] & (1<<(pos))) #define TO_CELCIUS(n) ((float)n-40) -#define TO_PSI(n) ((float)n/4.0) +#define TO_PSI(n) ((float)n/4.0) -#define UDS_SID_IOCTRL_BY_ID 0x2F // InputOutputControlByCommonID +#define UDS_SID_IOCTRL_BY_ID 0x2F // InputOutputControlByCommonID #define UDS_SID_IOCTRL_BY_LOC_ID 0x30 // InputOutputControlByLocalID #define UDS_SID_TESTER_PRESENT 0x3E // TesterPresent -#define UDS_DEFAULT_SESSION 0x01 -#define UDS_PROGRAMMING_SESSION 0x02 -#define UDS_EXTENDED_DIAGNOSTIC_SESSION 0x03 +#define UDS_DEFAULT_SESSION 0x01 +#define UDS_PROGRAMMING_SESSION 0x02 +#define UDS_EXTENDED_DIAGNOSTIC_SESSION 0x03 #define UDS_SAFETY_SYSTEM_DIAGNOSTIC_SESSION 0x04 #define POLLSTATE_OFF PollSetState(0); @@ -105,67 +105,6 @@ OvmsVehicle::vehicle_command_t OvmsVehicleDFE60::CommandUnlock(const char *pin) void OvmsVehicleDFE60::IncomingFrameCan1(CAN_frame_t *p_frame) { - - const uint8_t (&data)[8] = p_frame->data.u8; - - // Check if response is from synchronous can message - if (can_message_buffer.status == 0xff && p_frame->MsgID == (can_message_buffer.id + 0x08)) - { - // Store message bytes so that the async method can continue - can_message_buffer.status = 3; - - std::copy(std::begin(data), std::end(data), std::begin(can_message_buffer.byte)); - } - - // set batt temp - switch (p_frame->MsgID) - { - case 0x488: - { - StdMetrics.ms_v_pos_odometer->SetValue((int)CAN_UINT24(0) / 10, Kilometers); - break; - } - case 0x347: - { - StdMetrics.ms_v_env_awake->SetValue(CAN_BIT(0, 6)); - break; - } - case 0x23a: - { - StdMetrics.ms_v_door_fl->SetValue(CAN_BIT(1, 3)); - StdMetrics.ms_v_door_fr->SetValue(CAN_BIT(1, 4)); - StdMetrics.ms_v_door_rr->SetValue(CAN_BIT(1, 5)); - StdMetrics.ms_v_door_rl->SetValue(CAN_BIT(1, 6)); - break; - } - case 0x380: - { - StdMetrics.ms_v_bat_soc->SetValue(CAN_BYTE(0), Percentage); - if (CAN_BIT(1, 2) && !CAN_BIT(1, 3)) - { - StdMetrics.ms_v_charge_inprogress->SetValue(true); - } - else - { - StdMetrics.ms_v_charge_inprogress->SetValue(false); - } - break; - } - case 0x490: - { - StdMetrics.ms_v_env_locked->SetValue(CAN_BIT(0, 2)); - break; - } - case 0x0a0: - { - // (it doesnt show the same speed as in the screen but it is close, a little less when going slow and a little more when going fast) - StdMetrics.ms_v_pos_speed->SetValue((int)CAN_UINT(6) / 93, Kph); - break; - } - default: - break; - } - } From 9ef9d31da1b31db394e274d478cb188485fe91ae Mon Sep 17 00:00:00 2001 From: atroncoso-tucar Date: Mon, 12 Aug 2024 17:15:05 -0400 Subject: [PATCH 33/45] Tucar/feat/support kia niroevsg2 (#3) * Feat(adding-non-compiling-kia-niro-sg2) * Feat(kia-niro-compiling-and-completing-interface) * Feat(removing-windows-since-unnecessary) * Feat(finished-support-for-kia-niro) * Feat(adding-necessary-variable-initializations) --- .../vehicle_kianirosg2/CMakeLists.txt | 13 + .../vehicle_kianirosg2/component.mk | 14 + .../vehicle_kianirosg2/docs/Todo.md | 5 + .../src/vehicle_kia_niroevsg2.cpp | 508 ++++++++++++++++++ .../src/vehicle_kia_niroevsg2.h | 94 ++++ vehicle/OVMS.V3/main/Kconfig | 7 + 6 files changed, 641 insertions(+) create mode 100644 vehicle/OVMS.V3/components/vehicle_kianirosg2/CMakeLists.txt create mode 100644 vehicle/OVMS.V3/components/vehicle_kianirosg2/component.mk create mode 100644 vehicle/OVMS.V3/components/vehicle_kianirosg2/docs/Todo.md create mode 100644 vehicle/OVMS.V3/components/vehicle_kianirosg2/src/vehicle_kia_niroevsg2.cpp create mode 100644 vehicle/OVMS.V3/components/vehicle_kianirosg2/src/vehicle_kia_niroevsg2.h diff --git a/vehicle/OVMS.V3/components/vehicle_kianirosg2/CMakeLists.txt b/vehicle/OVMS.V3/components/vehicle_kianirosg2/CMakeLists.txt new file mode 100644 index 000000000..634f3f6e3 --- /dev/null +++ b/vehicle/OVMS.V3/components/vehicle_kianirosg2/CMakeLists.txt @@ -0,0 +1,13 @@ +set(srcs) +set(include_dirs) + +if (CONFIG_OVMS_VEHICLE_KIANIROEVSG2) + list(APPEND srcs "src/vehicle_kia_niroevsg2.cpp") + list(APPEND include_dirs "src") +endif () + +# requirements can't depend on config +idf_component_register(SRCS ${srcs} + INCLUDE_DIRS ${include_dirs} + PRIV_REQUIRES "main" + WHOLE_ARCHIVE) diff --git a/vehicle/OVMS.V3/components/vehicle_kianirosg2/component.mk b/vehicle/OVMS.V3/components/vehicle_kianirosg2/component.mk new file mode 100644 index 000000000..9e93f1ee5 --- /dev/null +++ b/vehicle/OVMS.V3/components/vehicle_kianirosg2/component.mk @@ -0,0 +1,14 @@ +# +# Main component makefile. +# +# This Makefile can be left empty. By default, it will take the sources in the +# src/ directory, compile them and link them into lib(subdirectory_name).a +# in the build directory. This behaviour is entirely configurable, +# please read the ESP-IDF documents if you need to do this. +# + +ifdef CONFIG_OVMS_VEHICLE_KIANIROEVSG2 +COMPONENT_ADD_INCLUDEDIRS:=src +COMPONENT_SRCDIRS:=src +COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive +endif diff --git a/vehicle/OVMS.V3/components/vehicle_kianirosg2/docs/Todo.md b/vehicle/OVMS.V3/components/vehicle_kianirosg2/docs/Todo.md new file mode 100644 index 000000000..667039fed --- /dev/null +++ b/vehicle/OVMS.V3/components/vehicle_kianirosg2/docs/Todo.md @@ -0,0 +1,5 @@ +# Checklist of known features to be implemented + +- [ ] Add the set charge metrics method to the kia common vehicle. +- [ ] Add missing metrics to the charge metrics method. +- [ ] Add PollState enum class to kia common class. diff --git a/vehicle/OVMS.V3/components/vehicle_kianirosg2/src/vehicle_kia_niroevsg2.cpp b/vehicle/OVMS.V3/components/vehicle_kianirosg2/src/vehicle_kia_niroevsg2.cpp new file mode 100644 index 000000000..149215d5d --- /dev/null +++ b/vehicle/OVMS.V3/components/vehicle_kianirosg2/src/vehicle_kia_niroevsg2.cpp @@ -0,0 +1,508 @@ +/* +; Project: Open Vehicle Monitor System +; Date: 9th August 2024 +; +; Changes: +; 0.0.1 Initial stub +; +; (C) 2018 Axel Troncoso / Tucar +; +; Permission is hereby granted, free of charge, to any person obtaining a copy +; of this software and associated documentation files (the "Software"), to deal +; in the Software without restriction, including without limitation the rights +; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +; copies of the Software, and to permit persons to whom the Software is +; furnished to do so, subject to the following conditions: +; +; The above copyright notice and this permission notice shall be included in +; all copies or substantial portions of the Software. +; +; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +; THE SOFTWARE. +*/ + +#include "vehicle_kia_niroevsg2.h" + +#include "ovms_log.h" + +#include +#include +#include "pcp.h" +#include "metrics_standard.h" +#include "ovms_metrics.h" +#include "ovms_notify.h" +#include +#include "../../vehicle_kiasoulev/src/kia_common.h" + +#define VERSION "0.0.1" + +static const char *TAG = "v-kianiroevsg2"; + +// Pollstate 0 - car is off +// Pollstate 1 - car is on +// Pollstate 2 - car is charging +static const OvmsPoller::poll_pid_t vehicle_kianiroevsg2_polls[] = + { + // ok2 IncomingIGMP + {0x770, 0x778, VEHICLE_POLL_TYPE_OBDIIEXTENDED, 0xbc03, {2, 2, 2}, 1, ISOTP_STD}, // IGMP Door status and lock + {0x770, 0x778, VEHICLE_POLL_TYPE_OBDIIEXTENDED, 0xbc04, {2, 2, 2}, 1, ISOTP_STD}, // IGMP Door lock + + // ok2 IncomingBCM + {0x7a0, 0x7a8, VEHICLE_POLL_TYPE_OBDIIEXTENDED, 0xC00B, {0, 25, 0}, 1, ISOTP_STD}, // TMPS - Pressure + {0x7a0, 0x7a8, VEHICLE_POLL_TYPE_OBDIIEXTENDED, 0xB010, {0, 25, 0}, 1, ISOTP_STD}, // TMPS - Pressure + + // ok2 IncomingVMCU + {0x7e2, 0x7ea, VEHICLE_POLL_TYPE_OBDIIGROUP, 0x02, {600, 25, 25}, 1, ISOTP_STD}, // VMCU - Aux Battery voltage + + // ok2 IncomingBMC + {0x7e4, 0x7ec, VEHICLE_POLL_TYPE_OBDIIEXTENDED, 0x0101, {5, 2, 2}, 1, ISOTP_STD}, // Voltage and current main bat + {0x7e4, 0x7ec, VEHICLE_POLL_TYPE_OBDIIEXTENDED, 0x0105, {0, 5, 5}, 1, ISOTP_STD}, // bat soc and soh + + // ok2 IncomingCM + {0x7c6, 0x7ce, VEHICLE_POLL_TYPE_OBDIIEXTENDED, 0xB002, {0, 25, 60}, 1, ISOTP_STD}, // ODO + {0x7c6, 0x7ce, VEHICLE_POLL_TYPE_OBDIIEXTENDED, 0xB003, {2, 2, 2}, 1, ISOTP_STD}, // AWAKE + + // ok2 IncomingSteeringwheel + {0x7d4, 0x7dc, VEHICLE_POLL_TYPE_OBDIIEXTENDED, 0x0101, {2, 2, 2}, 1, ISOTP_STD}, // ON SPEED + POLL_LIST_END + }; + +static const OvmsPoller::poll_pid_t vehicle_kianiroevsg2_polls_stop[] = {POLL_LIST_END}; + +/** + * Constructor for Kia Niro EV OvmsVehicleKiaNiroEvSg2 + */ +OvmsVehicleKiaNiroEvSg2::OvmsVehicleKiaNiroEvSg2() + { + ESP_LOGI(TAG, "Kia Sg2 EV vehicle module"); + + kia_send_can.id = 0; + kia_send_can.status = 0; + memset(kia_send_can.byte, 0, sizeof(kia_send_can.byte)); + + // init metrics: + m_v_door_lock_fl = MyMetrics.InitBool("xkn.v.door.lock.front.left", 10, 0); + m_v_door_lock_fr = MyMetrics.InitBool("xkn.v.door.lock.front.right", 10, 0); + m_v_door_lock_rl = MyMetrics.InitBool("xkn.v.door.lock.rear.left", 10, 0); + m_v_door_lock_rr = MyMetrics.InitBool("xkn.v.door.lock.rear.right", 10, 0); + + StdMetrics.ms_v_bat_12v_voltage->SetValue(12.5, Volts); + StdMetrics.ms_v_charge_inprogress->SetValue(false); + StdMetrics.ms_v_env_on->SetValue(false); + StdMetrics.ms_v_bat_temp->SetValue(20, Celcius); + + // Require GPS. + MyEvents.SignalEvent("vehicle.require.gps", NULL); + MyEvents.SignalEvent("vehicle.require.gpstime", NULL); + + PollSetThrottling(6); + RegisterCanBus(1, CAN_MODE_ACTIVE, CAN_SPEED_500KBPS); + POLLSTATE_OFF; + PollSetPidList(m_can1, vehicle_kianiroevsg2_polls); + } + +/** + * Destructor + */ +OvmsVehicleKiaNiroEvSg2::~OvmsVehicleKiaNiroEvSg2() + { + ESP_LOGI(TAG, "Shutdown Kia Sg2 EV vehicle module"); + } + +OvmsVehicleKiaNiroEvSg2::PollState OvmsVehicleKiaNiroEvSg2::GetPollState() + { + switch (m_poll_state) + { + case 0: + return PollState::OFF; + case 1: + return PollState::RUNNING; + case 2: + return PollState::CHARGING; + default: + assert (false); + return PollState::OFF; + } + } + +/** + * Ticker1: Called every second + */ +void OvmsVehicleKiaNiroEvSg2::Ticker1(uint32_t ticker) + { + /* Register car as locked, only if all doors are locked. */ + StdMetrics.ms_v_env_locked->SetValue( + m_v_door_lock_fr->AsBool() && + m_v_door_lock_fl->AsBool() && + m_v_door_lock_rr->AsBool() && + m_v_door_lock_rl->AsBool()); + + /* Set batery power */ + StdMetrics.ms_v_bat_power->SetValue( + StdMetrics.ms_v_bat_voltage->AsFloat(400, Volts) * + StdMetrics.ms_v_bat_current->AsFloat(1, Amps) / 1000, + kW); + + /* Set charge status */ + StdMetrics.ms_v_charge_inprogress->SetValue( + (StdMetrics.ms_v_pos_speed->AsFloat(0) < 1) & + (StdMetrics.ms_v_bat_power->AsFloat(0, kW) < -1)); + + auto vehicle_on = (bool) StdMetrics.ms_v_env_on->AsBool(); + auto vehicle_charging = (bool) StdMetrics.ms_v_charge_inprogress->AsBool(); + + /* Define next state. */ + auto to_run = vehicle_on && !vehicle_charging; + auto to_charge = vehicle_charging; + auto to_off = !vehicle_on && !vehicle_charging; + + /* There may be only one next state. */ + assert(to_run + to_charge + to_off == 1); + + /* Run actions depending on state. */ + auto poll_state = GetPollState(); + switch (poll_state) + { + case PollState::OFF: + if (to_run) + HandleCarOn(); + else if (to_charge) + HandleCharging(); + case PollState::RUNNING: + if (to_off) + HandleCarOff(); + else if (to_charge) + HandleCharging(); + case PollState::CHARGING: + if (to_off) + { + HandleChargeStop(); + HandleCarOff(); + } + else if (to_run) + { + HandleChargeStop(); + HandleCarOn(); + } + } + + } + +/** + * Update metrics when charging + */ +void OvmsVehicleKiaNiroEvSg2::HandleCharging() + { + POLLSTATE_CHARGING; + ESP_LOGI(TAG, "CAR IS CHARGING | POLLSTATE CHARGING"); + + SetChargeType(); + } + +/** + * Update metrics when charging stops + */ +void OvmsVehicleKiaNiroEvSg2::HandleChargeStop() + { + ESP_LOGI(TAG, "CAR CHARGING STOPPED"); + ResetChargeType(); + } + +/** + * Update metrics when car is turned on + */ +void OvmsVehicleKiaNiroEvSg2::HandleCarOn() + { + POLLSTATE_RUNNING; + ESP_LOGI(TAG, "CAR IS ON | POLLSTATE RUNNING"); + } + +/** + * Update metrics when car is turned off + */ +void OvmsVehicleKiaNiroEvSg2::HandleCarOff() + { + POLLSTATE_OFF; + ESP_LOGI(TAG, "CAR IS OFF | POLLSTATE OFF"); + } + +/** + * Sets the charger type + */ +void OvmsVehicleKiaNiroEvSg2::SetChargeType() + { + auto using_css = StdMetrics.ms_v_bat_power->AsFloat(0, kW) < -15; + StdMetrics.ms_v_charge_type->SetValue(using_css ? "CCS" : "Type2"); + } + +/** + * Resets the charges type + */ +void OvmsVehicleKiaNiroEvSg2::ResetChargeType() + { + StdMetrics.ms_v_charge_type->SetValue(""); + } + +/** + * Handles incoming CAN-frames on bus 1, the C-bus + */ +void OvmsVehicleKiaNiroEvSg2::IncomingFrameCan1(CAN_frame_t* p_frame) + { + uint8_t *d = p_frame->data.u8; + + // Check if response is from synchronous can message + if (kia_send_can.status == 0xff && p_frame->MsgID == (kia_send_can.id + 0x08)) + { + //Store message bytes so that the async method can continue + kia_send_can.status = 3; + + kia_send_can.byte[0] = d[0]; + kia_send_can.byte[1] = d[1]; + kia_send_can.byte[2] = d[2]; + kia_send_can.byte[3] = d[3]; + kia_send_can.byte[4] = d[4]; + kia_send_can.byte[5] = d[5]; + kia_send_can.byte[6] = d[6]; + kia_send_can.byte[7] = d[7]; + } + } + + +/** + * Incoming poll reply messages + */ +void OvmsVehicleKiaNiroEvSg2::IncomingPollReply(const OvmsPoller::poll_job_t &job, uint8_t *data, uint8_t length) + { + switch (job.moduleid_rec) + { + // ****** IGMP ***** + case 0x778: + IncomingIGMP(job.bus, job.type, job.pid, data, length, job.mlframe, job.mlremain); + break; + + // ****** BCM ****** + case 0x7a8: + IncomingBCM(job.bus, job.type, job.pid, data, length, job.mlframe, job.mlremain); + break; + + // ******* VMCU ****** + case 0x7ea: + IncomingVMCU(job.bus, job.type, job.pid, data, length, job.mlframe, job.mlremain); + break; + + // ***** BMC **** + case 0x7ec: + IncomingBMC(job.bus, job.type, job.pid, data, length, job.mlframe, job.mlremain); + break; + + // ***** CM **** + case 0x7ce: + IncomingCM(job.bus, job.type, job.pid, data, length, job.mlframe, job.mlremain); + break; + + // ***** SW **** + case 0x7dc: + IncomingSW(job.bus, job.type, job.pid, data, length, job.mlframe, job.mlremain); + break; + + default: + ESP_LOGD(TAG, "Unknown module: %03" PRIx32, job.moduleid_rec); + break; + } + } + +/** + * Handle incoming messages from cluster. + */ +void OvmsVehicleKiaNiroEvSg2::IncomingCM(canbus *bus, uint16_t type, uint16_t pid, const uint8_t *data, uint8_t length, uint16_t mlframe, uint16_t mlremain) + { + switch (pid) + { + case 0xb002: + if (mlframe == 1) + { + StdMetrics.ms_v_pos_odometer->SetValue(CAN_UINT24(3), Kilometers); + } + break; + case 0xb003: + if (mlframe == 1) + { + StdMetrics.ms_v_env_awake->SetValue(CAN_BYTE(1) != 0); + if (!StdMetrics.ms_v_env_awake->AsBool()) + { + StdMetrics.ms_v_env_on->SetValue(false); + } + } + break; + } + } + +/** + * Handle incoming messages from VMCU-poll + * + * - Aux battery SOC, Voltage and current + */ +void OvmsVehicleKiaNiroEvSg2::IncomingVMCU(canbus *bus, uint16_t type, uint16_t pid, const uint8_t *data, uint8_t length, uint16_t mlframe, uint16_t mlremain) + { + switch (pid) + { + case 0x02: + if (type == VEHICLE_POLL_TYPE_OBDIIGROUP) + { + if (mlframe == 3) + { + StdMetrics.ms_v_bat_12v_voltage->SetValue(((CAN_BYTE(2) << 8) + CAN_BYTE(1)) / 1000.0, Volts); + } + } + break; + } + } + +/** + * Handle incoming messages from BMC-poll + * + * - Pilot signal available + * - CCS / Type2 + * - Battery current + * - Battery voltage + * - Battery module temp 1-8 + * - Cell voltage max / min + cell # + * + more + */ +void OvmsVehicleKiaNiroEvSg2::IncomingBMC(canbus *bus, uint16_t type, uint16_t pid, const uint8_t *data, uint8_t length, uint16_t mlframe, uint16_t mlremain) + { + if (type == VEHICLE_POLL_TYPE_OBDIIEXTENDED) + { + switch (pid) + { + case 0x0101: + // diag page 01: skip first frame (no data) + // ESP_LOGD(TAG, "Frame number %x",mlframe); + + if (mlframe == 2) + { + StdMetrics.ms_v_bat_current->SetValue((float)CAN_INT(0) / 10.0, Amps); // negative regen, positive accel + StdMetrics.ms_v_bat_voltage->SetValue((float)CAN_UINT(2) / 10.0, Volts); + } + break; + + case 0x0105: + if (mlframe == 4) + { + StdMetrics.ms_v_bat_soh->SetValue((float)CAN_UINT(1) / 10.0, Percentage); + } + else if (mlframe == 5) + { + StdMetrics.ms_v_bat_soc->SetValue(CAN_BYTE(0) / 2.0, Percentage); + } + break; + } + } + } + +/** + * Handle incoming messages from BCM-poll + */ +void OvmsVehicleKiaNiroEvSg2::IncomingBCM(canbus *bus, uint16_t type, uint16_t pid, const uint8_t *data, uint8_t length, uint16_t mlframe, uint16_t mlremain) + { + uint8_t bVal; + if (type == VEHICLE_POLL_TYPE_OBDIIEXTENDED) + { + switch (pid) + { + case 0xC00B: + if (mlframe == 1) + { + bVal = CAN_BYTE(1); + if (bVal > 0) + StdMetrics.ms_v_tpms_pressure->SetElemValue(MS_V_TPMS_IDX_FL, bVal / 5.0, PSI); + bVal = CAN_BYTE(6); + if (bVal > 0) + StdMetrics.ms_v_tpms_pressure->SetElemValue(MS_V_TPMS_IDX_FR, bVal / 5.0, PSI); + } + else if (mlframe == 2) + { + bVal = CAN_BYTE(4); + if (bVal > 0) + StdMetrics.ms_v_tpms_pressure->SetElemValue(MS_V_TPMS_IDX_RL, bVal / 5.0, PSI); + } + else if (mlframe == 3) + { + bVal = CAN_BYTE(2); + if (bVal > 0) + StdMetrics.ms_v_tpms_pressure->SetElemValue(MS_V_TPMS_IDX_RR, bVal / 5.0, PSI); + } + break; + } + } + } + +/** + * Handle incoming messages from IGMP-poll + * + * + */ +void OvmsVehicleKiaNiroEvSg2::IncomingIGMP(canbus *bus, uint16_t type, uint16_t pid, const uint8_t *data, uint8_t length, uint16_t mlframe, uint16_t mlremain) + { + if (type == VEHICLE_POLL_TYPE_OBDIIEXTENDED) + { + switch (pid) + { + case 0xbc03: + if (mlframe == 1) + { + StdMetrics.ms_v_door_fl->SetValue(CAN_BIT(1, 5)); + StdMetrics.ms_v_door_fr->SetValue(CAN_BIT(1, 4)); + StdMetrics.ms_v_door_rl->SetValue(CAN_BIT(1, 0)); + StdMetrics.ms_v_door_rr->SetValue(CAN_BIT(1, 2)); + m_v_door_lock_rl->SetValue(!CAN_BIT(1, 1)); + m_v_door_lock_rr->SetValue(!CAN_BIT(1, 3)); + } + break; + + case 0xbc04: + if (mlframe == 1) + { + m_v_door_lock_fl->SetValue(!CAN_BIT(1, 3)); + m_v_door_lock_fr->SetValue(!CAN_BIT(1, 2)); + } + break; + } + } + } + +void OvmsVehicleKiaNiroEvSg2::IncomingSW(canbus *bus, uint16_t type, uint16_t pid, const uint8_t *data, uint8_t length, uint16_t mlframe, uint16_t mlremain) + { + if (type == VEHICLE_POLL_TYPE_OBDIIEXTENDED) + { + switch (pid) + { + case 0x0101: + if (mlframe == 2) + { + StdMetrics.ms_v_env_on->SetValue(CAN_BYTE(6) != 0); + StdMetrics.ms_v_pos_speed->SetValue(CAN_BYTE(2), Kph); + } + break; + } + } + } + + + +class OvmsVehicleKiaNiroEvSg2Init + { + public: + OvmsVehicleKiaNiroEvSg2Init(); + } MyOvmsVehicleKiaNiroEvSg2Init __attribute__((init_priority(9000))); + +OvmsVehicleKiaNiroEvSg2Init::OvmsVehicleKiaNiroEvSg2Init() + { + ESP_LOGI(TAG, "Registering Vehicle: Kia Niro Sg2 EV (9000)"); + MyVehicleFactory.RegisterVehicle("KN2", "Kia Niro Sg2 EV"); + } diff --git a/vehicle/OVMS.V3/components/vehicle_kianirosg2/src/vehicle_kia_niroevsg2.h b/vehicle/OVMS.V3/components/vehicle_kianirosg2/src/vehicle_kia_niroevsg2.h new file mode 100644 index 000000000..db1c59b6e --- /dev/null +++ b/vehicle/OVMS.V3/components/vehicle_kianirosg2/src/vehicle_kia_niroevsg2.h @@ -0,0 +1,94 @@ +/* +; Project: Open Vehicle Monitor System +; Date: 9th August 2024 +; +; Changes: +; 0.0.1 Initial stub +; +; (C) 2018 Axel Troncoso / Tucar +; +; Permission is hereby granted, free of charge, to any person obtaining a copy +; of this software and associated documentation files (the "Software"), to deal +; in the Software without restriction, including without limitation the rights +; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +; copies of the Software, and to permit persons to whom the Software is +; furnished to do so, subject to the following conditions: +; +; The above copyright notice and this permission notice shall be included in +; all copies or substantial portions of the Software. +; +; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +; THE SOFTWARE. +*/ + +#ifndef __VEHICLE_KIANIROEVSG2_H__ +#define __VEHICLE_KIANIROEVSG2_H__ + +#include "../../vehicle_kiasoulev/src/kia_common.h" +#include "vehicle.h" + + +using namespace std; + +class OvmsVehicleKiaNiroEvSg2 : public KiaVehicle + { + public: + OvmsVehicleKiaNiroEvSg2(); + ~OvmsVehicleKiaNiroEvSg2(); + + public: + void IncomingFrameCan1(CAN_frame_t *p_frame) override; + void Ticker1(uint32_t ticker) override; + void IncomingPollReply(const OvmsPoller::poll_job_t &job, uint8_t *data, uint8_t length) override; + void SendTesterPresent(uint16_t id, uint8_t length); + bool SetSessionMode(uint16_t id, uint8_t mode); + void SendCanMessage(uint16_t id, uint8_t count, + uint8_t serviceId, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, + uint8_t b5, uint8_t b6); + void SendCanMessageTriple(uint16_t id, uint8_t count, + uint8_t serviceId, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, + uint8_t b5, uint8_t b6); + bool SendCanMessage_sync(uint16_t id, uint8_t count, + uint8_t serviceId, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, + uint8_t b5, uint8_t b6); + bool SendCommandInSessionMode(uint16_t id, uint8_t count, + uint8_t serviceId, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, + uint8_t b5, uint8_t b6, uint8_t mode); + + protected: + void IncomingVMCU(canbus *bus, uint16_t type, uint16_t pid, const uint8_t *data, uint8_t length, uint16_t mlframe, uint16_t mlremain); + void IncomingBMC(canbus* bus, uint16_t type, uint16_t pid, const uint8_t* data, uint8_t length, uint16_t mlframe, uint16_t mlremain); + void IncomingBCM(canbus* bus, uint16_t type, uint16_t pid, const uint8_t* data, uint8_t length, uint16_t mlframe, uint16_t mlremain); + void IncomingIGMP(canbus* bus, uint16_t type, uint16_t pid, const uint8_t* data, uint8_t length, uint16_t mlframe, uint16_t mlremain); + void IncomingCM(canbus* bus, uint16_t type, uint16_t pid, const uint8_t* data, uint8_t length, uint16_t mlframe, uint16_t mlremain); + void IncomingSW(canbus* bus, uint16_t type, uint16_t pid, const uint8_t* data, uint8_t length, uint16_t mlframe, uint16_t mlremain); + void SendTesterPresentMessages(); + void StopTesterPresentMessages(); + + private: + + enum class PollState + { + OFF, + RUNNING, + CHARGING + }; + + void HandleCharging(); + void HandleChargeStop(); + void HandleCarOn(); + void HandleCarOff(); + + void SetChargeType(); + void ResetChargeType(); + + PollState GetPollState(); + + }; + +#endif //#ifndef __VEHICLE_KIANIROEVSG2_H__ diff --git a/vehicle/OVMS.V3/main/Kconfig b/vehicle/OVMS.V3/main/Kconfig index dfc753c1d..bbb98d782 100644 --- a/vehicle/OVMS.V3/main/Kconfig +++ b/vehicle/OVMS.V3/main/Kconfig @@ -600,6 +600,13 @@ config OVMS_VEHICLE_BYD_ATTO3 depends on OVMS_COMP_POLLER help Enable support for BYD Atto 3 +config OVMS_VEHICLE_KIANIROEVSG2 + bool "Include support for Kia Niro EV SG2" + default y + depends on OVMS + depends on OVMS_COMP_POLLER + help + Enable support for Kia Niro EV SG2 config OVMS_VEHICLE_DONGFENG_E60 bool "Include support for Dong Feng E60" From 0066458134b9f767085668efd7363dc221dd7a33 Mon Sep 17 00:00:00 2001 From: Jaime Date: Fri, 9 Aug 2024 16:33:55 -0400 Subject: [PATCH 34/45] new metrics --- vehicle/OVMS.V3/main/metrics_standard.cpp | 3 +++ vehicle/OVMS.V3/main/metrics_standard.h | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/vehicle/OVMS.V3/main/metrics_standard.cpp b/vehicle/OVMS.V3/main/metrics_standard.cpp index ddcb3ab50..724084d02 100644 --- a/vehicle/OVMS.V3/main/metrics_standard.cpp +++ b/vehicle/OVMS.V3/main/metrics_standard.cpp @@ -224,11 +224,14 @@ MetricsStandard::MetricsStandard() ms_v_env_awake = new OvmsMetricBool(MS_V_ENV_AWAKE, SM_STALE_MID, Other, true); ms_v_env_on = new OvmsMetricBool(MS_V_ENV_ON, SM_STALE_MID, Other, true); ms_v_env_drivemode = new OvmsMetricInt(MS_V_ENV_DRIVEMODE, SM_STALE_MID, Other, true); + ms_v_env_efficiencymode = new OvmsMetricString(MS_V_ENV_EFFICIENCYMODE, SM_STALE_MID, Other, true); + ms_v_env_regenlevel = new OvmsMetricFloat(MS_V_ENV_REGENLEVEL, SM_STALE_MID, Percentage, true); ms_v_env_gear = new OvmsMetricInt(MS_V_ENV_GEAR, SM_STALE_MID); ms_v_env_throttle = new OvmsMetricFloat(MS_V_ENV_THROTTLE, SM_STALE_MID, Percentage); ms_v_env_footbrake = new OvmsMetricFloat(MS_V_ENV_FOOTBRAKE, SM_STALE_MID, Percentage); ms_v_env_handbrake = new OvmsMetricBool(MS_V_ENV_HANDBRAKE, SM_STALE_MID); ms_v_env_regenbrake = new OvmsMetricBool(MS_V_ENV_REGENBRAKE, SM_STALE_MID); + ms_v_env_onepedal = new OvmsMetricBool(MS_V_ENV_ONEPEDAL, SM_STALE_MID); ms_v_env_cooling = new OvmsMetricBool(MS_V_ENV_COOLING, SM_STALE_MID); ms_v_env_heating = new OvmsMetricBool(MS_V_ENV_HEATING, SM_STALE_MID); ms_v_env_hvac = new OvmsMetricBool(MS_V_ENV_HVAC, SM_STALE_MID); diff --git a/vehicle/OVMS.V3/main/metrics_standard.h b/vehicle/OVMS.V3/main/metrics_standard.h index d0246f79e..0e47f3b61 100644 --- a/vehicle/OVMS.V3/main/metrics_standard.h +++ b/vehicle/OVMS.V3/main/metrics_standard.h @@ -197,11 +197,14 @@ #define MS_V_DOOR_TRUNK "v.d.trunk" #define MS_V_ENV_DRIVEMODE "v.e.drivemode" +#define MS_V_ENV_EFFICIENCYMODE "v.e.efficiencymode" +#define MS_V_ENV_REGENLEVEL "v.e.regenlevel" #define MS_V_ENV_GEAR "v.e.gear" #define MS_V_ENV_THROTTLE "v.e.throttle" #define MS_V_ENV_FOOTBRAKE "v.e.footbrake" #define MS_V_ENV_HANDBRAKE "v.e.handbrake" #define MS_V_ENV_REGENBRAKE "v.e.regenbrake" +#define MS_V_ENV_ONEPEDAL "v.e.onepedal" #define MS_V_ENV_AWAKE "v.e.awake" #define MS_V_ENV_CHARGING12V "v.e.charging12v" #define MS_V_ENV_AUX12V "v.e.aux12v" @@ -466,11 +469,14 @@ class MetricsStandard OvmsMetricBool* ms_v_env_awake; // Vehicle is fully awake (switched on by the user) OvmsMetricBool* ms_v_env_on; // Vehicle is in "ignition" state (drivable) OvmsMetricInt* ms_v_env_drivemode; // Active drive profile number [1] + OvmsMetricString* ms_v_env_efficiencymode; // Active efficiency profile number [1] OvmsMetricInt* ms_v_env_gear; // Gear/direction; negative=reverse, 0=neutral [1] + OvmsMetricFloat* ms_v_env_regenlevel; // regen level activaed OvmsMetricFloat* ms_v_env_throttle; // Drive pedal state [%] OvmsMetricFloat* ms_v_env_footbrake; // Brake pedal state [%] OvmsMetricBool* ms_v_env_handbrake; // Handbrake state OvmsMetricBool* ms_v_env_regenbrake; // Regenerative braking state + OvmsMetricBool* ms_v_env_onepedal; // If one pedal driving is active OvmsMetricBool* ms_v_env_cooling; OvmsMetricBool* ms_v_env_heating; OvmsMetricBool* ms_v_env_hvac; // Climate control system state From aeed29ed34f966fb46bab602c6e978b725626355 Mon Sep 17 00:00:00 2001 From: Jaime Date: Fri, 9 Aug 2024 16:27:38 -0400 Subject: [PATCH 35/45] base vehicle --- vehicle/OVMS.V3/components/vehicle/vehicle.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/vehicle/OVMS.V3/components/vehicle/vehicle.cpp b/vehicle/OVMS.V3/components/vehicle/vehicle.cpp index 129ce2075..bb87d87fd 100644 --- a/vehicle/OVMS.V3/components/vehicle/vehicle.cpp +++ b/vehicle/OVMS.V3/components/vehicle/vehicle.cpp @@ -30,6 +30,7 @@ #include "ovms_log.h" static const char *TAG = "vehicle"; +static const char *BASE_VEHICLE = "KN2"; // static const char *TAGRX = "vehicle-rx"; static const char *CHECK_SHUTDOWN_TAG = "vehicle-shutdown"; @@ -212,7 +213,11 @@ OvmsVehicle* OvmsVehicleFactory::NewVehicle(const char* VehicleType) { return iter->second.construct(); } - return NULL; + if (strcmp(VehicleType, BASE_VEHICLE) == 0) + { + return NULL; + } + return NewVehicle(BASE_VEHICLE); } void OvmsVehicleFactory::ClearVehicle() @@ -277,7 +282,7 @@ void OvmsVehicleFactory::SetVehicle(const char* type) void OvmsVehicleFactory::AutoInit() { - std::string type = MyConfig.GetParamValue("auto", "vehicle.type"); + std::string type = MyConfig.GetParamValue("auto", "vehicle.type", BASE_VEHICLE); if (!type.empty()) SetVehicle(type.c_str()); } From aec5056503b085d538e752e02827dd00958105be Mon Sep 17 00:00:00 2001 From: Jaime Date: Mon, 12 Aug 2024 18:15:33 -0400 Subject: [PATCH 36/45] version-wdt-factroy-if-2many-resets --- vehicle/OVMS.V3/main/ovms_housekeeping.cpp | 1 + vehicle/OVMS.V3/main/ovms_main.cpp | 2 +- vehicle/OVMS.V3/main/ovms_version.cpp | 4 +++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/vehicle/OVMS.V3/main/ovms_housekeeping.cpp b/vehicle/OVMS.V3/main/ovms_housekeeping.cpp index a42af1d63..530daffca 100644 --- a/vehicle/OVMS.V3/main/ovms_housekeeping.cpp +++ b/vehicle/OVMS.V3/main/ovms_housekeeping.cpp @@ -202,6 +202,7 @@ void Housekeeping::Init(std::string event, void* data) else if (MyBoot.GetEarlyCrashCount() >= AUTO_INIT_INHIBIT_CRASHCOUNT) { ESP_LOGE(TAG, "Auto init inhibited: too many early crashes (%d)", MyBoot.GetEarlyCrashCount()); + ExecuteDriverFactoryReset(); } else { diff --git a/vehicle/OVMS.V3/main/ovms_main.cpp b/vehicle/OVMS.V3/main/ovms_main.cpp index d91afaa18..5c150abc6 100644 --- a/vehicle/OVMS.V3/main/ovms_main.cpp +++ b/vehicle/OVMS.V3/main/ovms_main.cpp @@ -47,7 +47,7 @@ static class FrameworkInit }; ESP_ERROR_CHECK(esp_task_wdt_init(&config)); #else - esp_task_wdt_init(120, true); + esp_task_wdt_init(250, true); #endif #else ESP_LOGI(TAG, "WATCHDOG already initialized..."); diff --git a/vehicle/OVMS.V3/main/ovms_version.cpp b/vehicle/OVMS.V3/main/ovms_version.cpp index f53783214..315e39c80 100644 --- a/vehicle/OVMS.V3/main/ovms_version.cpp +++ b/vehicle/OVMS.V3/main/ovms_version.cpp @@ -207,7 +207,9 @@ void Version(std::string event, void* data) metric.append(" (build "); metric.append(GetOVMSBuild()); metric.append(")"); - StandardMetrics.ms_m_version->SetValue(metric.c_str()); + // StandardMetrics.ms_m_version->SetValue(metric.c_str()); + // CAMBIAR CON DIFERENTES VERSIONES + StandardMetrics.ms_m_version->SetValue("OVMS TUCAR V2.0"); metric = GetOVMSHardware(); StandardMetrics.ms_m_hardware->SetValue(metric.c_str()); From 5a17abb346a58007ec41390e8675c814043f7308 Mon Sep 17 00:00:00 2001 From: Jaime Date: Thu, 22 Aug 2024 10:39:25 -0400 Subject: [PATCH 37/45] connect after at least 10 secconds of good connection --- .../ovms_server_v3/src/ovms_server_v3.cpp | 48 ++++++++++++------- .../ovms_server_v3/src/ovms_server_v3.h | 1 + 2 files changed, 33 insertions(+), 16 deletions(-) diff --git a/vehicle/OVMS.V3/components/ovms_server_v3/src/ovms_server_v3.cpp b/vehicle/OVMS.V3/components/ovms_server_v3/src/ovms_server_v3.cpp index c73927b0f..262133700 100644 --- a/vehicle/OVMS.V3/components/ovms_server_v3/src/ovms_server_v3.cpp +++ b/vehicle/OVMS.V3/components/ovms_server_v3/src/ovms_server_v3.cpp @@ -95,6 +95,7 @@ static void OvmsServerV3MongooseCallback(struct mg_connection *nc, int ev, void StandardMetrics.ms_s_v3_peers->SetValue(0); MyOvmsServerV3->SetStatus("Error: Connection failed", true, OvmsServerV3::WaitReconnect); MyOvmsServerV3->m_connretry = 60; + MyOvmsServerV3->m_connection_counter = 0; } } } @@ -108,6 +109,7 @@ static void OvmsServerV3MongooseCallback(struct mg_connection *nc, int ev, void { MyOvmsServerV3->Disconnect(); MyOvmsServerV3->m_connretry = 60; + MyOvmsServerV3->m_connection_counter = 0; } } else @@ -173,6 +175,7 @@ static void OvmsServerV3MongooseCallback(struct mg_connection *nc, int ev, void { MyOvmsServerV3->Disconnect(); MyOvmsServerV3->m_connretry = 60; + MyOvmsServerV3->m_connection_counter = 0; } break; default: @@ -191,6 +194,7 @@ OvmsServerV3::OvmsServerV3(const char* name) SetStatus("Server has been started", false, WaitNetwork); m_connretry = 0; + m_connection_counter = 0; m_mgconn = NULL; m_sendall = false; m_lasttx = 0; @@ -626,12 +630,13 @@ void OvmsServerV3::CountClients() void OvmsServerV3::Connect() { - if (!m_connection_available) - { - ESP_LOGE(TAG, "No connection available, waiting for network"); - m_connretry = 10; - return; - } + if (!m_connection_available) + { + ESP_LOGE(TAG, "No connection available, waiting for network"); + m_connretry = 10; + m_connection_counter = 0; + return; + } m_msgid = 1; m_vehicleid = MyConfig.GetParamValue("vehicle", "id"); m_server = MyConfig.GetParamValue("server.v3", "server"); @@ -681,6 +686,7 @@ void OvmsServerV3::Connect() { SetStatus("Error: Parameter server.v3/server must be defined", true, WaitReconnect); m_connretry = 20; // Try again in 20 seconds... + m_connection_counter = 0; return; } @@ -706,6 +712,7 @@ void OvmsServerV3::Connect() { ESP_LOGE(TAG, "mg_connect(%s) failed: %s", address.c_str(), err); m_connretry = 20; // Try again in 20 seconds... + m_connection_counter = 0; return; } return; @@ -862,6 +869,7 @@ void OvmsServerV3::NetReconfigured(std::string event, void* data) ESP_LOGI(TAG, "Network was reconfigured: disconnect, and reconnect in 10 seconds"); Disconnect(); m_connretry = 10; + m_connection_counter = 0; } void OvmsServerV3::NetmanInit(std::string event, void* data) @@ -886,25 +894,33 @@ void OvmsServerV3::Ticker1(std::string event, void* data) { m_connection_available = StdMetrics.ms_m_net_connected->AsBool() && StdMetrics.ms_m_net_ip->AsBool() && - !StdMetrics.ms_m_net_good_sq->AsBool(); - + StdMetrics.ms_m_net_good_sq->AsBool(); if (!m_connection_available && m_mgconn) { Disconnect(); m_connretry = 10; } + + if (!m_connection_available) m_connection_counter = 0; + else if (m_connection_counter < 10) + { + m_connection_counter++; + if (m_connretry == 0 && m_connection_counter == 10) + { + if (m_mgconn) Disconnect(); // Disconnect first (timeout) + Connect(); // Kick off the connection + return; + } + } if (m_connretry > 0) { - if (m_connection_available) + m_connretry--; + if (m_connretry == 0 && m_connection_counter == 10) { - m_connretry--; - if (m_connretry == 0) - { - if (m_mgconn) Disconnect(); // Disconnect first (timeout) - Connect(); // Kick off the connection - return; - } + if (m_mgconn) Disconnect(); // Disconnect first (timeout) + Connect(); // Kick off the connection + return; } } diff --git a/vehicle/OVMS.V3/components/ovms_server_v3/src/ovms_server_v3.h b/vehicle/OVMS.V3/components/ovms_server_v3/src/ovms_server_v3.h index 812f0791c..29ef5b467 100644 --- a/vehicle/OVMS.V3/components/ovms_server_v3/src/ovms_server_v3.h +++ b/vehicle/OVMS.V3/components/ovms_server_v3/src/ovms_server_v3.h @@ -95,6 +95,7 @@ class OvmsServerV3 : public OvmsServer struct mg_connection *m_mgconn; OvmsMutex m_mgconn_mutex; int m_connretry; + int m_connection_counter; bool m_sendall; int m_msgid; int m_lasttx; From 86a6c18442f0c243ff6663e8fd005c65a76342b0 Mon Sep 17 00:00:00 2001 From: Jaime Date: Thu, 22 Aug 2024 10:42:02 -0400 Subject: [PATCH 38/45] config for good and bad quality signal for cellulat --- .../components/ovms_webserver/src/web_cfg.cpp | 78 ++++++++++++++----- vehicle/OVMS.V3/main/ovms_netmanager.cpp | 3 +- 2 files changed, 61 insertions(+), 20 deletions(-) diff --git a/vehicle/OVMS.V3/components/ovms_webserver/src/web_cfg.cpp b/vehicle/OVMS.V3/components/ovms_webserver/src/web_cfg.cpp index 6d5b65c99..35a2999b6 100644 --- a/vehicle/OVMS.V3/components/ovms_webserver/src/web_cfg.cpp +++ b/vehicle/OVMS.V3/components/ovms_webserver/src/web_cfg.cpp @@ -880,8 +880,9 @@ void OvmsWebServer::HandleCfgVehicle(PageEntry_t& p, PageContext_t& c) */ void OvmsWebServer::HandleCfgModem(PageEntry_t& p, PageContext_t& c) { - std::string apn, apn_user, apn_pass, network_dns, pincode; + std::string apn, apn_user, apn_pass, network_dns, pincode, error; bool enable_gps, enable_gpstime, enable_net, enable_sms, wrongpincode; + float cfg_sq_good, cfg_sq_bad; if (c.method == "POST") { // process form submission: @@ -894,27 +895,49 @@ void OvmsWebServer::HandleCfgModem(PageEntry_t& p, PageContext_t& c) enable_sms = (c.getvar("enable_sms") == "yes"); enable_gps = (c.getvar("enable_gps") == "yes"); enable_gpstime = (c.getvar("enable_gpstime") == "yes"); + cfg_sq_good = atof(c.getvar("cfg_sq_good").c_str()); + cfg_sq_bad = atof(c.getvar("cfg_sq_bad").c_str()); - MyConfig.SetParamValue("modem", "apn", apn); - MyConfig.SetParamValue("modem", "apn.user", apn_user); - MyConfig.SetParamValue("modem", "apn.password", apn_pass); - if ( MyConfig.GetParamValueBool("modem","wrongpincode") && (MyConfig.GetParamValue("modem","pincode") != pincode) ) + if (cfg_sq_bad >= cfg_sq_good) { - ESP_LOGI(TAG,"New SIM card PIN code entered. Cleared wrong_pin_code flag"); - MyConfig.SetParamValueBool("modem", "wrongpincode", false); + error += "
  • 'Bad' signal level must be lower than 'good' level.
  • "; } - MyConfig.SetParamValue("modem", "pincode", pincode); - MyConfig.SetParamValue("network", "dns", network_dns); - MyConfig.SetParamValueBool("modem", "enable.net", enable_net); - MyConfig.SetParamValueBool("modem", "enable.sms", enable_sms); - MyConfig.SetParamValueBool("modem", "enable.gps", enable_gps); - MyConfig.SetParamValueBool("modem", "enable.gpstime", enable_gpstime); + else + { + MyConfig.SetParamValue("modem", "apn", apn); + MyConfig.SetParamValue("modem", "apn.user", apn_user); + MyConfig.SetParamValue("modem", "apn.password", apn_pass); + if ( MyConfig.GetParamValueBool("modem","wrongpincode") && (MyConfig.GetParamValue("modem","pincode") != pincode) ) + { + ESP_LOGI(TAG,"New SIM card PIN code entered. Cleared wrong_pin_code flag"); + MyConfig.SetParamValueBool("modem", "wrongpincode", false); + } + MyConfig.SetParamValue("modem", "pincode", pincode); + MyConfig.SetParamValue("network", "dns", network_dns); + MyConfig.SetParamValueBool("modem", "enable.net", enable_net); + MyConfig.SetParamValueBool("modem", "enable.sms", enable_sms); + MyConfig.SetParamValueBool("modem", "enable.gps", enable_gps); + MyConfig.SetParamValueBool("modem", "enable.gpstime", enable_gpstime); + + MyConfig.SetParamValueFloat("network", "modem.sq.good", cfg_sq_good); + MyConfig.SetParamValueFloat("network", "modem.sq.bad", cfg_sq_bad); + } + if (error == "") + { + c.head(200); + c.alert("success", "

    Modem configured.

    "); + OutputHome(p, c); + c.done(); + return; + } + error = "

    Error!

      " + error + "
    "; + c.head(400); + c.alert("danger", error.c_str()); + } + else + { c.head(200); - c.alert("success", "

    Modem configured.

    "); - OutputHome(p, c); - c.done(); - return; } // read configuration: @@ -928,9 +951,10 @@ void OvmsWebServer::HandleCfgModem(PageEntry_t& p, PageContext_t& c) enable_sms = MyConfig.GetParamValueBool("modem", "enable.sms", true); enable_gps = MyConfig.GetParamValueBool("modem", "enable.gps", false); enable_gpstime = MyConfig.GetParamValueBool("modem", "enable.gpstime", false); + cfg_sq_good = MyConfig.GetParamValueFloat("network", "modem.sq.good", -95); + cfg_sq_bad = MyConfig.GetParamValueFloat("network", "modem.sq.bad", -93); // generate form: - c.head(200); c.panel_start("primary", "Cellular modem configuration"); c.form_start(p.uri); @@ -976,6 +1000,13 @@ void OvmsWebServer::HandleCfgModem(PageEntry_t& p, PageContext_t& c) c.input_checkbox("Use GPS time", "enable_gpstime", enable_gpstime); c.fieldset_end(); + c.fieldset_start("Cellular client options"); + c.input_slider("Good signal level", "cfg_sq_good", 3, "dBm", -1, cfg_sq_good, -93.0, -128.0, 0.0, 0.1, + "

    Threshold for usable wifi signal strength

    "); + c.input_slider("Bad signal level", "cfg_sq_bad", 3, "dBm", -1, cfg_sq_bad, -95.0, -128.0, 0.0, 0.1, + "

    Threshold for unusable wifi signal strength

    "); + c.fieldset_end(); + c.hr(); c.input_button("default", "Save"); c.form_end(); @@ -2044,6 +2075,7 @@ void OvmsWebServer::HandleCfgWebServer(PageEntry_t& p, PageContext_t& c) void OvmsWebServer::HandleCfgWifi(PageEntry_t& p, PageContext_t& c) { bool cfg_bad_reconnect; + bool cfg_reboot_no_ip; float cfg_sq_good, cfg_sq_bad; if (c.method == "POST") { @@ -2056,6 +2088,7 @@ void OvmsWebServer::HandleCfgWifi(PageEntry_t& p, PageContext_t& c) cfg_sq_good = atof(c.getvar("cfg_sq_good").c_str()); cfg_sq_bad = atof(c.getvar("cfg_sq_bad").c_str()); cfg_bad_reconnect = (c.getvar("cfg_bad_reconnect") == "yes"); + cfg_reboot_no_ip = (c.getvar("cfg_reboot_no_ip") == "yes"); if (cfg_sq_bad >= cfg_sq_good) { error += "
  • 'Bad' signal level must be lower than 'good' level.
  • "; @@ -2072,6 +2105,10 @@ void OvmsWebServer::HandleCfgWifi(PageEntry_t& p, PageContext_t& c) MyConfig.DeleteInstance("network", "wifi.bad.reconnect"); else MyConfig.SetParamValueBool("network", "wifi.bad.reconnect", cfg_bad_reconnect); + if (!cfg_reboot_no_ip) + MyConfig.DeleteInstance("network", "reboot.no.ip"); + else + MyConfig.SetParamValueBool("network", "reboot.no.ip", cfg_reboot_no_ip); } if (error == "") { @@ -2095,7 +2132,7 @@ void OvmsWebServer::HandleCfgWifi(PageEntry_t& p, PageContext_t& c) cfg_sq_good = MyConfig.GetParamValueFloat("network", "wifi.sq.good", -87); cfg_sq_bad = MyConfig.GetParamValueFloat("network", "wifi.sq.bad", -89); cfg_bad_reconnect = MyConfig.GetParamValueBool("network", "wifi.bad.reconnect", false); - + cfg_reboot_no_ip = MyConfig.GetParamValueBool("network", "reboot.no.ip", false); c.head(200); } @@ -2121,6 +2158,9 @@ void OvmsWebServer::HandleCfgWifi(PageEntry_t& p, PageContext_t& c) c.input_checkbox("Immediate disconnect/reconnect", "cfg_bad_reconnect", cfg_bad_reconnect, "

    Check to immediately look for better access points when signal level gets bad." " Default is to stay with the current AP as long as possible.

    "); + c.input_checkbox("Reboot when no IP is aquired after 5 minutes with a good connection", "cfg_reboot_no_ip", cfg_reboot_no_ip, + "

    Reboot device when there is good signal but the connection fails to obtain an IP address after 5 minutes." + " Takes into consideration both wifi and cellular connections.

    "); c.fieldset_end(); c.print( diff --git a/vehicle/OVMS.V3/main/ovms_netmanager.cpp b/vehicle/OVMS.V3/main/ovms_netmanager.cpp index 54c2a00de..93e5afbbd 100644 --- a/vehicle/OVMS.V3/main/ovms_netmanager.cpp +++ b/vehicle/OVMS.V3/main/ovms_netmanager.cpp @@ -661,6 +661,7 @@ void OvmsNetManager::Ticker1(std::string event, void *data) { if (m_connected_any && !m_has_ip && StdMetrics.ms_m_net_good_sq->AsBool()) { + ESP_LOGI(TAG, "Connection available with good signal, but no IP address; rebooting in %i seconds", 300-m_not_connected_counter); m_not_connected_counter++; if (m_not_connected_counter > 300) { @@ -745,7 +746,7 @@ void OvmsNetManager::ConfigChanged(std::string event, void* data) if (!param || param->GetName() == "network") { // Network config has been changed, apply: - m_cfg_reboot_no_connection = MyConfig.GetParamValueBool("network", "reboot.no.connection", false); + m_cfg_reboot_no_connection = MyConfig.GetParamValueBool("network", "reboot.no.ip", false); m_cfg_wifi_sq_good = MyConfig.GetParamValueFloat("network", "wifi.sq.good", -87); m_cfg_wifi_sq_bad = MyConfig.GetParamValueFloat("network", "wifi.sq.bad", -89); if (m_cfg_wifi_sq_good < m_cfg_wifi_sq_bad) From 39b0e2d3f16a5899f9b574768688e5cb690ae83e Mon Sep 17 00:00:00 2001 From: Jaime Middleton <30701876+Jamidd@users.noreply.github.com> Date: Mon, 26 Aug 2024 09:50:39 -0400 Subject: [PATCH 39/45] factory reset if config file is corrupted (#15) * factory reset if config file is corrupted * Update ovms_config.cpp * Update ovms_module.cpp --- vehicle/OVMS.V3/main/ovms_config.cpp | 11 +++++++++++ vehicle/OVMS.V3/main/ovms_module.cpp | 5 +++++ vehicle/OVMS.V3/main/ovms_module.h | 1 + 3 files changed, 17 insertions(+) diff --git a/vehicle/OVMS.V3/main/ovms_config.cpp b/vehicle/OVMS.V3/main/ovms_config.cpp index 06bca7b71..344fd5a24 100644 --- a/vehicle/OVMS.V3/main/ovms_config.cpp +++ b/vehicle/OVMS.V3/main/ovms_config.cpp @@ -46,6 +46,8 @@ static const char *TAG = "config"; #include "ovms_boot.h" #include "ovms_semaphore.h" #include "ovms_vfs.h" +#include "ovms_module.h" + #ifdef CONFIG_OVMS_SC_ZIP #include "zip_archive.h" @@ -1189,7 +1191,16 @@ void OvmsConfigParam::RewriteConfig() path.append(m_name); FILE* f = fopen(path.c_str(), "w"); if (!f) + { ESP_LOGE(TAG, "RewriteConfig: can't open '%s': %s", path.c_str(), strerror(errno)); + // in case /store/ovms_config/ is not accesible factory reset. + // This is a workaround in case config is corrupted + if (startsWith(path, "/store/ovms_config/")) + { + ESP_LOGE(TAG, "RewriteConfig: factory reset"); + ExecuteDriverFactoryReset(); + } + } else { #ifdef OVMS_PERSIST_METADATA diff --git a/vehicle/OVMS.V3/main/ovms_module.cpp b/vehicle/OVMS.V3/main/ovms_module.cpp index a9a016805..fc7ce5735 100644 --- a/vehicle/OVMS.V3/main/ovms_module.cpp +++ b/vehicle/OVMS.V3/main/ovms_module.cpp @@ -1134,6 +1134,11 @@ bool module_factory_reset_yesno(OvmsWriter* writer, void* ctx, char ch) return false; } +void ExecuteDriverFactoryReset() + { + module_perform_factoryreset(NULL); + } + static void module_factory_reset(int verbosity, OvmsWriter* writer, OvmsCommand* cmd, int argc, const char* const* argv) { if (argc > 0) diff --git a/vehicle/OVMS.V3/main/ovms_module.h b/vehicle/OVMS.V3/main/ovms_module.h index 27cdc8c9d..5ffb06456 100644 --- a/vehicle/OVMS.V3/main/ovms_module.h +++ b/vehicle/OVMS.V3/main/ovms_module.h @@ -31,6 +31,7 @@ #ifndef __OVMS_MODULE_H__ extern void AddTaskToMap(TaskHandle_t task); +extern void ExecuteDriverFactoryReset(); #define __OVMS_MODULE_H__ From 4ebb9d55659419db77b1dadc86d5068edc81344a Mon Sep 17 00:00:00 2001 From: Jaime Middleton <30701876+Jamidd@users.noreply.github.com> Date: Mon, 26 Aug 2024 10:13:37 -0400 Subject: [PATCH 40/45] Tucar/feat/support maxus euniq6 (#19) * Feat(init-commit-support-maxus-eu6) * Feat(correct-can-codes-and-tested) * Refactor(replacing-tabs-for-spaces) * Refactor(replacing-tabs-for-spaces) * Feat(Refactor-allign-table) * Refactor(remove-unnecessary-buffer) * Feat(rename-id-for-maxus-euniq6-to-not-conflict-with-existing) --------- Co-authored-by: axel troncoso --- .../vehicle_maxus_euniq6/CMakeLists.txt | 13 ++ .../vehicle_maxus_euniq6/component.mk | 14 ++ .../vehicle_maxus_euniq6/src/vehicle_me6.cpp | 172 ++++++++++++++++++ .../vehicle_maxus_euniq6/src/vehicle_me6.h | 58 ++++++ vehicle/OVMS.V3/main/Kconfig | 8 + 5 files changed, 265 insertions(+) create mode 100644 vehicle/OVMS.V3/components/vehicle_maxus_euniq6/CMakeLists.txt create mode 100644 vehicle/OVMS.V3/components/vehicle_maxus_euniq6/component.mk create mode 100644 vehicle/OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.cpp create mode 100644 vehicle/OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.h diff --git a/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/CMakeLists.txt b/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/CMakeLists.txt new file mode 100644 index 000000000..1c2ad99a3 --- /dev/null +++ b/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/CMakeLists.txt @@ -0,0 +1,13 @@ +set(srcs) +set(include_dirs) + +if (CONFIG_OVMS_VEHICLE_MAXE6) + list(APPEND srcs "vehicle_me6.cpp") + list(APPEND include_dirs "src") +endif () + +# requirements can't depend on config +idf_component_register(SRCS ${srcs} + INCLUDE_DIRS ${include_dirs} + PRIV_REQUIRES "main" + WHOLE_ARCHIVE) diff --git a/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/component.mk b/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/component.mk new file mode 100644 index 000000000..095e6f1e3 --- /dev/null +++ b/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/component.mk @@ -0,0 +1,14 @@ +# +# Main component makefile. +# +# This Makefile can be left empty. By default, it will take the sources in the +# src/ directory, compile them and link them into lib(subdirectory_name).a +# in the build directory. This behaviour is entirely configurable, +# please read the ESP-IDF documents if you need to do this. +# + +ifdef CONFIG_OVMS_VEHICLE_MAXE6 +COMPONENT_ADD_INCLUDEDIRS:=src +COMPONENT_SRCDIRS:=src +COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive +endif diff --git a/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.cpp b/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.cpp new file mode 100644 index 000000000..6d748a478 --- /dev/null +++ b/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.cpp @@ -0,0 +1,172 @@ +/* +; Project: Open Vehicle Monitor System +; Date: 14th August 2024 +; +; Changes: +; 1.0 Initial release +; +; (C) 2021 Jaime Middleton / Tucar +; (C) 2021 Axel Troncoso / Tucar +; +; Permission is hereby granted, free of charge, to any person obtaining a copy +; of this software and associated documentation files (the "Software"), to deal +; in the Software without restriction, including without limitation the rights +; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +; copies of the Software, and to permit persons to whom the Software is +; furnished to do so, subject to the following conditions: +; +; The above copyright notice and this permission notice shall be included in +; all copies or substantial portions of the Software. +; +; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +; THE SOFTWARE. +*/ + +#include "ovms_log.h" +static const char *TAG = "v-maxe6"; + +#include +#include + +#include "vehicle_me6.h" +#include "ovms_notify.h" +#include +#include "metrics_standard.h" + +// CAN buffer access macros: b=byte# 0..7 / n=nibble# 0..15 +#define CAN_BYTE(b) data[b] +#define CAN_INT(b) ((int16_t)CAN_UINT(b)) +#define CAN_UINT(b) (((UINT)CAN_BYTE(b) << 8) | CAN_BYTE(b+1)) +#define CAN_UINT24(b) (((uint32_t)CAN_BYTE(b) << 16) | ((UINT)CAN_BYTE(b+1) << 8) | CAN_BYTE(b+2)) +#define CAN_UINT32(b) (((uint32_t)CAN_BYTE(b) << 24) | ((uint32_t)CAN_BYTE(b+1) << 16) | ((UINT)CAN_BYTE(b+2) << 8) | CAN_BYTE(b+3)) +#define CAN_NIBL(b) (can_databuffer[b] & 0x0f) +#define CAN_NIBH(b) (can_databuffer[b] >> 4) +#define CAN_NIB(n) (((n)&1) ? CAN_NIBL((n)>>1) : CAN_NIBH((n)>>1)) +#define CAN_BIT(b,pos) !!(data[b] & (1<<(pos))) + +OvmsVehicleMaxe6::OvmsVehicleMaxe6() +{ + ESP_LOGI(TAG, "Start Maxus Euniq 6 vehicle module"); + + // Init CAN: + RegisterCanBus(1,CAN_MODE_ACTIVE,CAN_SPEED_500KBPS); + + // Init Energy: + StdMetrics.ms_v_charge_mode->SetValue("standard"); + + // Require GPS: + MyEvents.SignalEvent("vehicle.require.gps", NULL); + MyEvents.SignalEvent("vehicle.require.gpstime", NULL); +} + +OvmsVehicleMaxe6::~OvmsVehicleMaxe6() +{ + ESP_LOGI(TAG, "Stop Euniq 6 vehicle module"); +} + +void OvmsVehicleMaxe6::IncomingFrameCan1(CAN_frame_t *p_frame) +{ + /* + BASIC METRICS + StdMetrics.ms_v_pos_speed ok + StdMetrics.ms_v_bat_soc ok + StdMetrics.ms_v_pos_odometer ok + + StdMetrics.ms_v_door_fl ok + StdMetrics.ms_v_door_fr ok + StdMetrics.ms_v_door_rl ok + StdMetrics.ms_v_door_rr ok + StdMetrics.ms_v_trunk ok + StdMetrics.ms_v_env_locked ok + + StdMetrics.ms_v_bat_current - + StdMetrics.ms_v_bat_voltage - + StdMetrics.ms_v_bat_power wip (percentage units) + + StdMetrics.ms_v_charge_inprogress rev + + StdMetrics.ms_v_env_on ok + StdMetrics.ms_v_env_awake ok + + StdMetrics.ms_v_env_aux12v rev + */ + + uint8_t *data = p_frame->data.u8; + + switch (p_frame->MsgID) + { + case 0x0c9: + { + StdMetrics.ms_v_charge_inprogress->SetValue( + CAN_BIT(2,0) && CAN_BIT(2,1) && CAN_BIT(2,2) + ); + break; + } + case 0x281: + { + StdMetrics.ms_v_env_locked->SetValue( + CAN_BIT(1,0) && CAN_BIT(1,2) && CAN_BIT(1,4) && CAN_BIT(1,6) && + !StdMetrics.ms_v_door_fl->AsBool() && + !StdMetrics.ms_v_door_fr->AsBool() && + !StdMetrics.ms_v_door_rl->AsBool() && + !StdMetrics.ms_v_door_rr->AsBool() && + !StdMetrics.ms_v_door_trunk->AsBool()); + break; + } + case 0x46a: + { + StdMetrics.ms_v_door_fl->SetValue(CAN_BIT(0, 0)); + StdMetrics.ms_v_door_fr->SetValue(CAN_BIT(0, 3)); + StdMetrics.ms_v_door_rr->SetValue(CAN_BIT(0, 5)); + StdMetrics.ms_v_door_rl->SetValue(CAN_BIT(0, 7)); + StdMetrics.ms_v_door_trunk->SetValue(CAN_BIT(1, 1)); + break; + } + case 0x540: + { + StdMetrics.ms_v_pos_odometer->SetValue(CAN_UINT24(0)); + break; + } + case 0x6f0: + { + StdMetrics.ms_v_pos_speed->SetValue(CAN_BYTE(4)); + break; + } + case 0x6f1: + { + StdMetrics.ms_v_env_awake->SetValue(CAN_BIT(4,7)); + StdMetrics.ms_v_env_on->SetValue(CAN_BIT(1,4) && CAN_BIT(4,7)); + break; + } + case 0x6f2: + { + // Units percentage. + StdMetrics.ms_v_bat_soc->SetValue(CAN_BYTE(1)); + StdMetrics.ms_v_bat_power->SetValue((CAN_BYTE(2) - 100) * 120, kW); + break; + } + default: + break; + } +} + +void OvmsVehicleMaxe6::Ticker1(uint32_t ticker) +{ +} + +class OvmsVehicleMaxe6Init +{ +public: OvmsVehicleMaxe6Init(); +} OvmsVehicleMaxe6Init __attribute__ ((init_priority (9000))); + +OvmsVehicleMaxe6Init::OvmsVehicleMaxe6Init() +{ + ESP_LOGI(TAG, "Registering Vehicle: Maxus Euniq 6 (9000)"); + + MyVehicleFactory.RegisterVehicle("ME6","Maxus Euniq 6"); +} diff --git a/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.h b/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.h new file mode 100644 index 000000000..18f11bc99 --- /dev/null +++ b/vehicle/OVMS.V3/components/vehicle_maxus_euniq6/src/vehicle_me6.h @@ -0,0 +1,58 @@ +/* +; Project: Open Vehicle Monitor System +; Date: 14th August 2024 +; +; Changes: +; 1.0 Initial release +; +; (C) 2021 Jaime Middleton / Tucar +; (C) 2021 Axel Troncoso / Tucar +; +; Permission is hereby granted, free of charge, to any person obtaining a copy +; of this software and associated documentation files (the "Software"), to deal +; in the Software without restriction, including without limitation the rights +; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +; copies of the Software, and to permit persons to whom the Software is +; furnished to do so, subject to the following conditions: +; +; The above copyright notice and this permission notice shall be included in +; all copies or substantial portions of the Software. +; +; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +; THE SOFTWARE. +*/ + +#ifndef __VEHICLE_ME6_H__ +#define __VEHICLE_ME6_H__ + +#include "vehicle.h" +#include "metrics_standard.h" + +#include "freertos/timers.h" + +#include + + +using namespace std; + +class OvmsVehicleMaxe6 : public OvmsVehicle +{ +public: + + OvmsVehicleMaxe6(); + ~OvmsVehicleMaxe6(); + +protected: + void Ticker1(uint32_t ticker) override; + +private: + void IncomingFrameCan1(CAN_frame_t* p_frame) override; +}; + +#endif //#ifndef __VEHICLE_ME6_H__ + diff --git a/vehicle/OVMS.V3/main/Kconfig b/vehicle/OVMS.V3/main/Kconfig index bbb98d782..bc94123a2 100644 --- a/vehicle/OVMS.V3/main/Kconfig +++ b/vehicle/OVMS.V3/main/Kconfig @@ -429,6 +429,14 @@ config OVMS_VEHICLE_MAXE56 depends on OVMS_COMP_POLLER help Enable to include support for Maxus Euniq 5 6-seats vehicle. + +config OVMS_VEHICLE_MAXE6 + bool "Include support for Maxus Euniq 6 vehicle" + default y + depends on OVMS + depends on OVMS_COMP_POLLER + help + Enable to include support for Maxus Euniq 6 vehicle. config OVMS_VEHICLE_KIASOULEV bool "Include support for Kia Soul EV vehicles" From 8984f71810098bc7b7b47011bf26891d799d98a8 Mon Sep 17 00:00:00 2001 From: Jaime Middleton <30701876+Jamidd@users.noreply.github.com> Date: Mon, 26 Aug 2024 10:14:10 -0400 Subject: [PATCH 41/45] Tucar/feat/support maple 60s (#20) * Feat(support-for-door-status-on-maple) * Feat(tested-maple-with-logs) * Feat(removing-unnecessary-logs) * Feat(remove-maple-docs) * Refactor(Replace-tabs-for-spaces) * Refactor(Replace-tabs-for-spaces) * Refactor(allign-table) * Refactor(general) * Refactor(removing-unnecessary-data-buffer) * Refactor(removing-unnecessary-data-buffer) * fix kconfig --------- Co-authored-by: axel troncoso --- .../vehicle_maple60s/CMakeLists.txt | 13 ++ .../components/vehicle_maple60s/component.mk | 14 ++ .../src/vehicle_maple_60s.cpp | 195 ++++++++++++++++++ .../vehicle_maple60s/src/vehicle_maple_60s.h | 51 +++++ vehicle/OVMS.V3/main/Kconfig | 9 + 5 files changed, 282 insertions(+) create mode 100644 vehicle/OVMS.V3/components/vehicle_maple60s/CMakeLists.txt create mode 100644 vehicle/OVMS.V3/components/vehicle_maple60s/component.mk create mode 100644 vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.cpp create mode 100644 vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.h diff --git a/vehicle/OVMS.V3/components/vehicle_maple60s/CMakeLists.txt b/vehicle/OVMS.V3/components/vehicle_maple60s/CMakeLists.txt new file mode 100644 index 000000000..445c99f7d --- /dev/null +++ b/vehicle/OVMS.V3/components/vehicle_maple60s/CMakeLists.txt @@ -0,0 +1,13 @@ +set(srcs) +set(include_dirs) + +if (CONFIG_OVMS_VEHICLE_MAPLE60S) + list(APPEND srcs "src/vehicle_maple60s.cpp") + list(APPEND include_dirs "src") +endif () + +# requirements can't depend on config +idf_component_register(SRCS ${srcs} + INCLUDE_DIRS ${include_dirs} + PRIV_REQUIRES "main" + WHOLE_ARCHIVE) \ No newline at end of file diff --git a/vehicle/OVMS.V3/components/vehicle_maple60s/component.mk b/vehicle/OVMS.V3/components/vehicle_maple60s/component.mk new file mode 100644 index 000000000..040f9e492 --- /dev/null +++ b/vehicle/OVMS.V3/components/vehicle_maple60s/component.mk @@ -0,0 +1,14 @@ +# +# Main component makefile. +# +# This Makefile can be left empty. By default, it will take the sources in the +# src/ directory, compile them and link them into lib(subdirectory_name).a +# in the build directory. This behaviour is entirely configurable, +# please read the ESP-IDF documents if you need to do this. +# + +ifdef CONFIG_OVMS_VEHICLE_MAPLE60S +COMPONENT_ADD_INCLUDEDIRS:=src +COMPONENT_SRCDIRS:=src +COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive +endif diff --git a/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.cpp b/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.cpp new file mode 100644 index 000000000..08acae91a --- /dev/null +++ b/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.cpp @@ -0,0 +1,195 @@ +/* +; Project: Open Vehicle Monitor System +; Date: 16th August 2024 +; +; Changes: +; 1.0 Initial stub +; +; (C) 2024 Jaime Middleton / Tucar +; (C) 2024 Axel Troncoso / Tucar +; +; Permission is hereby granted, free of charge, to any person obtaining a copy +; of this software and associated documentation files (the "Software"), to deal +; in the Software without restriction, including without limitation the rights +; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +; copies of the Software, and to permit persons to whom the Software is +; furnished to do so, subject to the following conditions: +; +; The above copyright notice and this permission notice shall be included in +; all copies or substantial portions of the Software. +; +; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +; THE SOFTWARE. +*/ + +#include "vehicle_maple_60s.h" + +#include +#include + +#include "metrics_standard.h" +#include "ovms_log.h" +#include "ovms_metrics.h" + +#define VERSION "0.0.1" + +static const char *TAG = "v-maple60s"; + +// CAN buffer access macros: b=byte# 0..7 / n=nibble# 0..15 +#define CAN_BYTE(b) data[b] +#define CAN_INT(b) ((int16_t)CAN_UINT(b)) +#define CAN_UINT(b) (((UINT)CAN_BYTE(b) << 8) | CAN_BYTE(b+1)) +#define CAN_UINT24(b) (((uint32_t)CAN_BYTE(b) << 16) | ((UINT)CAN_BYTE(b+1) << 8) | CAN_BYTE(b+2)) +#define CAN_UINT32(b) (((uint32_t)CAN_BYTE(b) << 24) | ((uint32_t)CAN_BYTE(b+1) << 16) | ((UINT)CAN_BYTE(b+2) << 8) | CAN_BYTE(b+3)) +#define CAN_NIBL(b) (can_databuffer[b] & 0x0f) +#define CAN_NIBH(b) (can_databuffer[b] >> 4) +#define CAN_NIB(n) (((n)&1) ? CAN_NIBL((n)>>1) : CAN_NIBH((n)>>1)) +#define CAN_BIT(b,pos) !!(data[b] & (1<<(pos))) + +OvmsVehicleMaple60S::OvmsVehicleMaple60S() +{ + ESP_LOGI(TAG, "Maple 60s vehicle module"); + + m_door_lock_status.fill(false); + + StdMetrics.ms_v_charge_inprogress->SetValue(false); + StdMetrics.ms_v_env_on->SetValue(false); + StdMetrics.ms_v_env_locked->SetValue(false); + + // Require GPS. + MyEvents.SignalEvent("vehicle.require.gps", NULL); + MyEvents.SignalEvent("vehicle.require.gpstime", NULL); + + RegisterCanBus(1, CAN_MODE_LISTEN, CAN_SPEED_500KBPS); +} + +OvmsVehicleMaple60S::~OvmsVehicleMaple60S() +{ + ESP_LOGI(TAG, "Shutdown Maple 60S vehicle module"); +} + +void OvmsVehicleMaple60S::Ticker1(uint32_t ticker) +{ +} + +void OvmsVehicleMaple60S::IncomingFrameCan1(CAN_frame_t *p_frame) +{ + /* + BASIC METRICS + StdMetrics.ms_v_pos_speed ok + StdMetrics.ms_v_bat_soc ok + StdMetrics.ms_v_pos_odometer ok + + StdMetrics.ms_v_door_fl ok + StdMetrics.ms_v_door_fr ok + StdMetrics.ms_v_door_rl ok + StdMetrics.ms_v_door_rr ok + StdMetrics.ms_v_env_locked ok + + StdMetrics.ms_v_bat_current NA + StdMetrics.ms_v_bat_voltage NA + StdMetrics.ms_v_bat_power ok + + StdMetrics.ms_v_charge_inprogress rev + + StdMetrics.ms_v_env_on ok + StdMetrics.ms_v_env_awake ok + + StdMetrics.ms_v_env_aux12v rev + */ + + uint8_t *data = p_frame->data.u8; + + switch (p_frame->MsgID) + { + case 0x250: + StdMetrics.ms_v_charge_inprogress->SetValue(CAN_BIT(7, 0)); + break; + case 0x3F1: + StdMetrics.ms_v_pos_odometer->SetValue(CAN_UINT24(0) / 10.0, Kilometers); + break; + case 0x125: + StdMetrics.ms_v_pos_speed->SetValue((CAN_BYTE(1) * 2) + (2 * (CAN_BYTE(2) - 1) / 250.0)); + break; + case 0x162: // awake, on, off and power + { + StdMetrics.ms_v_env_awake->SetValue(CAN_BIT(5, 0)); + StdMetrics.ms_v_env_on->SetValue(CAN_BIT(3, 7) && CAN_BIT(5, 0)); + StdMetrics.ms_v_bat_power->SetValue(CAN_BYTE(4) - 100); + + auto usingCcsCharger = StdMetrics.ms_v_bat_power->AsFloat(0, kW) < -15; + StdMetrics.ms_v_charge_type->SetValue(usingCcsCharger ? "ccs" : "type2"); + break; + } + case 0x2F4: // Charge state + StdMetrics.ms_v_bat_soc->SetValue((100 * CAN_BYTE(1)) / 255, Percentage); + break; + case 0x235: + StdMetrics.ms_v_env_aux12v->SetValue((CAN_BYTE(7) + 67)/15); + break; + case 0x284: + { + StdMetrics.ms_v_door_trunk->SetValue(CAN_BIT(1, 2)); + break; + } + case 0x285: + { + StdMetrics.ms_v_door_fl->SetValue(CAN_BIT(4, 0)); + StdMetrics.ms_v_door_rl->SetValue(CAN_BIT(4, 1)); + + /* It's unclear which bit is associated with which door. + * However this doesn't matter since to consider the + * vehicle locked, all must be locked. */ + m_door_lock_status[0] = CAN_BIT(4, 2); + m_door_lock_status[1] = CAN_BIT(4, 4); + + auto vehicle_locked = std::accumulate( + m_door_lock_status.begin(), + m_door_lock_status.end(), + true, + [](bool a, bool b) + { return a && b; }); + + StdMetrics.ms_v_env_locked->SetValue(vehicle_locked); + break; + } + case 0x286: + { + StdMetrics.ms_v_door_fr->SetValue(CAN_BIT(4, 0)); + StdMetrics.ms_v_door_rr->SetValue(CAN_BIT(4, 1)); + + /* It's unclear which bit is associated with which door. + * However this doesn't matter since to consider the + * vehicle locked, all must be locked. */ + m_door_lock_status[2] = CAN_BIT(4, 2); + m_door_lock_status[3] = CAN_BIT(4, 4); + + auto vehicle_locked = std::accumulate( + m_door_lock_status.begin(), + m_door_lock_status.end(), + true, + [](bool a, bool b) + { return a && b; }); + + StdMetrics.ms_v_env_locked->SetValue(vehicle_locked); + break; + } + } +} + +class OvmsVehicleMaple60SInit +{ + public: + OvmsVehicleMaple60SInit(); +} MyOvmsVehicleMaple60SInit __attribute__((init_priority(9000))); + +OvmsVehicleMaple60SInit::OvmsVehicleMaple60SInit() +{ + ESP_LOGI(TAG, "Registering Vehicle: Maple 60S (9000)"); + MyVehicleFactory.RegisterVehicle("MPL60S", "Maple 60S"); +} diff --git a/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.h b/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.h new file mode 100644 index 000000000..945638ac6 --- /dev/null +++ b/vehicle/OVMS.V3/components/vehicle_maple60s/src/vehicle_maple_60s.h @@ -0,0 +1,51 @@ +/* +; Project: Open Vehicle Monitor System +; Date: 16th August 2024 +; +; Changes: +; 1.0 Initial stub +; +; (C) 2024 Jaime Middleton / Tucar +; (C) 2024 Axel Troncoso / Tucar +; +; Permission is hereby granted, free of charge, to any person obtaining a copy +; of this software and associated documentation files (the "Software"), to deal +; in the Software without restriction, including without limitation the rights +; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +; copies of the Software, and to permit persons to whom the Software is +; furnished to do so, subject to the following conditions: +; +; The above copyright notice and this permission notice shall be included in +; all copies or substantial portions of the Software. +; +; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +; THE SOFTWARE. +*/ + +#ifndef __VEHICLE_MAPLE60S_H__ +#define __VEHICLE_MAPLE60S_H__ + +#include "vehicle.h" + +using namespace std; + +class OvmsVehicleMaple60S : public OvmsVehicle +{ +public: + OvmsVehicleMaple60S(); + ~OvmsVehicleMaple60S(); + +public: + void IncomingFrameCan1(CAN_frame_t *p_frame) override; + void Ticker1(uint32_t ticker) override; + +private: + std::array m_door_lock_status; +}; + +#endif // #ifndef __VEHICLE_MAPLE60S_H__ \ No newline at end of file diff --git a/vehicle/OVMS.V3/main/Kconfig b/vehicle/OVMS.V3/main/Kconfig index bc94123a2..d8935bcbb 100644 --- a/vehicle/OVMS.V3/main/Kconfig +++ b/vehicle/OVMS.V3/main/Kconfig @@ -601,6 +601,7 @@ config OVMS_VEHICLE_TOYOTARAV4EV depends on OVMS help Enable to include support for Toyota RAV4 EV vehicles. + config OVMS_VEHICLE_BYD_ATTO3 bool "Include support for BYD Atto 3" default y @@ -624,6 +625,14 @@ config OVMS_VEHICLE_DONGFENG_E60 help Enable support for Dong Feng E60 +config OVMS_VEHICLE_MAPLE60S + bool "Include support for Maple 60s" + default y + depends on OVMS + depends on OVMS_COMP_POLLER + help + Enable support for Maple 60s + config OVMS_VEHICLE_RXTASK_STACK int "Stack size for ISOTP Poller RX task" default 6144 From 943175c6bbf505a0c51572ac3cac5f823f983b86 Mon Sep 17 00:00:00 2001 From: Jaime Middleton <30701876+Jamidd@users.noreply.github.com> Date: Mon, 26 Aug 2024 11:32:48 -0400 Subject: [PATCH 42/45] Tucar/feature/mqtt command throttling (#21) * mqtt command throttling * fix code style --- .../ovms_server_v3/src/ovms_server_v3.cpp | 14 ++++++++++++-- .../components/ovms_server_v3/src/ovms_server_v3.h | 1 + 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/vehicle/OVMS.V3/components/ovms_server_v3/src/ovms_server_v3.cpp b/vehicle/OVMS.V3/components/ovms_server_v3/src/ovms_server_v3.cpp index b72ef62b8..927bc58ea 100644 --- a/vehicle/OVMS.V3/components/ovms_server_v3/src/ovms_server_v3.cpp +++ b/vehicle/OVMS.V3/components/ovms_server_v3/src/ovms_server_v3.cpp @@ -137,8 +137,13 @@ static void OvmsServerV3MongooseCallback(struct mg_connection *nc, int ev, void msg->topic.p, (int) msg->payload.len, msg->payload.p); if (MyOvmsServerV3) { - MyOvmsServerV3->IncomingMsg(std::string(msg->topic.p,msg->topic.len), - std::string(msg->payload.p,msg->payload.len)); + if (MyOvmsServerV3->m_accept_command == 0) + { + MyOvmsServerV3->m_accept_command = 2; + MyOvmsServerV3->IncomingMsg( + std::string(msg->topic.p,msg->topic.len), + std::string(msg->payload.p,msg->payload.len)); + } } if (msg->qos == 1) { @@ -210,6 +215,7 @@ OvmsServerV3::OvmsServerV3(const char* name) m_notify_data_waitcomp = 0; m_notify_data_waittype = NULL; m_notify_data_waitentry = NULL; + m_accept_command = 0; ESP_LOGI(TAG, "OVMS Server v3 running"); @@ -877,6 +883,10 @@ void OvmsServerV3::NetmanStop(std::string event, void* data) void OvmsServerV3::Ticker1(std::string event, void* data) { + if (m_accept_command > 0) + { + m_accept_command--; + } if (m_connretry > 0) { if (MyNetManager.m_connected_any) diff --git a/vehicle/OVMS.V3/components/ovms_server_v3/src/ovms_server_v3.h b/vehicle/OVMS.V3/components/ovms_server_v3/src/ovms_server_v3.h index af843d280..fa2763fbb 100644 --- a/vehicle/OVMS.V3/components/ovms_server_v3/src/ovms_server_v3.h +++ b/vehicle/OVMS.V3/components/ovms_server_v3/src/ovms_server_v3.h @@ -96,6 +96,7 @@ class OvmsServerV3 : public OvmsServer OvmsMutex m_mgconn_mutex; int m_connretry; bool m_sendall; + int m_accept_command; int m_msgid; int m_lasttx; int m_lasttx_sendall; From ec6e918a52c04811b64eae3095537b86b2125baa Mon Sep 17 00:00:00 2001 From: Jaime Middleton <30701876+Jamidd@users.noreply.github.com> Date: Mon, 26 Aug 2024 11:50:38 -0400 Subject: [PATCH 43/45] Tucar/feature/server v3 connect if ip (#17) * wifiHasIp * connectIIFip * reset if not connected connected with connection available * missing imports * fix definitions * rename functions * wifi ip via events * reboot if no ip and good connection signal * server v3 connection takes into account usable signal quality * fix code style * connect after at least 10 secconds of good connection * config for good and bad quality signal for cellulat --------- Co-authored-by: atroncoso-tucar --- .../components/esp32wifi/src/esp32wifi.cpp | 42 ++++++++-- .../components/esp32wifi/src/esp32wifi.h | 5 ++ .../ovms_cellular/src/ovms_cellular.cpp | 30 ++++++- .../ovms_cellular/src/ovms_cellular.h | 5 ++ .../ovms_server_v3/src/ovms_server_v3.cpp | 49 ++++++++++-- .../ovms_server_v3/src/ovms_server_v3.h | 2 + .../components/ovms_webserver/src/web_cfg.cpp | 78 ++++++++++++++----- vehicle/OVMS.V3/main/metrics_standard.cpp | 3 + vehicle/OVMS.V3/main/metrics_standard.h | 6 ++ vehicle/OVMS.V3/main/ovms_netmanager.cpp | 33 +++++++- vehicle/OVMS.V3/main/ovms_netmanager.h | 4 + 11 files changed, 221 insertions(+), 36 deletions(-) diff --git a/vehicle/OVMS.V3/components/esp32wifi/src/esp32wifi.cpp b/vehicle/OVMS.V3/components/esp32wifi/src/esp32wifi.cpp index 83216d11a..50ef7edd4 100644 --- a/vehicle/OVMS.V3/components/esp32wifi/src/esp32wifi.cpp +++ b/vehicle/OVMS.V3/components/esp32wifi/src/esp32wifi.cpp @@ -375,6 +375,7 @@ esp32wifi::esp32wifi(const char* name) m_sta_reconnect = 0; m_sta_connected = false; m_sta_rssi = -1270; + m_good_signal = false; memset(&m_wifi_ap_cfg,0,sizeof(m_wifi_ap_cfg)); memset(&m_wifi_sta_cfg,0,sizeof(m_wifi_sta_cfg)); memset(&m_mac_ap,0,sizeof(m_mac_ap)); @@ -399,6 +400,9 @@ esp32wifi::esp32wifi(const char* name) MyEvents.RegisterEvent(TAG,"system.wifi.ap.sta.connected",std::bind(&esp32wifi::EventWifiApUpdate, this, _1, _2)); MyEvents.RegisterEvent(TAG,"system.wifi.ap.sta.disconnected",std::bind(&esp32wifi::EventWifiApUpdate, this, _1, _2)); MyEvents.RegisterEvent(TAG,"system.shuttingdown",std::bind(&esp32wifi::EventSystemShuttingDown, this, _1, _2)); + MyEvents.RegisterEvent(TAG,"config.mounted", std::bind(&esp32wifi::ConfigChanged, this, _1, _2)); + MyEvents.RegisterEvent(TAG,"config.changed", std::bind(&esp32wifi::ConfigChanged, this, _1, _2)); + ConfigChanged("config.mounted", NULL); } esp32wifi::~esp32wifi() @@ -996,13 +1000,19 @@ void esp32wifi::UpdateNetMetrics() m_sta_rssi = -1270; } - StdMetrics.ms_m_net_wifi_network->SetValue(GetSSID()); - StdMetrics.ms_m_net_wifi_sq->SetValue((float)m_sta_rssi/10, dbm); - if (StdMetrics.ms_m_net_type->AsString() == "wifi") - { - StdMetrics.ms_m_net_provider->SetValue(GetSSID()); - StdMetrics.ms_m_net_sq->SetValue((int)(m_sta_rssi-5)/10, dbm); - } + float current_dbm = (float)m_sta_rssi / 10; + StdMetrics.ms_m_net_wifi_network->SetValue(GetSSID()); + StdMetrics.ms_m_net_wifi_sq->SetValue(current_dbm, dbm); + if (StdMetrics.ms_m_net_type->AsString() == "wifi") + { + StdMetrics.ms_m_net_provider->SetValue(GetSSID()); + StdMetrics.ms_m_net_sq->SetValue((int)(m_sta_rssi-5)/10, dbm); + if (m_good_signal && current_dbm < m_bad_dbm) + m_good_signal = false; + if (!m_good_signal && current_dbm > m_good_dbm) + m_good_signal = true; + StdMetrics.ms_m_net_good_sq->SetValue(m_good_signal); + } } void esp32wifi::EventWifiGotIp(std::string event, void* data) @@ -1021,6 +1031,13 @@ void esp32wifi::EventWifiGotIp(std::string event, void* data) IP2STR(&m_ip_info_sta.ip), IP2STR(&m_ip_info_sta.netmask), IP2STR(&m_ip_info_sta.gw)); } +bool esp32wifi::WifiHasIp() + { + char numstr[150]; + sprintf(numstr, IPSTR, IP2STR(&m_ip_info_sta.ip)); + return strcmp(numstr, "0.0.0.0") == 1; + } + void esp32wifi::EventWifiLostIp(std::string event, void* data) { memset(&m_ip_info_sta,0,sizeof(m_ip_info_sta)); @@ -1393,6 +1410,17 @@ void esp32wifi::OutputStatus(int verbosity, OvmsWriter* writer) } } +void esp32wifi::ConfigChanged(std::string event, void* data) + { + OvmsConfigParam* param = (OvmsConfigParam*)data; + if (event == "config.mounted" || !param || param->GetName() == "network") + { + // Network config has been changed, apply: + m_good_dbm = MyConfig.GetParamValueFloat("network", "wifi.sq.good", -87); + m_bad_dbm = MyConfig.GetParamValueFloat("network", "wifi.sq.bad", -89); + } + } + void esp32wifi::StartDhcpClient() { if (m_mode == ESP32WIFI_MODE_CLIENT || m_mode == ESP32WIFI_MODE_APCLIENT) diff --git a/vehicle/OVMS.V3/components/esp32wifi/src/esp32wifi.h b/vehicle/OVMS.V3/components/esp32wifi/src/esp32wifi.h index 2725340fa..6d6d8fb90 100644 --- a/vehicle/OVMS.V3/components/esp32wifi/src/esp32wifi.h +++ b/vehicle/OVMS.V3/components/esp32wifi/src/esp32wifi.h @@ -87,6 +87,7 @@ class esp32wifi : public pcp, public InternalRamAllocated void StartDhcpClient(); void SetSTAWifiIP(std::string ip="", std::string sn="", std::string gw=""); void SetAPWifiBW(); + bool WifiHasIp(); public: void EventWifiStaState(std::string event, void* data); @@ -100,6 +101,7 @@ class esp32wifi : public pcp, public InternalRamAllocated void EventWifiScanDone(std::string event, void* data); void EventSystemShuttingDown(std::string event, void* data); void OutputStatus(int verbosity, OvmsWriter* writer); + void ConfigChanged(std::string event, void *data); protected: bool m_poweredup; @@ -132,6 +134,9 @@ class esp32wifi : public pcp, public InternalRamAllocated uint32_t m_sta_reconnect; wifi_ap_record_t m_sta_ap_info; int m_sta_rssi; // smoothed RSSI [dBm/10] + float m_good_dbm; + float m_bad_dbm; + bool m_good_signal; }; #endif //#ifndef __ESP32WIFI_H__ diff --git a/vehicle/OVMS.V3/components/ovms_cellular/src/ovms_cellular.cpp b/vehicle/OVMS.V3/components/ovms_cellular/src/ovms_cellular.cpp index 6f8683364..e88fda2f3 100644 --- a/vehicle/OVMS.V3/components/ovms_cellular/src/ovms_cellular.cpp +++ b/vehicle/OVMS.V3/components/ovms_cellular/src/ovms_cellular.cpp @@ -41,6 +41,7 @@ static const char *TAG = "cellular"; #include "ovms_events.h" #include "ovms_notify.h" #include "ovms_boot.h" +#include "ovms_config.h" //////////////////////////////////////////////////////////////////////////////// // Global convenience variables @@ -292,6 +293,7 @@ modem::modem(const char* name, uart_port_t uartnum, int baud, int rxpin, int txp for (size_t k=0; kGetName() == "network") + { + // Network config has been changed, apply: + m_good_dbm = MyConfig.GetParamValueFloat("network", "modem.sq.good", -95); + m_bad_dbm = MyConfig.GetParamValueFloat("network", "modem.sq.bad", -93); + } + } + void modem::IncomingMuxData(GsmMuxChannel* channel) { // The MUX has indicated there is data on the specified channel @@ -1616,10 +1637,16 @@ void modem::SetSignalQuality(int newsq) { m_sq = newsq; ESP_LOGD(TAG, "Signal Quality is: %d (%d dBm)", m_sq, UnitConvert(sq, dbm, m_sq)); + float current_dbm = UnitConvert(sq, dbm, m_sq); StdMetrics.ms_m_net_mdm_sq->SetValue(m_sq, sq); if (StdMetrics.ms_m_net_type->AsString() == "modem") { StdMetrics.ms_m_net_sq->SetValue(m_sq, sq); + if (m_good_signal && current_dbm < m_bad_dbm) + m_good_signal = false; + if (!m_good_signal && current_dbm > m_good_dbm) + m_good_signal = true; + StdMetrics.ms_m_net_good_sq->SetValue(m_good_signal); } } } @@ -1634,6 +1661,7 @@ void modem::ClearNetMetrics() StdMetrics.ms_m_net_mdm_network->Clear(); m_sq = 99; + m_good_signal = false; StdMetrics.ms_m_net_mdm_sq->Clear(); if (StdMetrics.ms_m_net_type->AsString() == "modem") diff --git a/vehicle/OVMS.V3/components/ovms_cellular/src/ovms_cellular.h b/vehicle/OVMS.V3/components/ovms_cellular/src/ovms_cellular.h index a00db8c1a..2bc3e5204 100644 --- a/vehicle/OVMS.V3/components/ovms_cellular/src/ovms_cellular.h +++ b/vehicle/OVMS.V3/components/ovms_cellular/src/ovms_cellular.h @@ -65,6 +65,9 @@ class modem : public pcp, public InternalRamAllocated int m_txpin; int m_pwregpio; int m_dtregpio; + float m_good_dbm; + float m_bad_dbm; + bool m_good_signal; public: typedef enum @@ -199,6 +202,7 @@ class modem : public pcp, public InternalRamAllocated public: // High level API functions + bool ModemIsNetMode(); void StartTask(); void StopTask(); bool StartNMEA(bool force=false); @@ -211,6 +215,7 @@ class modem : public pcp, public InternalRamAllocated void Task(); void Ticker(std::string event, void* data); void EventListener(std::string event, void* data); + void ConfigChanged(std::string event, void *data); void IncomingMuxData(GsmMuxChannel* channel); void SendSetState1(modem_state1_t newstate); bool IsStarted(); diff --git a/vehicle/OVMS.V3/components/ovms_server_v3/src/ovms_server_v3.cpp b/vehicle/OVMS.V3/components/ovms_server_v3/src/ovms_server_v3.cpp index 927bc58ea..af7f08312 100644 --- a/vehicle/OVMS.V3/components/ovms_server_v3/src/ovms_server_v3.cpp +++ b/vehicle/OVMS.V3/components/ovms_server_v3/src/ovms_server_v3.cpp @@ -95,6 +95,7 @@ static void OvmsServerV3MongooseCallback(struct mg_connection *nc, int ev, void StandardMetrics.ms_s_v3_peers->SetValue(0); MyOvmsServerV3->SetStatus("Error: Connection failed", true, OvmsServerV3::WaitReconnect); MyOvmsServerV3->m_connretry = 60; + MyOvmsServerV3->m_connection_counter = 0; } } } @@ -108,6 +109,7 @@ static void OvmsServerV3MongooseCallback(struct mg_connection *nc, int ev, void { MyOvmsServerV3->Disconnect(); MyOvmsServerV3->m_connretry = 60; + MyOvmsServerV3->m_connection_counter = 0; } } else @@ -178,6 +180,7 @@ static void OvmsServerV3MongooseCallback(struct mg_connection *nc, int ev, void { MyOvmsServerV3->Disconnect(); MyOvmsServerV3->m_connretry = 60; + MyOvmsServerV3->m_connection_counter = 0; } break; default: @@ -196,6 +199,7 @@ OvmsServerV3::OvmsServerV3(const char* name) SetStatus("Server has been started", false, WaitNetwork); m_connretry = 0; + m_connection_counter = 0; m_mgconn = NULL; m_sendall = false; m_lasttx = 0; @@ -215,6 +219,7 @@ OvmsServerV3::OvmsServerV3(const char* name) m_notify_data_waitcomp = 0; m_notify_data_waittype = NULL; m_notify_data_waitentry = NULL; + m_connection_available = false; m_accept_command = 0; ESP_LOGI(TAG, "OVMS Server v3 running"); @@ -631,6 +636,13 @@ void OvmsServerV3::CountClients() void OvmsServerV3::Connect() { + if (!m_connection_available) + { + ESP_LOGE(TAG, "No connection available, waiting for network"); + m_connretry = 10; + m_connection_counter = 0; + return; + } m_msgid = 1; m_vehicleid = MyConfig.GetParamValue("vehicle", "id"); m_server = MyConfig.GetParamValue("server.v3", "server"); @@ -680,6 +692,7 @@ void OvmsServerV3::Connect() { SetStatus("Error: Parameter server.v3/server must be defined", true, WaitReconnect); m_connretry = 20; // Try again in 20 seconds... + m_connection_counter = 0; return; } @@ -705,6 +718,7 @@ void OvmsServerV3::Connect() { ESP_LOGE(TAG, "mg_connect(%s) failed: %s", address.c_str(), err); m_connretry = 20; // Try again in 20 seconds... + m_connection_counter = 0; return; } return; @@ -861,6 +875,7 @@ void OvmsServerV3::NetReconfigured(std::string event, void* data) ESP_LOGI(TAG, "Network was reconfigured: disconnect, and reconnect in 10 seconds"); Disconnect(); m_connretry = 10; + m_connection_counter = 0; } void OvmsServerV3::NetmanInit(std::string event, void* data) @@ -883,21 +898,39 @@ void OvmsServerV3::NetmanStop(std::string event, void* data) void OvmsServerV3::Ticker1(std::string event, void* data) { + m_connection_available = StdMetrics.ms_m_net_connected->AsBool() && + StdMetrics.ms_m_net_ip->AsBool() && + StdMetrics.ms_m_net_good_sq->AsBool(); + if (!m_connection_available && m_mgconn) + { + Disconnect(); + m_connretry = 10; + } + + if (!m_connection_available) m_connection_counter = 0; + else if (m_connection_counter < 10) + { + m_connection_counter++; + if (m_connretry == 0 && m_connection_counter == 10) + { + if (m_mgconn) Disconnect(); // Disconnect first (timeout) + Connect(); // Kick off the connection + return; + } + } + if (m_accept_command > 0) { m_accept_command--; } if (m_connretry > 0) { - if (MyNetManager.m_connected_any) + m_connretry--; + if (m_connretry == 0 && m_connection_counter == 10) { - m_connretry--; - if (m_connretry == 0) - { - if (m_mgconn) Disconnect(); // Disconnect first (timeout) - Connect(); // Kick off the connection - return; - } + if (m_mgconn) Disconnect(); // Disconnect first (timeout) + Connect(); // Kick off the connection + return; } } diff --git a/vehicle/OVMS.V3/components/ovms_server_v3/src/ovms_server_v3.h b/vehicle/OVMS.V3/components/ovms_server_v3/src/ovms_server_v3.h index fa2763fbb..0bdf26cac 100644 --- a/vehicle/OVMS.V3/components/ovms_server_v3/src/ovms_server_v3.h +++ b/vehicle/OVMS.V3/components/ovms_server_v3/src/ovms_server_v3.h @@ -95,6 +95,7 @@ class OvmsServerV3 : public OvmsServer struct mg_connection *m_mgconn; OvmsMutex m_mgconn_mutex; int m_connretry; + int m_connection_counter; bool m_sendall; int m_accept_command; int m_msgid; @@ -109,6 +110,7 @@ class OvmsServerV3 : public OvmsServer int m_updatetime_charging; int m_updatetime_sendall; + bool m_connection_available; bool m_notify_info_pending; bool m_notify_error_pending; bool m_notify_alert_pending; diff --git a/vehicle/OVMS.V3/components/ovms_webserver/src/web_cfg.cpp b/vehicle/OVMS.V3/components/ovms_webserver/src/web_cfg.cpp index 6d5b65c99..35a2999b6 100644 --- a/vehicle/OVMS.V3/components/ovms_webserver/src/web_cfg.cpp +++ b/vehicle/OVMS.V3/components/ovms_webserver/src/web_cfg.cpp @@ -880,8 +880,9 @@ void OvmsWebServer::HandleCfgVehicle(PageEntry_t& p, PageContext_t& c) */ void OvmsWebServer::HandleCfgModem(PageEntry_t& p, PageContext_t& c) { - std::string apn, apn_user, apn_pass, network_dns, pincode; + std::string apn, apn_user, apn_pass, network_dns, pincode, error; bool enable_gps, enable_gpstime, enable_net, enable_sms, wrongpincode; + float cfg_sq_good, cfg_sq_bad; if (c.method == "POST") { // process form submission: @@ -894,27 +895,49 @@ void OvmsWebServer::HandleCfgModem(PageEntry_t& p, PageContext_t& c) enable_sms = (c.getvar("enable_sms") == "yes"); enable_gps = (c.getvar("enable_gps") == "yes"); enable_gpstime = (c.getvar("enable_gpstime") == "yes"); + cfg_sq_good = atof(c.getvar("cfg_sq_good").c_str()); + cfg_sq_bad = atof(c.getvar("cfg_sq_bad").c_str()); - MyConfig.SetParamValue("modem", "apn", apn); - MyConfig.SetParamValue("modem", "apn.user", apn_user); - MyConfig.SetParamValue("modem", "apn.password", apn_pass); - if ( MyConfig.GetParamValueBool("modem","wrongpincode") && (MyConfig.GetParamValue("modem","pincode") != pincode) ) + if (cfg_sq_bad >= cfg_sq_good) { - ESP_LOGI(TAG,"New SIM card PIN code entered. Cleared wrong_pin_code flag"); - MyConfig.SetParamValueBool("modem", "wrongpincode", false); + error += "
  • 'Bad' signal level must be lower than 'good' level.
  • "; } - MyConfig.SetParamValue("modem", "pincode", pincode); - MyConfig.SetParamValue("network", "dns", network_dns); - MyConfig.SetParamValueBool("modem", "enable.net", enable_net); - MyConfig.SetParamValueBool("modem", "enable.sms", enable_sms); - MyConfig.SetParamValueBool("modem", "enable.gps", enable_gps); - MyConfig.SetParamValueBool("modem", "enable.gpstime", enable_gpstime); + else + { + MyConfig.SetParamValue("modem", "apn", apn); + MyConfig.SetParamValue("modem", "apn.user", apn_user); + MyConfig.SetParamValue("modem", "apn.password", apn_pass); + if ( MyConfig.GetParamValueBool("modem","wrongpincode") && (MyConfig.GetParamValue("modem","pincode") != pincode) ) + { + ESP_LOGI(TAG,"New SIM card PIN code entered. Cleared wrong_pin_code flag"); + MyConfig.SetParamValueBool("modem", "wrongpincode", false); + } + MyConfig.SetParamValue("modem", "pincode", pincode); + MyConfig.SetParamValue("network", "dns", network_dns); + MyConfig.SetParamValueBool("modem", "enable.net", enable_net); + MyConfig.SetParamValueBool("modem", "enable.sms", enable_sms); + MyConfig.SetParamValueBool("modem", "enable.gps", enable_gps); + MyConfig.SetParamValueBool("modem", "enable.gpstime", enable_gpstime); + + MyConfig.SetParamValueFloat("network", "modem.sq.good", cfg_sq_good); + MyConfig.SetParamValueFloat("network", "modem.sq.bad", cfg_sq_bad); + } + if (error == "") + { + c.head(200); + c.alert("success", "

    Modem configured.

    "); + OutputHome(p, c); + c.done(); + return; + } + error = "

    Error!

      " + error + "
    "; + c.head(400); + c.alert("danger", error.c_str()); + } + else + { c.head(200); - c.alert("success", "

    Modem configured.

    "); - OutputHome(p, c); - c.done(); - return; } // read configuration: @@ -928,9 +951,10 @@ void OvmsWebServer::HandleCfgModem(PageEntry_t& p, PageContext_t& c) enable_sms = MyConfig.GetParamValueBool("modem", "enable.sms", true); enable_gps = MyConfig.GetParamValueBool("modem", "enable.gps", false); enable_gpstime = MyConfig.GetParamValueBool("modem", "enable.gpstime", false); + cfg_sq_good = MyConfig.GetParamValueFloat("network", "modem.sq.good", -95); + cfg_sq_bad = MyConfig.GetParamValueFloat("network", "modem.sq.bad", -93); // generate form: - c.head(200); c.panel_start("primary", "Cellular modem configuration"); c.form_start(p.uri); @@ -976,6 +1000,13 @@ void OvmsWebServer::HandleCfgModem(PageEntry_t& p, PageContext_t& c) c.input_checkbox("Use GPS time", "enable_gpstime", enable_gpstime); c.fieldset_end(); + c.fieldset_start("Cellular client options"); + c.input_slider("Good signal level", "cfg_sq_good", 3, "dBm", -1, cfg_sq_good, -93.0, -128.0, 0.0, 0.1, + "

    Threshold for usable wifi signal strength

    "); + c.input_slider("Bad signal level", "cfg_sq_bad", 3, "dBm", -1, cfg_sq_bad, -95.0, -128.0, 0.0, 0.1, + "

    Threshold for unusable wifi signal strength

    "); + c.fieldset_end(); + c.hr(); c.input_button("default", "Save"); c.form_end(); @@ -2044,6 +2075,7 @@ void OvmsWebServer::HandleCfgWebServer(PageEntry_t& p, PageContext_t& c) void OvmsWebServer::HandleCfgWifi(PageEntry_t& p, PageContext_t& c) { bool cfg_bad_reconnect; + bool cfg_reboot_no_ip; float cfg_sq_good, cfg_sq_bad; if (c.method == "POST") { @@ -2056,6 +2088,7 @@ void OvmsWebServer::HandleCfgWifi(PageEntry_t& p, PageContext_t& c) cfg_sq_good = atof(c.getvar("cfg_sq_good").c_str()); cfg_sq_bad = atof(c.getvar("cfg_sq_bad").c_str()); cfg_bad_reconnect = (c.getvar("cfg_bad_reconnect") == "yes"); + cfg_reboot_no_ip = (c.getvar("cfg_reboot_no_ip") == "yes"); if (cfg_sq_bad >= cfg_sq_good) { error += "
  • 'Bad' signal level must be lower than 'good' level.
  • "; @@ -2072,6 +2105,10 @@ void OvmsWebServer::HandleCfgWifi(PageEntry_t& p, PageContext_t& c) MyConfig.DeleteInstance("network", "wifi.bad.reconnect"); else MyConfig.SetParamValueBool("network", "wifi.bad.reconnect", cfg_bad_reconnect); + if (!cfg_reboot_no_ip) + MyConfig.DeleteInstance("network", "reboot.no.ip"); + else + MyConfig.SetParamValueBool("network", "reboot.no.ip", cfg_reboot_no_ip); } if (error == "") { @@ -2095,7 +2132,7 @@ void OvmsWebServer::HandleCfgWifi(PageEntry_t& p, PageContext_t& c) cfg_sq_good = MyConfig.GetParamValueFloat("network", "wifi.sq.good", -87); cfg_sq_bad = MyConfig.GetParamValueFloat("network", "wifi.sq.bad", -89); cfg_bad_reconnect = MyConfig.GetParamValueBool("network", "wifi.bad.reconnect", false); - + cfg_reboot_no_ip = MyConfig.GetParamValueBool("network", "reboot.no.ip", false); c.head(200); } @@ -2121,6 +2158,9 @@ void OvmsWebServer::HandleCfgWifi(PageEntry_t& p, PageContext_t& c) c.input_checkbox("Immediate disconnect/reconnect", "cfg_bad_reconnect", cfg_bad_reconnect, "

    Check to immediately look for better access points when signal level gets bad." " Default is to stay with the current AP as long as possible.

    "); + c.input_checkbox("Reboot when no IP is aquired after 5 minutes with a good connection", "cfg_reboot_no_ip", cfg_reboot_no_ip, + "

    Reboot device when there is good signal but the connection fails to obtain an IP address after 5 minutes." + " Takes into consideration both wifi and cellular connections.

    "); c.fieldset_end(); c.print( diff --git a/vehicle/OVMS.V3/main/metrics_standard.cpp b/vehicle/OVMS.V3/main/metrics_standard.cpp index 724084d02..458d176b8 100644 --- a/vehicle/OVMS.V3/main/metrics_standard.cpp +++ b/vehicle/OVMS.V3/main/metrics_standard.cpp @@ -48,6 +48,9 @@ MetricsStandard::MetricsStandard() ms_m_net_type = new OvmsMetricString(MS_N_TYPE, SM_STALE_MAX); ms_m_net_sq = new OvmsMetricInt(MS_N_SQ, SM_STALE_MAX, dbm); ms_m_net_provider = new OvmsMetricString(MS_N_PROVIDER, SM_STALE_MAX); + ms_m_net_connected = new OvmsMetricBool(MS_N_CONNECTED); + ms_m_net_ip = new OvmsMetricBool(MS_N_IP); + ms_m_net_good_sq = new OvmsMetricBool(MS_N_GOOD_SQ); ms_m_net_wifi_sq = new OvmsMetricFloat(MS_N_WIFI_SQ, SM_STALE_MAX, dbm); ms_m_net_wifi_network = new OvmsMetricString(MS_N_WIFI_NETWORK, SM_STALE_MAX); ms_m_net_mdm_sq = new OvmsMetricFloat(MS_N_MDM_SQ, SM_STALE_MAX, dbm); diff --git a/vehicle/OVMS.V3/main/metrics_standard.h b/vehicle/OVMS.V3/main/metrics_standard.h index 0e47f3b61..4e3a50dfa 100644 --- a/vehicle/OVMS.V3/main/metrics_standard.h +++ b/vehicle/OVMS.V3/main/metrics_standard.h @@ -50,6 +50,9 @@ #define MS_N_TYPE "m.net.type" #define MS_N_SQ "m.net.sq" +#define MS_N_CONNECTED "m.net.connected" +#define MS_N_IP "m.net.ip" +#define MS_N_GOOD_SQ "m.net.good.sq" #define MS_N_PROVIDER "m.net.provider" #define MS_N_MDM_ICCID "m.net.mdm.iccid" #define MS_N_MDM_MODEL "m.net.mdm.model" @@ -300,6 +303,9 @@ class MetricsStandard OvmsMetricString* ms_m_net_mdm_iccid; // ICCID of SIM card in modem OvmsMetricString* ms_m_net_mdm_model; // Model of modem discovered OvmsMetricString* ms_m_net_mdm_mode; // Cellular connection mode and status + OvmsMetricBool* ms_m_net_connected; // True = connected_any is true + OvmsMetricBool* ms_m_net_ip; // True = device has ip available + OvmsMetricBool* ms_m_net_good_sq; // True = sq is above the configured threshold for sq usability #ifdef CONFIG_OVMS_COMP_MAX7317 OvmsMetricBitset<10,0>* ms_m_egpio_input; // EGPIO (MAX7317) input port state (ports 0…9) diff --git a/vehicle/OVMS.V3/main/ovms_netmanager.cpp b/vehicle/OVMS.V3/main/ovms_netmanager.cpp index 2265a8c70..93e5afbbd 100644 --- a/vehicle/OVMS.V3/main/ovms_netmanager.cpp +++ b/vehicle/OVMS.V3/main/ovms_netmanager.cpp @@ -49,6 +49,7 @@ static const char *TAG = "netmanager"; #include "ovms_command.h" #include "ovms_config.h" #include "ovms_module.h" +#include "ovms_boot.h" #ifdef CONFIG_OVMS_DEV_NETMANAGER_PING #include "ping/ping_sock.h" #endif // CONFIG_OVMS_DEV_NETMANAGER_PING @@ -343,6 +344,7 @@ void network_connections(int verbosity, OvmsWriter* writer, OvmsCommand* cmd, in OvmsNetManager::OvmsNetManager() { ESP_LOGI(TAG, "Initialising NETMANAGER (8999)"); + m_not_connected_counter = 0; m_connected_wifi = false; m_connected_modem = false; m_connected_any = false; @@ -399,6 +401,7 @@ OvmsNetManager::OvmsNetManager() MyEvents.RegisterEvent(TAG,"system.wifi.ap.sta.disconnected", std::bind(&OvmsNetManager::WifiApStaDisconnect, this, _1, _2)); #endif // #ifdef CONFIG_OVMS_COMP_WIFI + MyEvents.RegisterEvent(TAG, "ticker.1", std::bind(&OvmsNetManager::Ticker1, this, _1, _2)); MyEvents.RegisterEvent(TAG,"system.modem.gotip", std::bind(&OvmsNetManager::ModemUp, this, _1, _2)); MyEvents.RegisterEvent(TAG,"system.modem.stop", std::bind(&OvmsNetManager::ModemDown, this, _1, _2)); MyEvents.RegisterEvent(TAG,"system.modem.down", std::bind(&OvmsNetManager::ModemDown, this, _1, _2)); @@ -652,6 +655,26 @@ void OvmsNetManager::WifiApStaDisconnect(std::string event, void* data) #endif // #ifdef CONFIG_OVMS_COMP_WIFI +void OvmsNetManager::Ticker1(std::string event, void *data) + { + if (m_cfg_reboot_no_connection) + { + if (m_connected_any && !m_has_ip && StdMetrics.ms_m_net_good_sq->AsBool()) + { + ESP_LOGI(TAG, "Connection available with good signal, but no IP address; rebooting in %i seconds", 300-m_not_connected_counter); + m_not_connected_counter++; + if (m_not_connected_counter > 300) + { + MyBoot.Restart(); + } + } + else + { + m_not_connected_counter = 0; + } + } + } + void OvmsNetManager::ModemUp(std::string event, void* data) { m_connected_modem = true; @@ -723,8 +746,9 @@ void OvmsNetManager::ConfigChanged(std::string event, void* data) if (!param || param->GetName() == "network") { // Network config has been changed, apply: + m_cfg_reboot_no_connection = MyConfig.GetParamValueBool("network", "reboot.no.ip", false); m_cfg_wifi_sq_good = MyConfig.GetParamValueFloat("network", "wifi.sq.good", -87); - m_cfg_wifi_sq_bad = MyConfig.GetParamValueFloat("network", "wifi.sq.bad", -89); + m_cfg_wifi_sq_bad = MyConfig.GetParamValueFloat("network", "wifi.sq.bad", -89); if (m_cfg_wifi_sq_good < m_cfg_wifi_sq_bad) { float x = m_cfg_wifi_sq_good; @@ -854,6 +878,8 @@ void OvmsNetManager::DoSafePrioritiseAndIndicate() // A convenient place to keep track of connectivity in general m_connected_any = m_connected_wifi || m_connected_modem; m_network_any = m_connected_wifi || m_connected_modem || m_wifi_ap; + StdMetrics.ms_m_net_connected->SetValue(m_connected_any); + // Priority order... if (m_connected_wifi) @@ -862,6 +888,7 @@ void OvmsNetManager::DoSafePrioritiseAndIndicate() SetNetType("wifi"); search = "st"; dns = m_dns_wifi; + m_has_ip = MyPeripherals->m_esp32wifi->WifiHasIp(); } else if (m_connected_modem) { @@ -869,7 +896,11 @@ void OvmsNetManager::DoSafePrioritiseAndIndicate() SetNetType("modem"); search = "pp"; dns = m_dns_modem; + m_has_ip = MyPeripherals->m_cellular_modem->ModemIsNetMode() && + MyPeripherals->m_cellular_modem->m_mux->IsMuxUp() && + MyPeripherals->m_cellular_modem->m_ppp->m_connected; } + StdMetrics.ms_m_net_ip->SetValue(m_has_ip); if (search == NULL) { diff --git a/vehicle/OVMS.V3/main/ovms_netmanager.h b/vehicle/OVMS.V3/main/ovms_netmanager.h index e647937ec..da329ceea 100644 --- a/vehicle/OVMS.V3/main/ovms_netmanager.h +++ b/vehicle/OVMS.V3/main/ovms_netmanager.h @@ -116,6 +116,7 @@ class OvmsNetManager void WifiApStaDisconnect(std::string event, void* data); #endif // CONFIG_OVMS_COMP_WIFI + void Ticker1(std::string event, void *data); void ModemUp(std::string event, void* data); void ModemDown(std::string event, void* data); void InterfaceUp(std::string event, void* data); @@ -137,9 +138,11 @@ class OvmsNetManager void SetDNSServer(ip_addr_t* dnsstore); public: + int m_not_connected_counter; bool m_connected_wifi; bool m_connected_modem; bool m_connected_any; + bool m_has_ip; bool m_wifi_sta; bool m_wifi_good; bool m_wifi_ap; @@ -150,6 +153,7 @@ class OvmsNetManager char m_previous_name[2]; protected: + bool m_cfg_reboot_no_connection; float m_cfg_wifi_sq_good; // config network wifi.sq.good [dBm] default -87 float m_cfg_wifi_sq_bad; // config network wifi.sq.bad [dBm] default -89 From d0b625f0cb74229a4a79f507bb102e8229d4d596 Mon Sep 17 00:00:00 2001 From: Jaime Date: Mon, 26 Aug 2024 16:10:16 -0400 Subject: [PATCH 44/45] fix style --- .../ovms_webserver/assets/charts.js.gz | Bin 80477 -> 80477 bytes vehicle/OVMS.V3/main/ovms_events.cpp | 12 ++++++------ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/vehicle/OVMS.V3/components/ovms_webserver/assets/charts.js.gz b/vehicle/OVMS.V3/components/ovms_webserver/assets/charts.js.gz index c7f8bf7e96641532ab14504950f7e70821a21a92..8e4a16f1f607cafcf250c01fb81a7a525c5a1585 100644 GIT binary patch delta 22 bcmccnh2`!S77qDt4h9ft 30) - { + { ESP_LOGE(TAG, "Timer service / ticker timer has died => aborting"); MyBoot.Restart(); + } } - } else - { + { HandleQueueSignalEvent(&msg); if (startsWith(m_current_event, "ticker.") && detect_event_loop_blockage > 0) - { + { detect_event_loop_blockage--; + } } - } esp_task_wdt_reset(); // Reset WATCHDOG timer for this task m_current_event.clear(); break; From f7c0c2f44abe5c4bbd7e365ce67adcfea8dd8cde Mon Sep 17 00:00:00 2001 From: Jaime Date: Mon, 26 Aug 2024 16:51:55 -0400 Subject: [PATCH 45/45] make variable detect_event_loop_blockage local --- vehicle/OVMS.V3/main/ovms_events.cpp | 2 +- vehicle/OVMS.V3/main/ovms_events.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/vehicle/OVMS.V3/main/ovms_events.cpp b/vehicle/OVMS.V3/main/ovms_events.cpp index bd6ce9321..d158a55e6 100644 --- a/vehicle/OVMS.V3/main/ovms_events.cpp +++ b/vehicle/OVMS.V3/main/ovms_events.cpp @@ -246,7 +246,7 @@ OvmsEvents::~OvmsEvents() void OvmsEvents::EventTask() { event_queue_t msg; - detect_event_loop_blockage = 0; + int detect_event_loop_blockage = 0; esp_task_wdt_add(NULL); // WATCHDOG is active for this task while(1) diff --git a/vehicle/OVMS.V3/main/ovms_events.h b/vehicle/OVMS.V3/main/ovms_events.h index ef9f8ae08..f1120a286 100644 --- a/vehicle/OVMS.V3/main/ovms_events.h +++ b/vehicle/OVMS.V3/main/ovms_events.h @@ -129,7 +129,6 @@ class OvmsEvents TimerList m_timers; TimerStatusMap m_timer_active; OvmsMutex m_timers_mutex; - int detect_event_loop_blockage; #if ESP_IDF_VERSION_MAJOR >= 4 esp_event_handler_instance_t event_handler_instance; #endif