diff --git a/.github/workflows/compile-all-batteries.yml b/.github/workflows/compile-all-batteries.yml index 80466e52..09e852ca 100644 --- a/.github/workflows/compile-all-batteries.yml +++ b/.github/workflows/compile-all-batteries.yml @@ -70,6 +70,7 @@ jobs: - RENAULT_ZOE_GEN1_BATTERY - RENAULT_ZOE_GEN2_BATTERY - SANTA_FE_PHEV_BATTERY + - STELLANTIS_ECMP_BATTERY - TESLA_MODEL_3Y_BATTERY - TESLA_MODEL_SX_BATTERY - VOLVO_SPA_BATTERY diff --git a/.github/workflows/compile-all-combinations-part2-batteries-N-to-Z.yml b/.github/workflows/compile-all-combinations-part2-batteries-N-to-Z.yml index 8c77e237..abec324e 100644 --- a/.github/workflows/compile-all-combinations-part2-batteries-N-to-Z.yml +++ b/.github/workflows/compile-all-combinations-part2-batteries-N-to-Z.yml @@ -63,6 +63,7 @@ jobs: - RENAULT_ZOE_GEN1_BATTERY - RENAULT_ZOE_GEN2_BATTERY - SANTA_FE_PHEV_BATTERY + - STELLANTIS_ECMP_BATTERY - TESLA_MODEL_3Y_BATTERY - TESLA_MODEL_SX_BATTERY - VOLVO_SPA_BATTERY diff --git a/README.md b/README.md index 2e897f0e..1c4e676e 100644 --- a/README.md +++ b/README.md @@ -85,7 +85,7 @@ This code uses the following excellent libraries: - [eModbus/eModbus](https://github.com/eModbus/eModbus) MIT-License - [knolleary/pubsubclient](https://github.com/knolleary/pubsubclient) MIT-License - [mackelec/SerialDataLink](https://github.com/mackelec/SerialDataLink) -- [mathieucarbou/AsyncTCP](https://github.com/mathieucarbou/AsyncTCP) LGPL-3.0 license +- [me-no-dev/AsyncTCP](https://github.com/me-no-dev/AsyncTCP) LGPL-3.0 license - [me-no-dev/ESPAsyncWebServer](https://github.com/me-no-dev/ESPAsyncWebServer) - [miwagner/ESP32-Arduino-CAN](https://github.com/miwagner/ESP32-Arduino-CAN/) MIT-License - [pierremolinaro/acan2515](https://github.com/pierremolinaro/acan2515) MIT-License diff --git a/Software/Software.ino b/Software/Software.ino index 60cc30d2..ce84181b 100644 --- a/Software/Software.ino +++ b/Software/Software.ino @@ -1,16 +1,13 @@ /* Do not change any code below this line unless you are sure what you are doing */ /* Only change battery specific settings in "USER_SETTINGS.h" */ - -#include "src/include.h" - #include "HardwareSerial.h" +#include "USER_SECRETS.h" #include "USER_SETTINGS.h" #include "esp_system.h" #include "esp_task_wdt.h" #include "esp_timer.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "src/charger/CHARGERS.h" #include "src/communication/can/comm_can.h" #include "src/communication/contactorcontrol/comm_contactorcontrol.h" #include "src/communication/equipmentstopbutton/comm_equipmentstopbutton.h" @@ -22,6 +19,7 @@ #include "src/devboard/utils/led_handler.h" #include "src/devboard/utils/logging.h" #include "src/devboard/utils/value_mapping.h" +#include "src/include.h" #include "src/lib/YiannisBourkelis-Uptime-Library/src/uptime.h" #include "src/lib/YiannisBourkelis-Uptime-Library/src/uptime_formatter.h" #include "src/lib/bblanchon-ArduinoJson/ArduinoJson.h" @@ -30,7 +28,10 @@ #include "src/lib/eModbus-eModbus/scripts/mbServerFCs.h" #include "src/lib/miwagner-ESP32-Arduino-CAN/CAN_config.h" #include "src/lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h" - +#ifndef AP_PASSWORD +#error \ + "Initial setup not completed, USER_SECRETS.h is missing. Please rename the file USER_SECRETS.TEMPLATE.h to USER_SECRETS.h and fill in the required credentials. This file is ignored by version control to keep sensitive information private." +#endif #ifdef WIFI #include "src/devboard/wifi/wifi.h" #ifdef WEBSERVER @@ -233,9 +234,6 @@ void core_loop(void* task_time_us) { update_machineryprotection(); // Check safeties (Not on serial link reciever board) #endif // SERIAL_LINK_RECEIVER update_values_inverter(); // Update values heading towards inverter - if (DUMMY_EVENT_ENABLED) { - set_event(EVENT_DUMMY_ERROR, (uint8_t)millis()); - } } END_TIME_MEASUREMENT_MAX(time_values, datalayer.system.status.time_values_us); diff --git a/Software/USER_SECRETS.TEMPLATE.h b/Software/USER_SECRETS.TEMPLATE.h index 1d1b0569..1cd013b9 100644 --- a/Software/USER_SECRETS.TEMPLATE.h +++ b/Software/USER_SECRETS.TEMPLATE.h @@ -1,13 +1,20 @@ -#define WIFI_SSID "REPLACE_WITH_YOUR_SSID" // Maximum of 63 characters -#define WIFI_PASSWORD "REPLACE_WITH_YOUR_PASSWORD" // Minimum of 8 characters +/* This file should be renamed to USER_SECRETS.h to be able to use the software! +It contains all the credentials that should never be made public */ + +//Password to the access point generated by the Battery-Emulator #define AP_PASSWORD "123456789" // Minimum of 8 characters; set to blank if you want the access point to be open -#define WEBSERVER_AUTH_REQUIRED \ - false //Set this line to true to activate webserver authentication (this line must not be commented). -#define HTTP_USERNAME "admin" // username to webserver authentication; -#define HTTP_PASSWORD "admin" // password to webserver authentication; +//Name and password of Wifi network you want the emulator to connect to +#define WIFI_SSID "REPLACE_WITH_YOUR_SSID" // Maximum of 63 characters +#define WIFI_PASSWORD "REPLACE_WITH_YOUR_PASSWORD" // Minimum of 8 characters -#define MQTT_SERVER "192.168.xxx.yyy" // mqtt server address -#define MQTT_PORT 1883 // mqtt server port -#define MQTT_USER NULL // mqtt username, leave blank for no authentication -#define MQTT_PASSWORD NULL // mqtt password, leave blank for no authentication +//Set WEBSERVER_AUTH_REQUIRED to true to require a password when accessing the webserver homepage. Improves cybersecurity. +#define WEBSERVER_AUTH_REQUIRED false +#define HTTP_USERNAME "admin" // Username for webserver authentication +#define HTTP_PASSWORD "admin" // Password for webserver authentication + +//MQTT credentials +#define MQTT_SERVER "192.168.xxx.yyy" // MQTT server address +#define MQTT_PORT 1883 // MQTT server port +#define MQTT_USER NULL // MQTT username, leave blank for no authentication +#define MQTT_PASSWORD NULL // MQTT password, leave blank for no authentication diff --git a/Software/USER_SETTINGS.cpp b/Software/USER_SETTINGS.cpp index 7c406893..0ed5c847 100644 --- a/Software/USER_SETTINGS.cpp +++ b/Software/USER_SETTINGS.cpp @@ -20,28 +20,21 @@ volatile CAN_Configuration can_config = { .charger = CAN_NATIVE // (OPTIONAL) Which CAN is your charger connected to? }; -#ifdef WIFI +std::string ssid = WIFI_SSID; // Set in USER_SECRETS.h +std::string password = WIFI_PASSWORD; // Set in USER_SECRETS.h +const char* ssidAP = "Battery Emulator"; // Maximum of 63 characters, also used for device name on web interface +const char* passwordAP = AP_PASSWORD; // Set in USER_SECRETS.h +const uint8_t wifi_channel = 0; // Set to 0 for automatic channel selection -volatile uint8_t AccessPointEnabled = true; //Set to either true/false to enable direct wifi access point -std::string ssid = WIFI_SSID; // Set in USER_SECRETS.h -std::string password = WIFI_PASSWORD; // Set in USER_SECRETS.h -const char* ssidAP = "Battery Emulator"; // Maximum of 63 characters, also used for device name on web interface -const char* passwordAP = AP_PASSWORD; // Set in USER_SECRETS.h -const uint8_t wifi_channel = 0; // Set to 0 for automatic channel selection - -#ifdef WIFICONFIG -// Set your Static IP address -IPAddress local_IP(192, 168, 10, 150); -// Set your Gateway IP address -IPAddress gateway(192, 168, 10, 1); -// Set your Subnet IP address -IPAddress subnet(255, 255, 255, 0); -#endif #ifdef WEBSERVER const char* http_username = HTTP_USERNAME; // Set in USER_SECRETS.h const char* http_password = HTTP_PASSWORD; // Set in USER_SECRETS.h - +// Set your Static IP address. Only used incase WIFICONFIG is set in USER_SETTINGS.h +IPAddress local_IP(192, 168, 10, 150); +IPAddress gateway(192, 168, 10, 1); +IPAddress subnet(255, 255, 255, 0); #endif // WEBSERVER + // MQTT #ifdef MQTT const char* mqtt_user = MQTT_USER; // Set in USER_SECRETS.h @@ -55,7 +48,6 @@ const char* mqtt_device_name = "Battery Emulator"; // Custom device name in Home Assistant. Previously, the name was automatically set to "BatteryEmulator_esp32-XXXXXX" #endif // MQTT_MANUAL_TOPIC_OBJECT_NAME #endif // USE_MQTT -#endif // WIFI #ifdef EQUIPMENT_STOP_BUTTON // Equipment stop button behavior. Use NC button for safety reasons. diff --git a/Software/USER_SETTINGS.h b/Software/USER_SETTINGS.h index a73799c5..2496c2ce 100644 --- a/Software/USER_SETTINGS.h +++ b/Software/USER_SETTINGS.h @@ -31,6 +31,7 @@ //#define RENAULT_ZOE_GEN1_BATTERY //#define RENAULT_ZOE_GEN2_BATTERY //#define SANTA_FE_PHEV_BATTERY +//#define STELLANTIS_ECMP_BATTERY //#define TESLA_MODEL_3Y_BATTERY //#define TESLA_MODEL_SX_BATTERY //#define VOLVO_SPA_BATTERY @@ -77,20 +78,17 @@ //#define CAN_ADDON //Enable this line to activate an isolated secondary CAN Bus using add-on MCP2515 chip (Needed for some inverters / double battery) #define CRYSTAL_FREQUENCY_MHZ 8 //CAN_ADDON option, what is your MCP2515 add-on boards crystal frequency? //#define CANFD_ADDON //Enable this line to activate an isolated secondary CAN-FD bus using add-on MCP2518FD chip / Native CANFD on Stark board -#ifdef CANFD_ADDON // CANFD_ADDON additional options if enabled #define CANFD_ADDON_CRYSTAL_FREQUENCY_MHZ \ - ACAN2517FDSettings:: \ - OSC_40MHz //CANFD_ADDON option, what is your MCP2518 add-on boards crystal frequency? (Default OSC_40MHz) -#endif // CANFD_ADDON + ACAN2517FDSettings::OSC_40MHz //CANFD_ADDON option, what is your MCP2518 add-on boards crystal frequency? //#define USE_CANFD_INTERFACE_AS_CLASSIC_CAN // Enable this line if you intend to use the CANFD as normal CAN //#define SERIAL_LINK_RECEIVER //Enable this line to receive battery data over RS485 pins from another Lilygo (This LilyGo interfaces with inverter) //#define SERIAL_LINK_TRANSMITTER //Enable this line to send battery data over RS485 pins to another Lilygo (This LilyGo interfaces with battery) #define WIFI //#define WIFICONFIG //Enable this line to set a static IP address / gateway /subnet mask for the device. see USER_SETTINGS.cpp for the settings #define WEBSERVER //Enable this line to enable WiFi, and to run the webserver. See USER_SETTINGS.cpp for the Wifi settings. -#define WIFIAP //Disable this line to permanently disable WIFI AP mode (make sure to hardcode ssid and password of you home wifi network). When enabled WIFI AP can still be disabled by a setting in the future. +#define WIFIAP //When enabled, the emulator will broadcast its own access point Wifi. Can be used at the same time as a normal Wifi connection to a router. #define MDNSRESPONDER //Enable this line to enable MDNS, allows battery monitor te be found by .local address. Requires WEBSERVER to be enabled. -#define LOAD_SAVED_SETTINGS_ON_BOOT //Enable this line to read settings stored via the webserver on boot (overrides Wifi/battery settings set below) +#define LOAD_SAVED_SETTINGS_ON_BOOT // Enable this line to read settings stored via the webserver on boot (overrides Wifi credentials set here) //#define FUNCTION_TIME_MEASUREMENT // Enable this to record execution times and present them in the web UI (WARNING, raises CPU load, do not use for production) //#define EQUIPMENT_STOP_BUTTON // Enable this to allow an equipment stop button connected to the Battery-Emulator to disengage the battery @@ -107,9 +105,6 @@ /* Home Assistant options */ #define HA_AUTODISCOVERY // Enable this line to send Home Assistant autodiscovery messages. If not enabled manual configuration of Home Assitant is required -/* Event options*/ -#define DUMMY_EVENT_ENABLED false //Enable this line to have a dummy event that gets logged to test the interface - /* Select charger used (Optional) */ //#define CHEVYVOLT_CHARGER //Enable this line to control a Chevrolet Volt charger connected to battery - for example, when generator charging or using an inverter without a charging function. //#define NISSANLEAF_CHARGER //Enable this line to control a Nissan LEAF PDM connected to battery - for example, when generator charging @@ -138,8 +133,8 @@ // 3000 = 300.0V, Target discharge voltage (Value can be tuned on the fly via webserver). Not used unless BATTERY_USE_VOLTAGE_LIMITS = true #define BATTERY_MAX_DISCHARGE_VOLTAGE 3000 -/* Do not change any code below this line unless you are sure what you are doing */ -/* Only change battery specific settings in "USER_SETTINGS.h" */ +/* Do not change any code below this line */ +/* Only change battery specific settings above and in "USER_SETTINGS.cpp" */ typedef enum { CAN_NATIVE = 0, CANFD_NATIVE = 1, CAN_ADDON_MCP2515 = 2, CANFD_ADDON_MCP2518 = 3 } CAN_Interface; typedef struct { CAN_Interface battery; @@ -169,9 +164,7 @@ extern volatile STOP_BUTTON_BEHAVIOR equipment_stop_behavior; #ifdef WIFICONFIG extern IPAddress local_IP; -// Set your Gateway IP address extern IPAddress gateway; -// Set your Subnet IP address extern IPAddress subnet; #endif diff --git a/Software/src/battery/BATTERIES.h b/Software/src/battery/BATTERIES.h index 08413b00..7be73f22 100644 --- a/Software/src/battery/BATTERIES.h +++ b/Software/src/battery/BATTERIES.h @@ -27,6 +27,10 @@ #include "CHADEMO-SHUNTS.h" #endif +#ifdef STELLANTIS_ECMP_BATTERY +#include "ECMP-BATTERY.h" +#endif + #ifdef IMIEV_CZERO_ION_BATTERY #include "IMIEV-CZERO-ION-BATTERY.h" #endif diff --git a/Software/src/battery/ECMP-BATTERY.cpp b/Software/src/battery/ECMP-BATTERY.cpp new file mode 100644 index 00000000..afcfd98b --- /dev/null +++ b/Software/src/battery/ECMP-BATTERY.cpp @@ -0,0 +1,308 @@ +#include "../include.h" +#ifdef STELLANTIS_ECMP_BATTERY +#include // For std::min and std::max +#include "../datalayer/datalayer.h" +#include "../devboard/utils/events.h" +#include "ECMP-BATTERY.h" + +/* TODO: +This integration is still ongoing. Here is what still needs to be done in order to use this battery type +- Find SOC% +- Find battery voltage +- Find current value +- Find/estimate charge/discharge limits +- Find temperature +- Figure out contactor closing + - Which CAN messages need to be sent towards the battery? +*/ + +/* Do not change code below unless you are sure what you are doing */ +static unsigned long previousMillis1000 = 0; // will store last time a 1s CAN Message was sent + +//Actual content messages +CAN_frame ECMP_XXX = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x301, + .data = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; + +static uint16_t battery_voltage = 37000; +static uint16_t battery_soc = 0; +static uint16_t cellvoltages[108]; + +void update_values_battery() { + + datalayer.battery.status.real_soc = battery_soc * 100; + + datalayer.battery.status.soh_pptt; + + datalayer.battery.status.voltage_dV = (battery_voltage / 10); + + datalayer.battery.status.current_dA; + + datalayer.battery.status.active_power_W = //Power in watts, Negative = charging batt + ((datalayer.battery.status.voltage_dV * datalayer.battery.status.current_dA) / 100); + + datalayer.battery.status.max_charge_power_W; + + datalayer.battery.status.max_discharge_power_W; + + datalayer.battery.status.temperature_min_dC; + + datalayer.battery.status.temperature_max_dC; + + // Initialize min and max, lets find which cells are min and max! + uint16_t min_cell_mv_value = std::numeric_limits::max(); + uint16_t max_cell_mv_value = 0; + // Loop to find the min and max while ignoring zero values + for (uint8_t i = 0; i < datalayer.battery.info.number_of_cells; ++i) { + uint16_t voltage_mV = datalayer.battery.status.cell_voltages_mV[i]; + if (voltage_mV != 0) { // Skip unread values (0) + min_cell_mv_value = std::min(min_cell_mv_value, voltage_mV); + max_cell_mv_value = std::max(max_cell_mv_value, voltage_mV); + } + } + // If all array values are 0, reset min/max to 3700 + if (min_cell_mv_value == std::numeric_limits::max()) { + min_cell_mv_value = 3700; + max_cell_mv_value = 3700; + } + + datalayer.battery.status.cell_min_voltage_mV = min_cell_mv_value; + datalayer.battery.status.cell_max_voltage_mV = max_cell_mv_value; +} + +void receive_can_battery(CAN_frame rx_frame) { + datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE; + switch (rx_frame.ID) { + case 0x125: + break; + case 0x127: + break; + case 0x129: + break; + case 0x31B: + break; + case 0x358: + break; + case 0x359: + break; + case 0x361: + battery_voltage = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]; + break; + case 0x362: + break; + case 0x454: + break; + case 0x494: + break; + case 0x594: + break; + case 0x6D0: + battery_soc = (100 - rx_frame.data.u8[0]); + break; + case 0x6D1: + break; + case 0x6D2: + break; + case 0x6D3: + cellvoltages[0] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1]; + cellvoltages[1] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3]; + cellvoltages[2] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]; + cellvoltages[3] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7]; + break; + case 0x6D4: + cellvoltages[4] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1]; + cellvoltages[5] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3]; + cellvoltages[6] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]; + cellvoltages[7] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7]; + break; + case 0x6E0: + break; + case 0x6E1: + cellvoltages[8] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1]; + cellvoltages[9] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3]; + cellvoltages[10] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]; + cellvoltages[11] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7]; + break; + case 0x6E2: + cellvoltages[12] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1]; + cellvoltages[13] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3]; + cellvoltages[14] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]; + cellvoltages[15] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7]; + break; + case 0x6E3: + break; + case 0x6E4: + break; + case 0x6E5: + break; + case 0x6E6: + break; + case 0x6E7: + cellvoltages[16] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1]; + cellvoltages[17] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3]; + cellvoltages[18] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]; + cellvoltages[19] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7]; + break; + case 0x6E8: + cellvoltages[20] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1]; + cellvoltages[21] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3]; + cellvoltages[22] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]; + cellvoltages[23] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7]; + break; + case 0x6E9: + cellvoltages[24] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1]; + cellvoltages[25] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3]; + cellvoltages[26] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]; + cellvoltages[27] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7]; + break; + case 0x6EB: + cellvoltages[28] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1]; + cellvoltages[29] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3]; + cellvoltages[30] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]; + cellvoltages[31] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7]; + break; + case 0x6EC: + //Not available on e-C4 + break; + case 0x6ED: + cellvoltages[32] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1]; + cellvoltages[33] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3]; + cellvoltages[34] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]; + cellvoltages[35] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7]; + break; + case 0x6EE: + cellvoltages[36] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1]; + cellvoltages[37] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3]; + cellvoltages[38] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]; + cellvoltages[39] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7]; + break; + case 0x6EF: + cellvoltages[40] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1]; + cellvoltages[41] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3]; + cellvoltages[42] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]; + cellvoltages[43] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7]; + break; + case 0x6F0: + cellvoltages[44] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1]; + cellvoltages[45] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3]; + cellvoltages[46] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]; + cellvoltages[47] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7]; + break; + case 0x6F1: + cellvoltages[48] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1]; + cellvoltages[49] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3]; + cellvoltages[50] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]; + cellvoltages[51] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7]; + break; + case 0x6F2: + cellvoltages[52] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1]; + cellvoltages[53] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3]; + cellvoltages[54] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]; + cellvoltages[55] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7]; + break; + case 0x6F3: + cellvoltages[56] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1]; + cellvoltages[57] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3]; + cellvoltages[58] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]; + cellvoltages[59] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7]; + break; + case 0x6F4: + cellvoltages[60] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1]; + cellvoltages[61] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3]; + cellvoltages[62] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]; + cellvoltages[63] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7]; + break; + case 0x6F5: + cellvoltages[64] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1]; + cellvoltages[65] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3]; + cellvoltages[66] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]; + cellvoltages[67] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7]; + break; + case 0x6F6: + cellvoltages[68] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1]; + cellvoltages[69] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3]; + cellvoltages[70] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]; + cellvoltages[71] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7]; + break; + case 0x6F7: + cellvoltages[72] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1]; + cellvoltages[73] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3]; + cellvoltages[74] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]; + cellvoltages[75] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7]; + break; + case 0x6F8: + cellvoltages[76] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1]; + cellvoltages[77] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3]; + cellvoltages[78] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]; + cellvoltages[79] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7]; + break; + case 0x6F9: + cellvoltages[80] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1]; + cellvoltages[81] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3]; + cellvoltages[82] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]; + cellvoltages[83] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7]; + break; + case 0x6FA: + cellvoltages[84] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1]; + cellvoltages[85] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3]; + cellvoltages[86] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]; + cellvoltages[87] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7]; + break; + case 0x6FB: + cellvoltages[88] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1]; + cellvoltages[89] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3]; + cellvoltages[90] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]; + cellvoltages[91] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7]; + break; + case 0x6FC: + cellvoltages[92] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1]; + cellvoltages[93] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3]; + cellvoltages[94] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]; + cellvoltages[95] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7]; + break; + case 0x6FD: + cellvoltages[96] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1]; + cellvoltages[97] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3]; + cellvoltages[98] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]; + cellvoltages[99] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7]; + break; + case 0x6FE: + cellvoltages[100] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1]; + cellvoltages[101] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3]; + cellvoltages[102] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]; + cellvoltages[103] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7]; + break; + case 0x6FF: + cellvoltages[104] = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1]; + cellvoltages[105] = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3]; + cellvoltages[106] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]; + cellvoltages[107] = (rx_frame.data.u8[6] << 8) | rx_frame.data.u8[7]; + memcpy(datalayer.battery.status.cell_voltages_mV, cellvoltages, 108 * sizeof(uint16_t)); + break; + case 0x794: + break; + default: + break; + } +} + +void send_can_battery() { + unsigned long currentMillis = millis(); + // Send 1s CAN Message + if (currentMillis - previousMillis1000 >= INTERVAL_1_S) { + previousMillis1000 = currentMillis; + } +} + +void setup_battery(void) { // Performs one time setup at startup +#ifdef DEBUG_VIA_USB + Serial.println("ECMP battery selected"); +#endif + datalayer.battery.info.number_of_cells = 108; + datalayer.battery.info.max_design_voltage_dV = 4546; // 454.6V, charging over this is not possible + datalayer.battery.info.min_design_voltage_dV = 3210; // 321.0V, under this, discharging further is disabled +} + +#endif diff --git a/Software/src/battery/ECMP-BATTERY.h b/Software/src/battery/ECMP-BATTERY.h new file mode 100644 index 00000000..14955bd6 --- /dev/null +++ b/Software/src/battery/ECMP-BATTERY.h @@ -0,0 +1,12 @@ +#ifndef STELLANTIS_ECMP_BATTERY_H +#define STELLANTIS_ECMP_BATTERY_H +#include +#include "../include.h" + +#define BATTERY_SELECTED +#define MAX_CELL_DEVIATION_MV 250 + +void setup_battery(void); +void transmit_can(CAN_frame* tx_frame, int interface); + +#endif diff --git a/Software/src/battery/TESLA-BATTERY.cpp b/Software/src/battery/TESLA-BATTERY.cpp index cc2cd2ee..5bcff8af 100644 --- a/Software/src/battery/TESLA-BATTERY.cpp +++ b/Software/src/battery/TESLA-BATTERY.cpp @@ -22,7 +22,12 @@ CAN_frame TESLA_221_2 = { .DLC = 8, .ID = 0x221, .data = {0x61, 0x15, 0x01, 0x00, 0x00, 0x00, 0x20, 0xBA}}; //Contactor Frame 221 - hv_up_for_drive + static uint16_t sendContactorClosingMessagesStill = 300; +static uint16_t battery_cell_max_v = 3700; +static uint16_t battery_cell_min_v = 3700; +static uint16_t battery_cell_deviation_mV = 0; //contains the deviation between highest and lowest cell in mV +//0x3d2: 978 BMS_kwhCounter static uint32_t battery_total_discharge = 0; static uint32_t battery_total_charge = 0; static uint16_t battery_volts = 0; // V @@ -50,14 +55,46 @@ static uint16_t battery_regenerative_limit = 0; static uint16_t battery_discharge_limit = 0; static uint16_t battery_max_heat_park = 0; static uint16_t battery_hvac_max_power = 0; +//0x352: 850 BMS_energyStatus +static uint16_t battery_energy_buffer = 0; // kWh +static uint16_t battery_energy_buffer_m1 = 0; // kWh +static uint16_t battery_energy_to_charge_complete = 0; // kWh +static uint16_t battery_energy_to_charge_complete_m1 = 0; // kWh +static uint16_t battery_expected_energy_remaining = 0; // kWh +static uint16_t battery_expected_energy_remaining_m1 = 0; // kWh +static bool battery_full_charge_complete = false; // Changed to bool +static bool battery_fully_charged = false; // Changed to bool +static uint16_t battery_ideal_energy_remaining = 0; // kWh +static uint16_t battery_ideal_energy_remaining_m0 = 0; // kWh +static uint16_t battery_nominal_energy_remaining = 0; // kWh +static uint16_t battery_nominal_energy_remaining_m0 = 0; // kWh +static uint16_t battery_nominal_full_pack_energy = 600; // Kwh +static uint16_t battery_nominal_full_pack_energy_m0 = 600; // Kwh +//0x132 306 HVBattAmpVolt +static uint16_t battery_volts = 0; // V +static int16_t battery_amps = 0; // A +static int16_t battery_raw_amps = 0; // A +static uint16_t battery_charge_time_remaining = 0; // Minutes +//0x252 594 BMS_powerAvailable +static uint16_t BMS_maxRegenPower = 0; //rename from battery_regenerative_limit +static uint16_t BMS_maxDischargePower = 0; // rename from battery_discharge_limit +static uint16_t BMS_maxStationaryHeatPower = 0; //rename from battery_max_heat_park +static uint16_t BMS_hvacPowerBudget = 0; //rename from battery_hvac_max_power +static uint8_t BMS_notEnoughPowerForHeatPump = 0; +static uint8_t BMS_powerLimitState = 0; +static uint8_t BMS_inverterTQF = 0; +//0x2d2: 722 BMSVAlimits static uint16_t battery_max_discharge_current = 0; static uint16_t battery_max_charge_current = 0; static uint16_t battery_bms_max_voltage = 0; static uint16_t battery_bms_min_voltage = 0; +//0x2b4: 692 PCS_dcdcRailStatus static uint16_t battery_dcdcHvBusVolt = 0; // Change name from battery_high_voltage to battery_dcdcHvBusVolt static uint16_t battery_dcdcLvBusVolt = 0; // Change name from battery_low_voltage to battery_dcdcLvBusVolt static uint16_t battery_dcdcLvOutputCurrent = 0; // Change name from battery_output_current to battery_dcdcLvOutputCurrent +//0x292: 658 BMS_socStatus +static uint16_t battery_beginning_of_life = 600; // kWh static uint16_t battery_soc_min = 0; static uint16_t battery_soc_max = 0; static uint16_t battery_soc_ui = 0; //Change name from battery_soc_vi to reflect DBC battery_soc_ui @@ -75,87 +112,354 @@ static uint8_t battery_packContactorSetState = 0; static uint8_t battery_packCtrsClosingAllowed = 0; static uint8_t battery_pyroTestInProgress = 0; static uint8_t battery_battTempPct = 0; +//0x392: BMS_packConfig static uint32_t battery_packMass = 0; static uint32_t battery_platformMaxBusVoltage = 0; static uint32_t battery_packConfigMultiplexer = 0; static uint32_t battery_moduleType = 0; static uint32_t battery_reservedConfig = 0; -//Fault codes -static uint8_t battery_WatchdogReset = 0; //Warns if the processor has experienced a reset due to watchdog reset. -static uint8_t battery_PowerLossReset = 0; //Warns if the processor has experienced a reset due to power loss. -static uint8_t battery_SwAssertion = 0; //An internal software assertion has failed. -static uint8_t battery_CrashEvent = 0; //Warns if the crash signal is detected by HVP -static uint8_t battery_OverDchgCurrentFault = 0; //Warns if the pack discharge is above max discharge current limit -static uint8_t battery_OverChargeCurrentFault = - 0; //Warns if the pack discharge current is above max charge current limit -static uint8_t battery_OverCurrentFault = - 0; //Warns if the pack current (discharge or charge) is above max current limit. -static uint8_t battery_OverTemperatureFault = 0; //A pack module temperature is above maximum temperature limit -static uint8_t battery_OverVoltageFault = 0; //A brick voltage is above maximum voltage limit -static uint8_t battery_UnderVoltageFault = 0; //A brick voltage is below minimum voltage limit -static uint8_t battery_PrimaryBmbMiaFault = - 0; //Warns if the voltage and temperature readings from primary BMB chain are mia -static uint8_t battery_SecondaryBmbMiaFault = - 0; //Warns if the voltage and temperature readings from secondary BMB chain are mia -static uint8_t battery_BmbMismatchFault = - 0; //Warns if the primary and secondary BMB chain readings don't match with each other -static uint8_t battery_BmsHviMiaFault = 0; //Warns if the BMS node is mia on HVS or HVI CAN -static uint8_t battery_CpMiaFault = 0; //Warns if the CP node is mia on HVS CAN -static uint8_t battery_PcsMiaFault = 0; //The PCS node is mia on HVS CAN -static uint8_t battery_BmsFault = 0; //Warns if the BMS ECU has faulted -static uint8_t battery_PcsFault = 0; //Warns if the PCS ECU has faulted -static uint8_t battery_CpFault = 0; //Warns if the CP ECU has faulted -static uint8_t battery_ShuntHwMiaFault = 0; //Warns if the shunt current reading is not available -static uint8_t battery_PyroMiaFault = 0; //Warns if the pyro squib is not connected -static uint8_t battery_hvsMiaFault = 0; //Warns if the pack contactor hw fault -static uint8_t battery_hviMiaFault = 0; //Warns if the FC contactor hw fault -static uint8_t battery_Supply12vFault = 0; //Warns if the low voltage (12V) battery is below minimum voltage threshold -static uint8_t battery_VerSupplyFault = - 0; //Warns if the Energy reserve voltage supply is below minimum voltage threshold -static uint8_t battery_HvilFault = 0; //Warn if a High Voltage Inter Lock fault is detected -static uint8_t battery_BmsHvsMiaFault = 0; //Warns if the BMS node is mia on HVS or HVI CAN -static uint8_t battery_PackVoltMismatchFault = - 0; //Warns if the pack voltage doesn't match approximately with sum of brick voltages -static uint8_t battery_EnsMiaFault = 0; //Warns if the ENS line is not connected to HVC -static uint8_t battery_PackPosCtrArcFault = 0; //Warns if the HVP detectes series arc at pack contactor -static uint8_t battery_packNegCtrArcFault = 0; //Warns if the HVP detectes series arc at FC contactor -static uint8_t battery_ShuntHwAndBmsMiaFault = 0; -static uint8_t battery_fcContHwFault = 0; -static uint8_t battery_robinOverVoltageFault = 0; -static uint8_t battery_packContHwFault = 0; -static uint8_t battery_pyroFuseBlown = 0; -static uint8_t battery_pyroFuseFailedToBlow = 0; -static uint8_t battery_CpilFault = 0; -static uint8_t battery_PackContactorFellOpen = 0; -static uint8_t battery_FcContactorFellOpen = 0; -static uint8_t battery_packCtrCloseBlocked = 0; -static uint8_t battery_fcCtrCloseBlocked = 0; -static uint8_t battery_packContactorForceOpen = 0; -static uint8_t battery_fcContactorForceOpen = 0; -static uint8_t battery_dcLinkOverVoltage = 0; -static uint8_t battery_shuntOverTemperature = 0; -static uint8_t battery_passivePyroDeploy = 0; -static uint8_t battery_logUploadRequest = 0; -static uint8_t battery_packCtrCloseFailed = 0; -static uint8_t battery_fcCtrCloseFailed = 0; -static uint8_t battery_shuntThermistorMia = 0; +//0x332: 818 BattBrickMinMax:BMS_bmbMinMax +static int16_t battery_max_temp = 0; // C* +static int16_t battery_min_temp = 0; // C* +static uint16_t battery_BrickVoltageMax = 0; +static uint16_t battery_BrickVoltageMin = 0; +static uint8_t battery_BrickTempMaxNum = 0; +static uint8_t battery_BrickTempMinNum = 0; +static uint8_t battery_BrickModelTMax = 0; +static uint8_t battery_BrickModelTMin = 0; +static uint8_t battery_BrickVoltageMaxNum = 0; //rename from battery_max_vno +static uint8_t battery_BrickVoltageMinNum = 0; //rename from battery_min_vno +//0x20A: 522 HVP_contactorState +static uint8_t battery_contactor = 0; //State of contactor +static uint8_t battery_hvil_status = 0; +static uint8_t battery_packContNegativeState = 0; +static uint8_t battery_packContPositiveState = 0; +static uint8_t battery_packContactorSetState = 0; +static bool battery_packCtrsClosingAllowed = false; // Change to bool +static bool battery_pyroTestInProgress = false; // Change to bool +static bool battery_packCtrsOpenNowRequested = false; // Change to bool +static bool battery_packCtrsOpenRequested = false; // Change to bool +static uint8_t battery_packCtrsRequestStatus = 0; +static bool battery_packCtrsResetRequestRequired = false; // Change to bool +static bool battery_dcLinkAllowedToEnergize = false; // Change to bool +static bool battery_fcContNegativeAuxOpen = false; // Change to bool +static uint8_t battery_fcContNegativeState = 0; +static bool battery_fcContPositiveAuxOpen = false; // Change to bool +static uint8_t battery_fcContPositiveState = 0; +static uint8_t battery_fcContactorSetState = 0; +static bool battery_fcCtrsClosingAllowed = false; // Change to bool +static bool battery_fcCtrsOpenNowRequested = false; // Change to bool +static bool battery_fcCtrsOpenRequested = false; // Change to bool +static uint8_t battery_fcCtrsRequestStatus = 0; +static bool battery_fcCtrsResetRequestRequired = false; // Change to bool +static bool battery_fcLinkAllowedToEnergize = false; // Change to bool +//0x212: 530 BMS_status +static bool battery_BMS_hvacPowerRequest = false; //Change to bool +static bool battery_BMS_notEnoughPowerForDrive = false; //Change to bool +static bool battery_BMS_notEnoughPowerForSupport = false; //Change to bool +static bool battery_BMS_preconditionAllowed = false; //Change to bool +static bool battery_BMS_updateAllowed = false; //Change to bool +static bool battery_BMS_activeHeatingWorthwhile = false; //Change to bool +static bool battery_BMS_cpMiaOnHvs = false; //Change to bool +static uint8_t battery_BMS_contactorState = 0; +static uint8_t battery_BMS_state = 0; +static uint8_t battery_BMS_hvState = 0; +static uint16_t battery_BMS_isolationResistance = 0; +static bool battery_BMS_chargeRequest = false; //Change to bool +static bool battery_BMS_keepWarmRequest = false; //Change to bool +static uint8_t battery_BMS_uiChargeStatus = 0; +static bool battery_BMS_diLimpRequest = false; //Change to bool +static bool battery_BMS_okToShipByAir = false; //Change to bool +static bool battery_BMS_okToShipByLand = false; //Change to bool +static uint32_t battery_BMS_chgPowerAvailable = 0; +static uint8_t battery_BMS_chargeRetryCount = 0; +static bool battery_BMS_pcsPwmEnabled = false; //Change to bool +static bool battery_BMS_ecuLogUploadRequest = false; //Change to bool +static uint8_t battery_BMS_minPackTemperature = 0; +// 0x224:548 PCS_dcdcStatus +static uint8_t battery_PCS_dcdcPrechargeStatus = 0; +static uint8_t battery_PCS_dcdc12VSupportStatus = 0; +static uint8_t battery_PCS_dcdcHvBusDischargeStatus = 0; +static uint16_t battery_PCS_dcdcMainState = 0; +static uint8_t battery_PCS_dcdcSubState = 0; +static bool battery_PCS_dcdcFaulted = false; //Change to bool +static bool battery_PCS_dcdcOutputIsLimited = false; //Change to bool +static uint32_t battery_PCS_dcdcMaxOutputCurrentAllowed = 0; +static uint8_t battery_PCS_dcdcPrechargeRtyCnt = 0; +static uint8_t battery_PCS_dcdc12VSupportRtyCnt = 0; +static uint8_t battery_PCS_dcdcDischargeRtyCnt = 0; +static uint8_t battery_PCS_dcdcPwmEnableLine = 0; +static uint8_t battery_PCS_dcdcSupportingFixedLvTarget = 0; +static uint8_t battery_PCS_ecuLogUploadRequest = 0; +static uint8_t battery_PCS_dcdcPrechargeRestartCnt = 0; +static uint8_t battery_PCS_dcdcInitialPrechargeSubState = 0; +//0x312: 786 BMS_thermalStatus +static uint16_t BMS_powerDissipation = 0; +static uint16_t BMS_flowRequest = 0; +static uint16_t BMS_inletActiveCoolTargetT = 0; +static uint16_t BMS_inletPassiveTargetT = 0; +static uint16_t BMS_inletActiveHeatTargetT = 0; +static uint16_t BMS_packTMin = 0; +static uint16_t BMS_packTMax = 0; +static bool BMS_pcsNoFlowRequest = false; +static bool BMS_noFlowRequest = false; +//0x2A4; 676 PCS_thermalStatus +static int16_t PCS_chgPhATemp = 0; +static int16_t PCS_chgPhBTemp = 0; +static int16_t PCS_chgPhCTemp = 0; +static int16_t PCS_dcdcTemp = 0; +static int16_t PCS_ambientTemp = 0; +//0x2C4; 708 PCS_logging +static uint16_t PCS_logMessageSelect = 0; +static uint16_t PCS_dcdcMaxLvOutputCurrent = 0; +static uint16_t PCS_dcdcCurrentLimit = 0; +static uint16_t PCS_dcdcLvOutputCurrentTempLimit = 0; +static uint16_t PCS_dcdcUnifiedCommand = 0; +static uint16_t PCS_dcdcCLAControllerOutput = 0; +static int16_t PCS_dcdcTankVoltage = 0; +static uint16_t PCS_dcdcTankVoltageTarget = 0; +static uint16_t PCS_dcdcClaCurrentFreq = 0; +static int16_t PCS_dcdcTCommMeasured = 0; +static uint16_t PCS_dcdcShortTimeUs = 0; +static uint16_t PCS_dcdcHalfPeriodUs = 0; +static uint16_t PCS_dcdcIntervalMaxFrequency = 0; +static uint16_t PCS_dcdcIntervalMaxHvBusVolt = 0; +static uint16_t PCS_dcdcIntervalMaxLvBusVolt = 0; +static uint16_t PCS_dcdcIntervalMaxLvOutputCurr = 0; +static uint16_t PCS_dcdcIntervalMinFrequency = 0; +static uint16_t PCS_dcdcIntervalMinHvBusVolt = 0; +static uint16_t PCS_dcdcIntervalMinLvBusVolt = 0; +static uint16_t PCS_dcdcIntervalMinLvOutputCurr = 0; +static uint32_t PCS_dcdc12vSupportLifetimekWh = 0; +//0x7AA: //1962 HVP_debugMessage: +static uint8_t HVP_debugMessageMultiplexer = 0; +static bool HVP_gpioPassivePyroDepl = false; //Change to bool +static bool HVP_gpioPyroIsoEn = false; //Change to bool +static bool HVP_gpioCpFaultIn = false; //Change to bool +static bool HVP_gpioPackContPowerEn = false; //Change to bool +static bool HVP_gpioHvCablesOk = false; //Change to bool +static bool HVP_gpioHvpSelfEnable = false; //Change to bool +static bool HVP_gpioLed = false; //Change to bool +static bool HVP_gpioCrashSignal = false; //Change to bool +static bool HVP_gpioShuntDataReady = false; //Change to bool +static bool HVP_gpioFcContPosAux = false; //Change to bool +static bool HVP_gpioFcContNegAux = false; //Change to bool +static bool HVP_gpioBmsEout = false; //Change to bool +static bool HVP_gpioCpFaultOut = false; //Change to bool +static bool HVP_gpioPyroPor = false; //Change to bool +static bool HVP_gpioShuntEn = false; //Change to bool +static bool HVP_gpioHvpVerEn = false; //Change to bool +static bool HVP_gpioPackCoontPosFlywheel = false; //Change to bool +static bool HVP_gpioCpLatchEnable = false; //Change to bool +static bool HVP_gpioPcsEnable = false; //Change to bool +static bool HVP_gpioPcsDcdcPwmEnable = false; //Change to bool +static bool HVP_gpioPcsChargePwmEnable = false; //Change to bool +static bool HVP_gpioFcContPowerEnable = false; //Change to bool +static bool HVP_gpioHvilEnable = false; //Change to bool +static bool HVP_gpioSecDrdy = false; //Change to bool +static uint16_t HVP_hvp1v5Ref = 0; +static int16_t HVP_shuntCurrentDebug = 0; +static bool HVP_packCurrentMia = false; //Change to bool +static bool HVP_auxCurrentMia = false; //Change to bool +static bool HVP_currentSenseMia = false; //Change to bool +static bool HVP_shuntRefVoltageMismatch = false; //Change to bool +static bool HVP_shuntThermistorMia = false; //Change to bool +static bool HVP_shuntHwMia = false; //Change to bool +static int16_t HVP_dcLinkVoltage = 0; +static int16_t HVP_packVoltage = 0; +static int16_t HVP_fcLinkVoltage = 0; +static uint16_t HVP_packContVoltage = 0; +static int16_t HVP_packNegativeV = 0; +static int16_t HVP_packPositiveV = 0; +static uint16_t HVP_pyroAnalog = 0; +static int16_t HVP_dcLinkNegativeV = 0; +static int16_t HVP_dcLinkPositiveV = 0; +static int16_t HVP_fcLinkNegativeV = 0; +static uint16_t HVP_fcContCoilCurrent = 0; +static uint16_t HVP_fcContVoltage = 0; +static uint16_t HVP_hvilInVoltage = 0; +static uint16_t HVP_hvilOutVoltage = 0; +static int16_t HVP_fcLinkPositiveV = 0; +static uint16_t HVP_packContCoilCurrent = 0; +static uint16_t HVP_battery12V = 0; +static int16_t HVP_shuntRefVoltageDbg = 0; +static int16_t HVP_shuntAuxCurrentDbg = 0; +static int16_t HVP_shuntBarTempDbg = 0; +static int16_t HVP_shuntAsicTempDbg = 0; +static uint8_t HVP_shuntAuxCurrentStatus = 0; +static uint8_t HVP_shuntBarTempStatus = 0; +static uint8_t HVP_shuntAsicTempStatus = 0; +//0x3aa: HVP_alertMatrix1 Fault codes // Change to bool +static bool battery_WatchdogReset = false; //Warns if the processor has experienced a reset due to watchdog reset. +static bool battery_PowerLossReset = false; //Warns if the processor has experienced a reset due to power loss. +static bool battery_SwAssertion = false; //An internal software assertion has failed. +static bool battery_CrashEvent = false; //Warns if the crash signal is detected by HVP +static bool battery_OverDchgCurrentFault = false; //Warns if the pack discharge is above max discharge current limit +static bool battery_OverChargeCurrentFault = + false; //Warns if the pack discharge current is above max charge current limit +static bool battery_OverCurrentFault = + false; //Warns if the pack current (discharge or charge) is above max current limit. +static bool battery_OverTemperatureFault = false; //A pack module temperature is above maximum temperature limit +static bool battery_OverVoltageFault = false; //A brick voltage is above maximum voltage limit +static bool battery_UnderVoltageFault = false; //A brick voltage is below minimum voltage limit +static bool battery_PrimaryBmbMiaFault = + false; //Warns if the voltage and temperature readings from primary BMB chain are mia +static bool battery_SecondaryBmbMiaFault = + false; //Warns if the voltage and temperature readings from secondary BMB chain are mia +static bool battery_BmbMismatchFault = + false; //Warns if the primary and secondary BMB chain readings don't match with each other +static bool battery_BmsHviMiaFault = false; //Warns if the BMS node is mia on HVS or HVI CAN +static bool battery_CpMiaFault = false; //Warns if the CP node is mia on HVS CAN +static bool battery_PcsMiaFault = false; //The PCS node is mia on HVS CAN +static bool battery_BmsFault = false; //Warns if the BMS ECU has faulted +static bool battery_PcsFault = false; //Warns if the PCS ECU has faulted +static bool battery_CpFault = false; //Warns if the CP ECU has faulted +static bool battery_ShuntHwMiaFault = false; //Warns if the shunt current reading is not available +static bool battery_PyroMiaFault = false; //Warns if the pyro squib is not connected +static bool battery_hvsMiaFault = false; //Warns if the pack contactor hw fault +static bool battery_hviMiaFault = false; //Warns if the FC contactor hw fault +static bool battery_Supply12vFault = false; //Warns if the low voltage (12V) battery is below minimum voltage threshold +static bool battery_VerSupplyFault = + false; //Warns if the Energy reserve voltage supply is below minimum voltage threshold +static bool battery_HvilFault = false; //Warn if a High Voltage Inter Lock fault is detected +static bool battery_BmsHvsMiaFault = false; //Warns if the BMS node is mia on HVS or HVI CAN +static bool battery_PackVoltMismatchFault = + false; //Warns if the pack voltage doesn't match approximately with sum of brick voltages +static bool battery_EnsMiaFault = false; //Warns if the ENS line is not connected to HVC +static bool battery_PackPosCtrArcFault = false; //Warns if the HVP detectes series arc at pack contactor +static bool battery_packNegCtrArcFault = false; //Warns if the HVP detectes series arc at FC contactor +static bool battery_ShuntHwAndBmsMiaFault = false; +static bool battery_fcContHwFault = false; +static bool battery_robinOverVoltageFault = false; +static bool battery_packContHwFault = false; +static bool battery_pyroFuseBlown = false; +static bool battery_pyroFuseFailedToBlow = false; +static bool battery_CpilFault = false; +static bool battery_PackContactorFellOpen = false; +static bool battery_FcContactorFellOpen = false; +static bool battery_packCtrCloseBlocked = false; +static bool battery_fcCtrCloseBlocked = false; +static bool battery_packContactorForceOpen = false; +static bool battery_fcContactorForceOpen = false; +static bool battery_dcLinkOverVoltage = false; +static bool battery_shuntOverTemperature = false; +static bool battery_passivePyroDeploy = false; +static bool battery_logUploadRequest = false; +static bool battery_packCtrCloseFailed = false; +static bool battery_fcCtrCloseFailed = false; +static bool battery_shuntThermistorMia = false; +//0x320: 800 BMS_alertMatrix +static uint8_t battery_BMS_matrixIndex = 0; // Changed to bool +static bool battery_BMS_a061_robinBrickOverVoltage = false; +static bool battery_BMS_a062_SW_BrickV_Imbalance = false; +static bool battery_BMS_a063_SW_ChargePort_Fault = false; +static bool battery_BMS_a064_SW_SOC_Imbalance = false; +static bool battery_BMS_a127_SW_shunt_SNA = false; +static bool battery_BMS_a128_SW_shunt_MIA = false; +static bool battery_BMS_a069_SW_Low_Power = false; +static bool battery_BMS_a130_IO_CAN_Error = false; +static bool battery_BMS_a071_SW_SM_TransCon_Not_Met = false; +static bool battery_BMS_a132_HW_BMB_OTP_Uncorrctbl = false; +static bool battery_BMS_a134_SW_Delayed_Ctr_Off = false; +static bool battery_BMS_a075_SW_Chg_Disable_Failure = false; +static bool battery_BMS_a076_SW_Dch_While_Charging = false; +static bool battery_BMS_a017_SW_Brick_OV = false; +static bool battery_BMS_a018_SW_Brick_UV = false; +static bool battery_BMS_a019_SW_Module_OT = false; +static bool battery_BMS_a021_SW_Dr_Limits_Regulation = false; +static bool battery_BMS_a022_SW_Over_Current = false; +static bool battery_BMS_a023_SW_Stack_OV = false; +static bool battery_BMS_a024_SW_Islanded_Brick = false; +static bool battery_BMS_a025_SW_PwrBalance_Anomaly = false; +static bool battery_BMS_a026_SW_HFCurrent_Anomaly = false; +static bool battery_BMS_a087_SW_Feim_Test_Blocked = false; +static bool battery_BMS_a088_SW_VcFront_MIA_InDrive = false; +static bool battery_BMS_a089_SW_VcFront_MIA = false; +static bool battery_BMS_a090_SW_Gateway_MIA = false; +static bool battery_BMS_a091_SW_ChargePort_MIA = false; +static bool battery_BMS_a092_SW_ChargePort_Mia_On_Hv = false; +static bool battery_BMS_a034_SW_Passive_Isolation = false; +static bool battery_BMS_a035_SW_Isolation = false; +static bool battery_BMS_a036_SW_HvpHvilFault = false; +static bool battery_BMS_a037_SW_Flood_Port_Open = false; +static bool battery_BMS_a158_SW_HVP_HVI_Comms = false; +static bool battery_BMS_a039_SW_DC_Link_Over_Voltage = false; +static bool battery_BMS_a041_SW_Power_On_Reset = false; +static bool battery_BMS_a042_SW_MPU_Error = false; +static bool battery_BMS_a043_SW_Watch_Dog_Reset = false; +static bool battery_BMS_a044_SW_Assertion = false; +static bool battery_BMS_a045_SW_Exception = false; +static bool battery_BMS_a046_SW_Task_Stack_Usage = false; +static bool battery_BMS_a047_SW_Task_Stack_Overflow = false; +static bool battery_BMS_a048_SW_Log_Upload_Request = false; +static bool battery_BMS_a169_SW_FC_Pack_Weld = false; +static bool battery_BMS_a050_SW_Brick_Voltage_MIA = false; +static bool battery_BMS_a051_SW_HVC_Vref_Bad = false; +static bool battery_BMS_a052_SW_PCS_MIA = false; +static bool battery_BMS_a053_SW_ThermalModel_Sanity = false; +static bool battery_BMS_a054_SW_Ver_Supply_Fault = false; +static bool battery_BMS_a176_SW_GracefulPowerOff = false; +static bool battery_BMS_a059_SW_Pack_Voltage_Sensing = false; +static bool battery_BMS_a060_SW_Leakage_Test_Failure = false; +static bool battery_BMS_a077_SW_Charger_Regulation = false; +static bool battery_BMS_a081_SW_Ctr_Close_Blocked = false; +static bool battery_BMS_a082_SW_Ctr_Force_Open = false; +static bool battery_BMS_a083_SW_Ctr_Close_Failure = false; +static bool battery_BMS_a084_SW_Sleep_Wake_Aborted = false; +static bool battery_BMS_a094_SW_Drive_Inverter_MIA = false; +static bool battery_BMS_a099_SW_BMB_Communication = false; +static bool battery_BMS_a105_SW_One_Module_Tsense = false; +static bool battery_BMS_a106_SW_All_Module_Tsense = false; +static bool battery_BMS_a107_SW_Stack_Voltage_MIA = false; +static bool battery_BMS_a121_SW_NVRAM_Config_Error = false; +static bool battery_BMS_a122_SW_BMS_Therm_Irrational = false; +static bool battery_BMS_a123_SW_Internal_Isolation = false; +static bool battery_BMS_a129_SW_VSH_Failure = false; +static bool battery_BMS_a131_Bleed_FET_Failure = false; +static bool battery_BMS_a136_SW_Module_OT_Warning = false; +static bool battery_BMS_a137_SW_Brick_UV_Warning = false; +static bool battery_BMS_a138_SW_Brick_OV_Warning = false; +static bool battery_BMS_a139_SW_DC_Link_V_Irrational = false; +static bool battery_BMS_a141_SW_BMB_Status_Warning = false; +static bool battery_BMS_a144_Hvp_Config_Mismatch = false; +static bool battery_BMS_a145_SW_SOC_Change = false; +static bool battery_BMS_a146_SW_Brick_Overdischarged = false; +static bool battery_BMS_a149_SW_Missing_Config_Block = false; +static bool battery_BMS_a151_SW_external_isolation = false; +static bool battery_BMS_a156_SW_BMB_Vref_bad = false; +static bool battery_BMS_a157_SW_HVP_HVS_Comms = false; +static bool battery_BMS_a159_SW_HVP_ECU_Error = false; +static bool battery_BMS_a161_SW_DI_Open_Request = false; +static bool battery_BMS_a162_SW_No_Power_For_Support = false; +static bool battery_BMS_a163_SW_Contactor_Mismatch = false; +static bool battery_BMS_a164_SW_Uncontrolled_Regen = false; +static bool battery_BMS_a165_SW_Pack_Partial_Weld = false; +static bool battery_BMS_a166_SW_Pack_Full_Weld = false; +static bool battery_BMS_a167_SW_FC_Partial_Weld = false; +static bool battery_BMS_a168_SW_FC_Full_Weld = false; +static bool battery_BMS_a170_SW_Limp_Mode = false; +static bool battery_BMS_a171_SW_Stack_Voltage_Sense = false; +static bool battery_BMS_a174_SW_Charge_Failure = false; +static bool battery_BMS_a179_SW_Hvp_12V_Fault = false; +static bool battery_BMS_a180_SW_ECU_reset_blocked = false; -#ifdef DOUBLE_BATTERY +#ifdef DOUBLE_BATTERY //need to update for battery2 + +static uint16_t battery2_cell_max_v = 3700; +static uint16_t battery2_cell_min_v = 3700; +static uint16_t battery2_cell_deviation_mV = 0; //contains the deviation between highest and lowest cell in mV +//0x3d2: 978 BMS_kwhCounter static uint32_t battery2_total_discharge = 0; static uint32_t battery2_total_charge = 0; -static uint16_t battery2_volts = 0; // V -static int16_t battery2_amps = 0; // A -static uint16_t battery2_raw_amps = 0; // A -static int16_t battery2_max_temp = 0; // C* -static int16_t battery2_min_temp = 0; // C* +//0x352: 850 BMS_energyStatus static uint16_t battery2_energy_buffer = 0; static uint16_t battery2_energy_buffer_m1 = 0; // kWh static uint16_t battery2_energy_to_charge_complete = 0; static uint16_t battery2_energy_to_charge_complete_m1 = 0; // kWh static uint16_t battery2_expected_energy_remaining = 0; static uint16_t battery2_expected_energy_remaining_m1 = 0; // kWh -static uint8_t battery2_full_charge_complete = 0; -static uint8_t battery2_fully_charged = 0; +static bool battery2_full_charge_complete = false; +static bool battery2_fully_charged = false; static uint16_t battery2_ideal_energy_remaining = 0; static uint16_t battery2_ideal_energy_remaining_m0 = 0; // kWh static uint16_t battery2_nominal_energy_remaining = 0; @@ -163,18 +467,32 @@ static uint16_t battery2_nominal_energy_remaining_m0 = 0; // kWh static uint16_t battery2_nominal_full_pack_energy = 0; static uint16_t battery2_nominal_full_pack_energy_m0 = 0; // Kwh static uint16_t battery2_beginning_of_life = 0; +static uint16_t battery2_nominal_full_pack_energy = 600; +static uint16_t battery2_nominal_full_pack_energy_m0 = 600; // Kwh +//0x132 306 HVBattAmpVolt +static uint16_t battery2_volts = 0; // V +static int16_t battery2_amps = 0; // A +static int16_t battery2_raw_amps = 0; // A static uint16_t battery2_charge_time_remaining = 0; // Minutes -static uint16_t battery2_regenerative_limit = 0; -static uint16_t battery2_discharge_limit = 0; -static uint16_t battery2_max_heat_park = 0; -static uint16_t battery2_hvac_max_power = 0; +//0x252 594 BMS_powerAvailable +static uint16_t BMS2_maxRegenPower = 0; //rename from battery_regenerative_limit +static uint16_t BMS2_maxDischargePower = 0; // rename from battery_discharge_limit +static uint16_t BMS2_maxStationaryHeatPower = 0; //rename from battery_max_heat_park +static uint16_t BMS2_hvacPowerBudget = 0; //rename from battery_hvac_max_power +static uint8_t BMS2_notEnoughPowerForHeatPump = 0; +static uint8_t BMS2_powerLimitState = 0; +static uint8_t BMS2_inverterTQF = 0; +//0x2d2: 722 BMSVAlimits static uint16_t battery2_max_discharge_current = 0; static uint16_t battery2_max_charge_current = 0; static uint16_t battery2_bms_max_voltage = 0; static uint16_t battery2_bms_min_voltage = 0; +//0x2b4: 692 PCS_dcdcRailStatus static uint16_t battery2_dcdcHvBusVolt = 0; //update name static uint16_t battery2_dcdcLvBusVolt = 0; //update name static uint16_t battery2_dcdcLvOutputCurrent = 0; //update name +//0x292: 658 BMS_socStatus +static uint16_t battery2_beginning_of_life = 600; static uint16_t battery2_soc_min = 0; static uint16_t battery2_soc_max = 0; static uint16_t battery2_soc_ui = 0; @@ -192,70 +510,338 @@ static uint8_t battery2_packContactorSetState = 0; static uint8_t battery2_packCtrsClosingAllowed = 0; static uint8_t battery2_pyroTestInProgress = 0; static uint8_t battery2_battTempPct = 0; +//0x392: BMS_packConfig static uint32_t battery2_packMass = 0; static uint32_t battery2_platformMaxBusVoltage = 0; static uint32_t battery2_packConfigMultiplexer = 0; static uint32_t battery2_moduleType = 0; static uint32_t battery2_reservedConfig = 0; -//Fault codes -static uint8_t battery2_WatchdogReset = 0; //Warns if the processor has experienced a reset due to watchdog reset. -static uint8_t battery2_PowerLossReset = 0; //Warns if the processor has experienced a reset due to power loss. -static uint8_t battery2_SwAssertion = 0; //An internal software assertion has failed. -static uint8_t battery2_CrashEvent = 0; //Warns if the crash signal is detected by HVP -static uint8_t battery2_OverDchgCurrentFault = 0; //Warns if the pack discharge is above max discharge current limit -static uint8_t battery2_OverChargeCurrentFault = - 0; //Warns if the pack discharge current is above max charge current limit -static uint8_t battery2_OverCurrentFault = - 0; //Warns if the pack current (discharge or charge) is above max current limit. -static uint8_t battery2_OverTemperatureFault = 0; //A pack module temperature is above maximum temperature limit -static uint8_t battery2_OverVoltageFault = 0; //A brick voltage is above maximum voltage limit -static uint8_t battery2_UnderVoltageFault = 0; //A brick voltage is below minimum voltage limit -static uint8_t battery2_PrimaryBmbMiaFault = - 0; //Warns if the voltage and temperature readings from primary BMB chain are mia -static uint8_t battery2_SecondaryBmbMiaFault = - 0; //Warns if the voltage and temperature readings from secondary BMB chain are mia -static uint8_t battery2_BmbMismatchFault = - 0; //Warns if the primary and secondary BMB chain readings don't match with each other -static uint8_t battery2_BmsHviMiaFault = 0; //Warns if the BMS node is mia on HVS or HVI CAN -static uint8_t battery2_CpMiaFault = 0; //Warns if the CP node is mia on HVS CAN -static uint8_t battery2_PcsMiaFault = 0; //The PCS node is mia on HVS CAN -static uint8_t battery2_BmsFault = 0; //Warns if the BMS ECU has faulted -static uint8_t battery2_PcsFault = 0; //Warns if the PCS ECU has faulted -static uint8_t battery2_CpFault = 0; //Warns if the CP ECU has faulted -static uint8_t battery2_ShuntHwMiaFault = 0; //Warns if the shunt current reading is not available -static uint8_t battery2_PyroMiaFault = 0; //Warns if the pyro squib is not connected -static uint8_t battery2_hvsMiaFault = 0; //Warns if the pack contactor hw fault -static uint8_t battery2_hviMiaFault = 0; //Warns if the FC contactor hw fault -static uint8_t battery2_Supply12vFault = 0; //Warns if the low voltage (12V) battery is below minimum voltage threshold -static uint8_t battery2_VerSupplyFault = - 0; //Warns if the Energy reserve voltage supply is below minimum voltage threshold -static uint8_t battery2_HvilFault = 0; //Warn if a High Voltage Inter Lock fault is detected -static uint8_t battery2_BmsHvsMiaFault = 0; //Warns if the BMS node is mia on HVS or HVI CAN -static uint8_t battery2_PackVoltMismatchFault = - 0; //Warns if the pack voltage doesn't match approximately with sum of brick voltages -static uint8_t battery2_EnsMiaFault = 0; //Warns if the ENS line is not connected to HVC -static uint8_t battery2_PackPosCtrArcFault = 0; //Warns if the HVP detectes series arc at pack contactor -static uint8_t battery2_packNegCtrArcFault = 0; //Warns if the HVP detectes series arc at FC contactor -static uint8_t battery2_ShuntHwAndBmsMiaFault = 0; -static uint8_t battery2_fcContHwFault = 0; -static uint8_t battery2_robinOverVoltageFault = 0; -static uint8_t battery2_packContHwFault = 0; -static uint8_t battery2_pyroFuseBlown = 0; -static uint8_t battery2_pyroFuseFailedToBlow = 0; -static uint8_t battery2_CpilFault = 0; -static uint8_t battery2_PackContactorFellOpen = 0; -static uint8_t battery2_FcContactorFellOpen = 0; -static uint8_t battery2_packCtrCloseBlocked = 0; -static uint8_t battery2_fcCtrCloseBlocked = 0; -static uint8_t battery2_packContactorForceOpen = 0; -static uint8_t battery2_fcContactorForceOpen = 0; -static uint8_t battery2_dcLinkOverVoltage = 0; -static uint8_t battery2_shuntOverTemperature = 0; -static uint8_t battery2_passivePyroDeploy = 0; -static uint8_t battery2_logUploadRequest = 0; -static uint8_t battery2_packCtrCloseFailed = 0; -static uint8_t battery2_fcCtrCloseFailed = 0; -static uint8_t battery2_shuntThermistorMia = 0; +//0x332: 818 BattBrickMinMax:BMS_bmbMinMax +static int16_t battery2_max_temp = 0; // C* +static int16_t battery2_min_temp = 0; // C* +static uint16_t battery2_BrickVoltageMax = 0; +static uint16_t battery2_BrickVoltageMin = 0; +static uint8_t battery2_BrickTempMaxNum = 0; +static uint8_t battery2_BrickTempMinNum = 0; +static uint8_t battery2_BrickModelTMax = 0; +static uint8_t battery2_BrickModelTMin = 0; +static uint8_t battery2_BrickVoltageMaxNum = 0; //rename from battery_max_vno +static uint8_t battery2_BrickVoltageMinNum = 0; //rename from battery_min_vno +//0x20A: 522 HVP_contactorState +static uint8_t battery2_contactor = 0; //State of contactor +static uint8_t battery2_hvil_status = 0; +static uint8_t battery2_packContNegativeState = 0; +static uint8_t battery2_packContPositiveState = 0; +static uint8_t battery2_packContactorSetState = 0; +static bool battery2_packCtrsClosingAllowed = false; +static bool battery2_pyroTestInProgress = false; +static bool battery2_packCtrsOpenNowRequested = false; +static bool battery2_packCtrsOpenRequested = false; +static uint8_t battery2_packCtrsRequestStatus = 0; +static bool battery2_packCtrsResetRequestRequired = false; +static bool battery2_dcLinkAllowedToEnergize = false; +static bool battery2_fcContNegativeAuxOpen = false; +static uint8_t battery2_fcContNegativeState = 0; +static bool battery2_fcContPositiveAuxOpen = false; +static uint8_t battery2_fcContPositiveState = 0; +static uint8_t battery2_fcContactorSetState = 0; +static bool battery2_fcCtrsClosingAllowed = false; +static bool battery2_fcCtrsOpenNowRequested = false; +static bool battery2_fcCtrsOpenRequested = false; +static uint8_t battery2_fcCtrsRequestStatus = 0; +static bool battery2_fcCtrsResetRequestRequired = false; +static bool battery2_fcLinkAllowedToEnergize = false; +//0x212: 530 BMS_status +static bool battery2_BMS_hvacPowerRequest = false; +static bool battery2_BMS_notEnoughPowerForDrive = false; +static bool battery2_BMS_notEnoughPowerForSupport = false; +static bool battery2_BMS_preconditionAllowed = false; +static bool battery2_BMS_updateAllowed = false; +static bool battery2_BMS_activeHeatingWorthwhile = false; +static bool battery2_BMS_cpMiaOnHvs = false; +static uint8_t battery2_BMS_contactorState = 0; +static uint8_t battery2_BMS_state = 0; +static uint8_t battery2_BMS_hvState = 0; +static uint16_t battery2_BMS_isolationResistance = 0; +static bool battery2_BMS_chargeRequest = false; +static bool battery2_BMS_keepWarmRequest = false; +static uint8_t battery2_BMS_uiChargeStatus = 0; +static bool battery2_BMS_diLimpRequest = false; +static bool battery2_BMS_okToShipByAir = false; +static bool battery2_BMS_okToShipByLand = false; +static uint32_t battery2_BMS_chgPowerAvailable = 0; +static uint8_t battery2_BMS_chargeRetryCount = 0; +static bool battery2_BMS_pcsPwmEnabled = false; +static bool battery2_BMS_ecuLogUploadRequest = false; +static uint8_t battery2_BMS_minPackTemperature = 0; +// 0x224:548 PCS_dcdcStatus +static uint8_t battery2_PCS_dcdcPrechargeStatus = 0; +static uint8_t battery2_PCS_dcdc12VSupportStatus = 0; +static uint8_t battery2_PCS_dcdcHvBusDischargeStatus = 0; +static uint16_t battery2_PCS_dcdcMainState = 0; +static uint8_t battery2_PCS_dcdcSubState = 0; +static bool battery2_PCS_dcdcFaulted = false; +static bool battery2_PCS_dcdcOutputIsLimited = false; +static uint32_t battery2_PCS_dcdcMaxOutputCurrentAllowed = 0; +static uint8_t battery2_PCS_dcdcPrechargeRtyCnt = 0; +static uint8_t battery2_PCS_dcdc12VSupportRtyCnt = 0; +static uint8_t battery2_PCS_dcdcDischargeRtyCnt = 0; +static uint8_t battery2_PCS_dcdcPwmEnableLine = 0; +static uint8_t battery2_PCS_dcdcSupportingFixedLvTarget = 0; +static uint8_t battery2_PCS_ecuLogUploadRequest = 0; +static uint8_t battery2_PCS_dcdcPrechargeRestartCnt = 0; +static uint8_t battery2_PCS_dcdcInitialPrechargeSubState = 0; +//0x312: 786 BMS_thermalStatus +static uint16_t BMS2_powerDissipation = 0; +static uint16_t BMS2_flowRequest = 0; +static uint16_t BMS2_inletActiveCoolTargetT = 0; +static uint16_t BMS2_inletPassiveTargetT = 0; +static uint16_t BMS2_inletActiveHeatTargetT = 0; +static uint16_t BMS2_packTMin = 0; +static uint16_t BMS2_packTMax = 0; +static bool BMS2_pcsNoFlowRequest = false; +static bool BMS2_noFlowRequest = false; +//0x2A4; 676 PCS_thermalStatus +static int16_t PCS2_chgPhATemp = 0; +static int16_t PCS2_chgPhBTemp = 0; +static int16_t PCS2_chgPhCTemp = 0; +static int16_t PCS2_dcdcTemp = 0; +static int16_t PCS2_ambientTemp = 0; +//0x2C4; 708 PCS_logging +static uint16_t PCS2_logMessageSelect = 0; +static uint16_t PCS2_dcdcMaxLvOutputCurrent = 0; +static uint16_t PCS2_dcdcCurrentLimit = 0; +static uint16_t PCS2_dcdcLvOutputCurrentTempLimit = 0; +static uint16_t PCS2_dcdcUnifiedCommand = 0; +static uint16_t PCS2_dcdcCLAControllerOutput = 0; +static int16_t PCS2_dcdcTankVoltage = 0; +static uint16_t PCS2_dcdcTankVoltageTarget = 0; +static uint16_t PCS2_dcdcClaCurrentFreq = 0; +static int16_t PCS2_dcdcTCommMeasured = 0; +static uint16_t PCS2_dcdcShortTimeUs = 0; +static uint16_t PCS2_dcdcHalfPeriodUs = 0; +static uint16_t PCS2_dcdcIntervalMaxFrequency = 0; +static uint16_t PCS2_dcdcIntervalMaxHvBusVolt = 0; +static uint16_t PCS2_dcdcIntervalMaxLvBusVolt = 0; +static uint16_t PCS2_dcdcIntervalMaxLvOutputCurr = 0; +static uint16_t PCS2_dcdcIntervalMinFrequency = 0; +static uint16_t PCS2_dcdcIntervalMinHvBusVolt = 0; +static uint16_t PCS2_dcdcIntervalMinLvBusVolt = 0; +static uint16_t PCS2_dcdcIntervalMinLvOutputCurr = 0; +static uint32_t PCS2_dcdc12vSupportLifetimekWh = 0; +//0x7AA: //1962 HVP_debugMessage: +static uint8_t HVP2_debugMessageMultiplexer = 0; +static bool HVP2_gpioPassivePyroDepl = false; +static bool HVP2_gpioPyroIsoEn = false; +static bool HVP2_gpioCpFaultIn = false; +static bool HVP2_gpioPackContPowerEn = false; +static bool HVP2_gpioHvCablesOk = false; +static bool HVP2_gpioHVPSelfEnable = false; +static bool HVP2_gpioLed = false; +static bool HVP2_gpioCrashSignal = false; +static bool HVP2_gpioShuntDataReady = false; +static bool HVP2_gpioFcContPosAux = false; +static bool HVP2_gpioFcContNegAux = false; +static bool HVP2_gpioBmsEout = false; +static bool HVP2_gpioCpFaultOut = false; +static bool HVP2_gpioPyroPor = false; +static bool HVP2_gpioShuntEn = false; +static bool HVP2_gpioHVPVerEn = false; +static bool HVP2_gpioPackCoontPosFlywheel = false; +static bool HVP2_gpioCpLatchEnable = false; +static bool HVP2_gpioPcsEnable = false; +static bool HVP2_gpioPcsDcdcPwmEnable = false; +static bool HVP2_gpioPcsChargePwmEnable = false; +static bool HVP2_gpioFcContPowerEnable = false; +static bool HVP2_gpioHvilEnable = false; +static bool HVP2_gpioSecDrdy = false; +static uint16_t HVP2_hvp1v5Ref = 0; +static int16_t HVP2_shuntCurrentDebug = 0; +static bool HVP2_packCurrentMia = false; +static bool HVP2_auxCurrentMia = false; +static bool HVP2_currentSenseMia = false; +static bool HVP2_shuntRefVoltageMismatch = false; +static bool HVP2_shuntThermistorMia = false; +static bool HVP2_shuntHwMia = false; +static int16_t HVP2_dcLinkVoltage = 0; +static int16_t HVP2_packVoltage = 0; +static int16_t HVP2_fcLinkVoltage = 0; +static uint16_t HVP2_packContVoltage = 0; +static int16_t HVP2_packNegativeV = 0; +static int16_t HVP2_packPositiveV = 0; +static uint16_t HVP2_pyroAnalog = 0; +static int16_t HVP2_dcLinkNegativeV = 0; +static int16_t HVP2_dcLinkPositiveV = 0; +static int16_t HVP2_fcLinkNegativeV = 0; +static uint16_t HVP2_fcContCoilCurrent = 0; +static uint16_t HVP2_fcContVoltage = 0; +static uint16_t HVP2_hvilInVoltage = 0; +static uint16_t HVP2_hvilOutVoltage = 0; +static int16_t HVP2_fcLinkPositiveV = 0; +static uint16_t HVP2_packContCoilCurrent = 0; +static uint16_t HVP2_battery12V = 0; +static int16_t HVP2_shuntRefVoltageDbg = 0; +static int16_t HVP2_shuntAuxCurrentDbg = 0; +static int16_t HVP2_shuntBarTempDbg = 0; +static int16_t HVP2_shuntAsicTempDbg = 0; +static uint8_t HVP2_shuntAuxCurrentStatus = 0; +static uint8_t HVP2_shuntBarTempStatus = 0; +static uint8_t HVP2_shuntAsicTempStatus = 0; +//0x3aa: HVP_alertMatrix1 Fault codes +static bool battery2_WatchdogReset = false; //Warns if the processor has experienced a reset due to watchdog reset. +static bool battery2_PowerLossReset = false; //Warns if the processor has experienced a reset due to power loss. +static bool battery2_SwAssertion = false; //An internal software assertion has failed. +static bool battery2_CrashEvent = false; //Warns if the crash signal is detected by HVP +static bool battery2_OverDchgCurrentFault = false; //Warns if the pack discharge is above max discharge current limit +static bool battery2_OverChargeCurrentFault = + false; //Warns if the pack discharge current is above max charge current limit +static bool battery2_OverCurrentFault = + false; //Warns if the pack current (discharge or charge) is above max current limit. +static bool battery2_OverTemperatureFault = false; //A pack module temperature is above maximum temperature limit +static bool battery2_OverVoltageFault = false; //A brick voltage is above maximum voltage limit +static bool battery2_UnderVoltageFault = false; //A brick voltage is below minimum voltage limit +static bool battery2_PrimaryBmbMiaFault = + false; //Warns if the voltage and temperature readings from primary BMB chain are mia +static bool battery2_SecondaryBmbMiaFault = + false; //Warns if the voltage and temperature readings from secondary BMB chain are mia +static bool battery2_BmbMismatchFault = + false; //Warns if the primary and secondary BMB chain readings don't match with each other +static bool battery2_BmsHviMiaFault = false; //Warns if the BMS node is mia on HVS or HVI CAN +static bool battery2_CpMiaFault = false; //Warns if the CP node is mia on HVS CAN +static bool battery2_PcsMiaFault = false; //The PCS node is mia on HVS CAN +static bool battery2_BmsFault = false; //Warns if the BMS ECU has faulted +static bool battery2_PcsFault = false; //Warns if the PCS ECU has faulted +static bool battery2_CpFault = false; //Warns if the CP ECU has faulted +static bool battery2_ShuntHwMiaFault = false; //Warns if the shunt current reading is not available +static bool battery2_PyroMiaFault = false; //Warns if the pyro squib is not connected +static bool battery2_hvsMiaFault = false; //Warns if the pack contactor hw fault +static bool battery2_hviMiaFault = false; //Warns if the FC contactor hw fault +static bool battery2_Supply12vFault = + false; //Warns if the low voltage (12V) battery is below minimum voltage threshold +static bool battery2_VerSupplyFault = + false; //Warns if the Energy reserve voltage supply is below minimum voltage threshold +static bool battery2_HvilFault = false; //Warn if a High Voltage Inter Lock fault is detected +static bool battery2_BmsHvsMiaFault = false; //Warns if the BMS node is mia on HVS or HVI CAN +static bool battery2_PackVoltMismatchFault = + false; //Warns if the pack voltage doesn't match approximately with sum of brick voltages +static bool battery2_EnsMiaFault = false; //Warns if the ENS line is not connected to HVC +static bool battery2_PackPosCtrArcFault = false; //Warns if the HVP detectes series arc at pack contactor +static bool battery2_packNegCtrArcFault = false; //Warns if the HVP detectes series arc at FC contactor +static bool battery2_ShuntHwAndBmsMiaFault = false; +static bool battery2_fcContHwFault = false; +static bool battery2_robinOverVoltageFault = false; +static bool battery2_packContHwFault = false; +static bool battery2_pyroFuseBlown = false; +static bool battery2_pyroFuseFailedToBlow = false; +static bool battery2_CpilFault = false; +static bool battery2_PackContactorFellOpen = false; +static bool battery2_FcContactorFellOpen = false; +static bool battery2_packCtrCloseBlocked = false; +static bool battery2_fcCtrCloseBlocked = false; +static bool battery2_packContactorForceOpen = false; +static bool battery2_fcContactorForceOpen = false; +static bool battery2_dcLinkOverVoltage = false; +static bool battery2_shuntOverTemperature = false; +static bool battery2_passivePyroDeploy = false; +static bool battery2_logUploadRequest = false; +static bool battery2_packCtrCloseFailed = false; +static bool battery2_fcCtrCloseFailed = false; +static bool battery2_shuntThermistorMia = false; +//0x320: 800 BMS_alertMatrix +static uint8_t battery2_BMS_matrixIndex = 4; +static bool battery2_BMS_a061_robinBrickOverVoltage = false; +static bool battery2_BMS_a062_SW_BrickV_Imbalance = false; +static bool battery2_BMS_a063_SW_ChargePort_Fault = false; +static bool battery2_BMS_a064_SW_SOC_Imbalance = false; +static bool battery2_BMS_a127_SW_shunt_SNA = false; +static bool battery2_BMS_a128_SW_shunt_MIA = false; +static bool battery2_BMS_a069_SW_Low_Power = false; +static bool battery2_BMS_a130_IO_CAN_Error = false; +static bool battery2_BMS_a071_SW_SM_TransCon_Not_Met = false; +static bool battery2_BMS_a132_HW_BMB_OTP_Uncorrctbl = false; +static bool battery2_BMS_a134_SW_Delayed_Ctr_Off = false; +static bool battery2_BMS_a075_SW_Chg_Disable_Failure = false; +static bool battery2_BMS_a076_SW_Dch_While_Charging = false; +static bool battery2_BMS_a017_SW_Brick_OV = false; +static bool battery2_BMS_a018_SW_Brick_UV = false; +static bool battery2_BMS_a019_SW_Module_OT = false; +static bool battery2_BMS_a021_SW_Dr_Limits_Regulation = false; +static bool battery2_BMS_a022_SW_Over_Current = false; +static bool battery2_BMS_a023_SW_Stack_OV = false; +static bool battery2_BMS_a024_SW_Islanded_Brick = false; +static bool battery2_BMS_a025_SW_PwrBalance_Anomaly = false; +static bool battery2_BMS_a026_SW_HFCurrent_Anomaly = false; +static bool battery2_BMS_a087_SW_Feim_Test_Blocked = false; +static bool battery2_BMS_a088_SW_VcFront_MIA_InDrive = false; +static bool battery2_BMS_a089_SW_VcFront_MIA = false; +static bool battery2_BMS_a090_SW_Gateway_MIA = false; +static bool battery2_BMS_a091_SW_ChargePort_MIA = false; +static bool battery2_BMS_a092_SW_ChargePort_Mia_On_Hv = false; +static bool battery2_BMS_a034_SW_Passive_Isolation = false; +static bool battery2_BMS_a035_SW_Isolation = false; +static bool battery2_BMS_a036_SW_HvpHvilFault = false; +static bool battery2_BMS_a037_SW_Flood_Port_Open = false; +static bool battery2_BMS_a158_SW_HVP_HVI_Comms = false; +static bool battery2_BMS_a039_SW_DC_Link_Over_Voltage = 1; +static bool battery2_BMS_a041_SW_Power_On_Reset = false; +static bool battery2_BMS_a042_SW_MPU_Error = false; +static bool battery2_BMS_a043_SW_Watch_Dog_Reset = false; +static bool battery2_BMS_a044_SW_Assertion = false; +static bool battery2_BMS_a045_SW_Exception = false; +static bool battery2_BMS_a046_SW_Task_Stack_Usage = false; +static bool battery2_BMS_a047_SW_Task_Stack_Overflow = false; +static bool battery2_BMS_a048_SW_Log_Upload_Request = false; +static bool battery2_BMS_a169_SW_FC_Pack_Weld = false; +static bool battery2_BMS_a050_SW_Brick_Voltage_MIA = false; +static bool battery2_BMS_a051_SW_HVC_Vref_Bad = false; +static bool battery2_BMS_a052_SW_PCS_MIA = false; +static bool battery2_BMS_a053_SW_ThermalModel_Sanity = false; +static bool battery2_BMS_a054_SW_Ver_Supply_Fault = false; +static bool battery2_BMS_a176_SW_GracefulPowerOff = false; +static bool battery2_BMS_a059_SW_Pack_Voltage_Sensing = false; +static bool battery2_BMS_a060_SW_Leakage_Test_Failure = false; +static bool battery2_BMS_a077_SW_Charger_Regulation = false; +static bool battery2_BMS_a081_SW_Ctr_Close_Blocked = false; +static bool battery2_BMS_a082_SW_Ctr_Force_Open = false; +static bool battery2_BMS_a083_SW_Ctr_Close_Failure = false; +static bool battery2_BMS_a084_SW_Sleep_Wake_Aborted = false; +static bool battery2_BMS_a094_SW_Drive_Inverter_MIA = false; +static bool battery2_BMS_a099_SW_BMB_Communication = false; +static bool battery2_BMS_a105_SW_One_Module_Tsense = false; +static bool battery2_BMS_a106_SW_All_Module_Tsense = false; +static bool battery2_BMS_a107_SW_Stack_Voltage_MIA = false; +static bool battery2_BMS_a121_SW_NVRAM_Config_Error = false; +static bool battery2_BMS_a122_SW_BMS_Therm_Irrational = false; +static bool battery2_BMS_a123_SW_Internal_Isolation = false; +static bool battery2_BMS_a129_SW_VSH_Failure = false; +static bool battery2_BMS_a131_Bleed_FET_Failure = false; +static bool battery2_BMS_a136_SW_Module_OT_Warning = false; +static bool battery2_BMS_a137_SW_Brick_UV_Warning = false; +static bool battery2_BMS_a138_SW_Brick_OV_Warning = false; +static bool battery2_BMS_a139_SW_DC_Link_V_Irrational = false; +static bool battery2_BMS_a141_SW_BMB_Status_Warning = false; +static bool battery2_BMS_a144_Hvp_Config_Mismatch = false; +static bool battery2_BMS_a145_SW_SOC_Change = false; +static bool battery2_BMS_a146_SW_Brick_Overdischarged = false; +static bool battery2_BMS_a149_SW_Missing_Config_Block = false; +static bool battery2_BMS_a151_SW_external_isolation = false; +static bool battery2_BMS_a156_SW_BMB_Vref_bad = false; +static bool battery2_BMS_a157_SW_HVP_HVS_Comms = false; +static bool battery2_BMS_a159_SW_HVP_ECU_Error = false; +static bool battery2_BMS_a16false_SW_DI_Open_Request = false; +static bool battery2_BMS_a162_SW_No_Power_For_Support = false; +static bool battery2_BMS_a163_SW_Contactor_Mismatch = false; +static bool battery2_BMS_a164_SW_Uncontrolled_Regen = false; +static bool battery2_BMS_a165_SW_Pack_Partial_Weld = false; +static bool battery2_BMS_a166_SW_Pack_Full_Weld = false; +static bool battery2_BMS_a167_SW_FC_Partial_Weld = false; +static bool battery2_BMS_a168_SW_FC_Full_Weld = false; +static bool battery2_BMS_a170_SW_Limp_Mode = false; +static bool battery2_BMS_a171_SW_Stack_Voltage_Sense = false; +static bool battery2_BMS_a174_SW_Charge_Failure = false; +static bool battery2_BMS_a179_SW_Hvp_12V_Fault = false; +static bool battery2_BMS_a180_SW_ECU_reset_blocked = false; + #endif //DOUBLE_BATTERY static const char* contactorText[] = {"UNKNOWN(0)", "OPEN", "CLOSING", "BLOCKED", "OPENING", @@ -368,6 +954,7 @@ void update_values_battery() { //This function maps all the values fetched via #endif // TESLA_MODEL_3Y_BATTERY // Update webserver datalayer + //0x20A datalayer_extended.tesla.status_contactor = battery_contactor; datalayer_extended.tesla.hvil_status = battery_hvil_status; datalayer_extended.tesla.packContNegativeState = battery_packContNegativeState; @@ -375,11 +962,16 @@ void update_values_battery() { //This function maps all the values fetched via datalayer_extended.tesla.packContactorSetState = battery_packContactorSetState; datalayer_extended.tesla.packCtrsClosingAllowed = battery_packCtrsClosingAllowed; datalayer_extended.tesla.pyroTestInProgress = battery_pyroTestInProgress; - datalayer_extended.tesla.battery_beginning_of_life = battery_beginning_of_life; //add from her down - datalayer_extended.tesla.battery_battTempPct = battery_battTempPct; + datalayer_extended.tesla.battery_packCtrsOpenNowRequested = battery_packCtrsOpenNowRequested; + datalayer_extended.tesla.battery_packCtrsOpenRequested = battery_packCtrsOpenRequested; + datalayer_extended.tesla.battery_packCtrsRequestStatus = battery_packCtrsRequestStatus; + datalayer_extended.tesla.battery_packCtrsResetRequestRequired = battery_packCtrsResetRequestRequired; + datalayer_extended.tesla.battery_dcLinkAllowedToEnergize = battery_dcLinkAllowedToEnergize; + //0x2B4 datalayer_extended.tesla.battery_dcdcLvBusVolt = battery_dcdcLvBusVolt; datalayer_extended.tesla.battery_dcdcHvBusVolt = battery_dcdcHvBusVolt; datalayer_extended.tesla.battery_dcdcLvOutputCurrent = battery_dcdcLvOutputCurrent; + //0x352 datalayer_extended.tesla.battery_nominal_full_pack_energy = battery_nominal_full_pack_energy; datalayer_extended.tesla.battery_nominal_full_pack_energy_m0 = battery_nominal_full_pack_energy_m0; datalayer_extended.tesla.battery_nominal_energy_remaining = battery_nominal_energy_remaining; @@ -390,23 +982,159 @@ void update_values_battery() { //This function maps all the values fetched via datalayer_extended.tesla.battery_energy_to_charge_complete_m1 = battery_energy_to_charge_complete_m1; datalayer_extended.tesla.battery_energy_buffer = battery_energy_buffer; datalayer_extended.tesla.battery_energy_buffer_m1 = battery_energy_buffer_m1; + datalayer_extended.tesla.battery_expected_energy_remaining_m1 = battery_expected_energy_remaining_m1; datalayer_extended.tesla.battery_full_charge_complete = battery_full_charge_complete; + datalayer_extended.tesla.battery_fully_charged = battery_fully_charged; + //0x3D2 datalayer_extended.tesla.battery_total_discharge = battery_total_discharge; datalayer_extended.tesla.battery_total_charge = battery_total_charge; - datalayer_extended.tesla.battery_fully_charged = battery_fully_charged; - datalayer_extended.tesla.battery_packConfigMultiplexer = battery_packConfigMultiplexer; + //0x392 datalayer_extended.tesla.battery_moduleType = battery_moduleType; - datalayer_extended.tesla.battery_reservedConfig = battery_reservedConfig; datalayer_extended.tesla.battery_packMass = battery_packMass; datalayer_extended.tesla.battery_platformMaxBusVoltage = battery_platformMaxBusVoltage; + //0x2D2 datalayer_extended.tesla.battery_bms_min_voltage = battery_bms_min_voltage; datalayer_extended.tesla.battery_bms_max_voltage = battery_bms_max_voltage; datalayer_extended.tesla.battery_max_charge_current = battery_max_charge_current; datalayer_extended.tesla.battery_max_discharge_current = battery_max_discharge_current; + //0x292 + datalayer_extended.tesla.battery_beginning_of_life = battery_beginning_of_life; + datalayer_extended.tesla.battery_battTempPct = battery_battTempPct; datalayer_extended.tesla.battery_soc_ave = battery_soc_ave; datalayer_extended.tesla.battery_soc_max = battery_soc_max; datalayer_extended.tesla.battery_soc_min = battery_soc_min; datalayer_extended.tesla.battery_soc_ui = battery_soc_ui; + //0x332 + datalayer_extended.tesla.battery_BrickVoltageMax = battery_BrickVoltageMax; + datalayer_extended.tesla.battery_BrickVoltageMin = battery_BrickVoltageMin; + datalayer_extended.tesla.battery_BrickTempMaxNum = battery_BrickTempMaxNum; + datalayer_extended.tesla.battery_BrickTempMinNum = battery_BrickTempMinNum; + datalayer_extended.tesla.battery_BrickModelTMax = battery_BrickModelTMax; + datalayer_extended.tesla.battery_BrickModelTMin = battery_BrickModelTMin; + //0x212 + datalayer_extended.tesla.battery_BMS_isolationResistance = battery_BMS_isolationResistance; + datalayer_extended.tesla.battery_BMS_contactorState = battery_BMS_contactorState; + datalayer_extended.tesla.battery_BMS_state = battery_BMS_state; + datalayer_extended.tesla.battery_BMS_hvState = battery_BMS_hvState; + datalayer_extended.tesla.battery_BMS_uiChargeStatus = battery_BMS_uiChargeStatus; + datalayer_extended.tesla.battery_BMS_diLimpRequest = battery_BMS_diLimpRequest; + datalayer_extended.tesla.battery_BMS_chgPowerAvailable = battery_BMS_chgPowerAvailable; + datalayer_extended.tesla.battery_BMS_pcsPwmEnabled = battery_BMS_pcsPwmEnabled; + //0x224 + datalayer_extended.tesla.battery_PCS_dcdcPrechargeStatus = battery_PCS_dcdcPrechargeStatus; + datalayer_extended.tesla.battery_PCS_dcdc12VSupportStatus = battery_PCS_dcdc12VSupportStatus; + datalayer_extended.tesla.battery_PCS_dcdcHvBusDischargeStatus = battery_PCS_dcdcHvBusDischargeStatus; + datalayer_extended.tesla.battery_PCS_dcdcMainState = battery_PCS_dcdcMainState; + datalayer_extended.tesla.battery_PCS_dcdcSubState = battery_PCS_dcdcSubState; + datalayer_extended.tesla.battery_PCS_dcdcFaulted = battery_PCS_dcdcFaulted; + datalayer_extended.tesla.battery_PCS_dcdcOutputIsLimited = battery_PCS_dcdcOutputIsLimited; + datalayer_extended.tesla.battery_PCS_dcdcMaxOutputCurrentAllowed = battery_PCS_dcdcMaxOutputCurrentAllowed; + datalayer_extended.tesla.battery_PCS_dcdcPrechargeRtyCnt = battery_PCS_dcdcPrechargeRtyCnt; + datalayer_extended.tesla.battery_PCS_dcdc12VSupportRtyCnt = battery_PCS_dcdc12VSupportRtyCnt; + datalayer_extended.tesla.battery_PCS_dcdcDischargeRtyCnt = battery_PCS_dcdcDischargeRtyCnt; + datalayer_extended.tesla.battery_PCS_dcdcPwmEnableLine = battery_PCS_dcdcPwmEnableLine; + datalayer_extended.tesla.battery_PCS_dcdcSupportingFixedLvTarget = battery_PCS_dcdcSupportingFixedLvTarget; + datalayer_extended.tesla.battery_PCS_dcdcPrechargeRestartCnt = battery_PCS_dcdcPrechargeRestartCnt; + datalayer_extended.tesla.battery_PCS_dcdcInitialPrechargeSubState = battery_PCS_dcdcInitialPrechargeSubState; + //0x252 + datalayer_extended.tesla.BMS_maxRegenPower = BMS_maxRegenPower; + datalayer_extended.tesla.BMS_maxDischargePower = BMS_maxDischargePower; + datalayer_extended.tesla.BMS_maxStationaryHeatPower = BMS_maxStationaryHeatPower; + datalayer_extended.tesla.BMS_hvacPowerBudget = BMS_hvacPowerBudget; + datalayer_extended.tesla.BMS_notEnoughPowerForHeatPump = BMS_notEnoughPowerForHeatPump; + datalayer_extended.tesla.BMS_powerLimitState = BMS_powerLimitState; + datalayer_extended.tesla.BMS_inverterTQF = BMS_inverterTQF; + //0x312 + datalayer_extended.tesla.BMS_powerDissipation = BMS_powerDissipation; + datalayer_extended.tesla.BMS_flowRequest = BMS_flowRequest; + datalayer_extended.tesla.BMS_inletActiveCoolTargetT = BMS_inletActiveCoolTargetT; + datalayer_extended.tesla.BMS_inletPassiveTargetT = BMS_inletPassiveTargetT; + datalayer_extended.tesla.BMS_inletActiveHeatTargetT = BMS_inletActiveHeatTargetT; + datalayer_extended.tesla.BMS_packTMin = BMS_packTMin; + datalayer_extended.tesla.BMS_packTMax = BMS_packTMax; + datalayer_extended.tesla.BMS_pcsNoFlowRequest = BMS_pcsNoFlowRequest; + datalayer_extended.tesla.BMS_noFlowRequest = BMS_noFlowRequest; + //0x2A4 + datalayer_extended.tesla.PCS_dcdcTemp = PCS_dcdcTemp; + datalayer_extended.tesla.PCS_ambientTemp = PCS_ambientTemp; + //0x2C4 + datalayer_extended.tesla.PCS_dcdcMaxLvOutputCurrent = PCS_dcdcMaxLvOutputCurrent; + datalayer_extended.tesla.PCS_dcdcCurrentLimit = PCS_dcdcCurrentLimit; + datalayer_extended.tesla.PCS_dcdcLvOutputCurrentTempLimit = PCS_dcdcLvOutputCurrentTempLimit; + datalayer_extended.tesla.PCS_dcdcUnifiedCommand = PCS_dcdcUnifiedCommand; + datalayer_extended.tesla.PCS_dcdcCLAControllerOutput = PCS_dcdcCLAControllerOutput; + datalayer_extended.tesla.PCS_dcdcTankVoltage = PCS_dcdcTankVoltage; + datalayer_extended.tesla.PCS_dcdcTankVoltageTarget = PCS_dcdcTankVoltageTarget; + datalayer_extended.tesla.PCS_dcdcClaCurrentFreq = PCS_dcdcClaCurrentFreq; + datalayer_extended.tesla.PCS_dcdcTCommMeasured = PCS_dcdcTCommMeasured; + datalayer_extended.tesla.PCS_dcdcShortTimeUs = PCS_dcdcShortTimeUs; + datalayer_extended.tesla.PCS_dcdcHalfPeriodUs = PCS_dcdcHalfPeriodUs; + datalayer_extended.tesla.PCS_dcdcIntervalMaxFrequency = PCS_dcdcIntervalMaxFrequency; + datalayer_extended.tesla.PCS_dcdcIntervalMaxHvBusVolt = PCS_dcdcIntervalMaxHvBusVolt; + datalayer_extended.tesla.PCS_dcdcIntervalMaxLvBusVolt = PCS_dcdcIntervalMaxLvBusVolt; + datalayer_extended.tesla.PCS_dcdcIntervalMaxLvOutputCurr = PCS_dcdcIntervalMaxLvOutputCurr; + datalayer_extended.tesla.PCS_dcdcIntervalMinFrequency = PCS_dcdcIntervalMinFrequency; + datalayer_extended.tesla.PCS_dcdcIntervalMinHvBusVolt = PCS_dcdcIntervalMinHvBusVolt; + datalayer_extended.tesla.PCS_dcdcIntervalMinLvBusVolt = PCS_dcdcIntervalMinLvBusVolt; + datalayer_extended.tesla.PCS_dcdcIntervalMinLvOutputCurr = PCS_dcdcIntervalMinLvOutputCurr; + datalayer_extended.tesla.PCS_dcdc12vSupportLifetimekWh = PCS_dcdc12vSupportLifetimekWh; + //0x7AA + datalayer_extended.tesla.HVP_gpioPassivePyroDepl = HVP_gpioPassivePyroDepl; + datalayer_extended.tesla.HVP_gpioPyroIsoEn = HVP_gpioPyroIsoEn; + datalayer_extended.tesla.HVP_gpioCpFaultIn = HVP_gpioCpFaultIn; + datalayer_extended.tesla.HVP_gpioPackContPowerEn = HVP_gpioPackContPowerEn; + datalayer_extended.tesla.HVP_gpioHvCablesOk = HVP_gpioHvCablesOk; + datalayer_extended.tesla.HVP_gpioHvpSelfEnable = HVP_gpioHvpSelfEnable; + datalayer_extended.tesla.HVP_gpioLed = HVP_gpioLed; + datalayer_extended.tesla.HVP_gpioCrashSignal = HVP_gpioCrashSignal; + datalayer_extended.tesla.HVP_gpioShuntDataReady = HVP_gpioShuntDataReady; + datalayer_extended.tesla.HVP_gpioFcContPosAux = HVP_gpioFcContPosAux; + datalayer_extended.tesla.HVP_gpioFcContNegAux = HVP_gpioFcContNegAux; + datalayer_extended.tesla.HVP_gpioBmsEout = HVP_gpioBmsEout; + datalayer_extended.tesla.HVP_gpioCpFaultOut = HVP_gpioCpFaultOut; + datalayer_extended.tesla.HVP_gpioPyroPor = HVP_gpioPyroPor; + datalayer_extended.tesla.HVP_gpioShuntEn = HVP_gpioShuntEn; + datalayer_extended.tesla.HVP_gpioHvpVerEn = HVP_gpioHvpVerEn; + datalayer_extended.tesla.HVP_gpioPackCoontPosFlywheel = HVP_gpioPackCoontPosFlywheel; + datalayer_extended.tesla.HVP_gpioCpLatchEnable = HVP_gpioCpLatchEnable; + datalayer_extended.tesla.HVP_gpioPcsEnable = HVP_gpioPcsEnable; + datalayer_extended.tesla.HVP_gpioPcsDcdcPwmEnable = HVP_gpioPcsDcdcPwmEnable; + datalayer_extended.tesla.HVP_gpioPcsChargePwmEnable = HVP_gpioPcsChargePwmEnable; + datalayer_extended.tesla.HVP_gpioFcContPowerEnable = HVP_gpioFcContPowerEnable; + datalayer_extended.tesla.HVP_gpioHvilEnable = HVP_gpioHvilEnable; + datalayer_extended.tesla.HVP_gpioSecDrdy = HVP_gpioSecDrdy; + datalayer_extended.tesla.HVP_hvp1v5Ref = HVP_hvp1v5Ref; + datalayer_extended.tesla.HVP_shuntCurrentDebug = HVP_shuntCurrentDebug; + datalayer_extended.tesla.HVP_packCurrentMia = HVP_packCurrentMia; + datalayer_extended.tesla.HVP_auxCurrentMia = HVP_auxCurrentMia; + datalayer_extended.tesla.HVP_currentSenseMia = HVP_currentSenseMia; + datalayer_extended.tesla.HVP_shuntRefVoltageMismatch = HVP_shuntRefVoltageMismatch; + datalayer_extended.tesla.HVP_shuntThermistorMia = HVP_shuntThermistorMia; + datalayer_extended.tesla.HVP_shuntHwMia = HVP_shuntHwMia; + datalayer_extended.tesla.HVP_dcLinkVoltage = HVP_dcLinkVoltage; + datalayer_extended.tesla.HVP_packVoltage = HVP_packVoltage; + datalayer_extended.tesla.HVP_fcLinkVoltage = HVP_fcLinkVoltage; + datalayer_extended.tesla.HVP_packContVoltage = HVP_packContVoltage; + datalayer_extended.tesla.HVP_packNegativeV = HVP_packNegativeV; + datalayer_extended.tesla.HVP_packPositiveV = HVP_packPositiveV; + datalayer_extended.tesla.HVP_pyroAnalog = HVP_pyroAnalog; + datalayer_extended.tesla.HVP_dcLinkNegativeV = HVP_dcLinkNegativeV; + datalayer_extended.tesla.HVP_dcLinkPositiveV = HVP_dcLinkPositiveV; + datalayer_extended.tesla.HVP_fcLinkNegativeV = HVP_fcLinkNegativeV; + datalayer_extended.tesla.HVP_fcContCoilCurrent = HVP_fcContCoilCurrent; + datalayer_extended.tesla.HVP_fcContVoltage = HVP_fcContVoltage; + datalayer_extended.tesla.HVP_hvilInVoltage = HVP_hvilInVoltage; + datalayer_extended.tesla.HVP_hvilOutVoltage = HVP_hvilOutVoltage; + datalayer_extended.tesla.HVP_fcLinkPositiveV = HVP_fcLinkPositiveV; + datalayer_extended.tesla.HVP_packContCoilCurrent = HVP_packContCoilCurrent; + datalayer_extended.tesla.HVP_battery12V = HVP_battery12V; + datalayer_extended.tesla.HVP_shuntRefVoltageDbg = HVP_shuntRefVoltageDbg; + datalayer_extended.tesla.HVP_shuntAuxCurrentDbg = HVP_shuntAuxCurrentDbg; + datalayer_extended.tesla.HVP_shuntBarTempDbg = HVP_shuntBarTempDbg; + datalayer_extended.tesla.HVP_shuntAsicTempDbg = HVP_shuntAsicTempDbg; + datalayer_extended.tesla.HVP_shuntAuxCurrentStatus = HVP_shuntAuxCurrentStatus; + datalayer_extended.tesla.HVP_shuntBarTempStatus = HVP_shuntBarTempStatus; + datalayer_extended.tesla.HVP_shuntAsicTempStatus = HVP_shuntAsicTempStatus; #ifdef DEBUG_LOG @@ -478,19 +1206,25 @@ void receive_can_battery(CAN_frame rx_frame) { static uint16_t temp = 0; switch (rx_frame.ID) { - case 0x352: // BMS_energyStatus // newer BMS >2021 + case 0x352: // 850 BMS_energyStatus newer BMS mux = (rx_frame.data.u8[0] & 0x02); //BMS_energyStatusIndex M : 0|2@1+ (1,0) [0|0] "" X if (mux == 0) { - //battery_nominal_full_pack_energy_m0 = ((rx_frame.data.u8[3] << 8) | rx_frame.data.u8[2]); //BMS_nominalFullPackEnergy m0 : 16|16@1+ (0.02,0) [0|0] "kWh" X - //battery_nominal_energy_remaining_m0 = ((rx_frame.data.u8[5] << 8) | rx_frame.data.u8[4]); //BMS_nominalEnergyRemaining m0 : 32|16@1+ (0.02,0) [0|0] "kWh" X - //battery_ideal_energy_remaining_m0 = ((rx_frame.data.u8[7] << 8) | rx_frame.data.u8[6]); //BMS_idealEnergyRemaining m0 : 48|16@1+ (0.02,0) [0|0] "kWh" X + battery_nominal_full_pack_energy_m0 = + ((rx_frame.data.u8[3] << 8) | rx_frame.data.u8[2]); //16|16@1+ (0.02,0) [0|0] "kWh"//to datalayer_extended + battery_nominal_energy_remaining_m0 = + ((rx_frame.data.u8[5] << 8) | rx_frame.data.u8[4]); //32|16@1+ (0.02,0) [0|0] "kWh"//to datalayer_extended + battery_ideal_energy_remaining_m0 = + ((rx_frame.data.u8[7] << 8) | rx_frame.data.u8[6]); //48|16@1+ (0.02,0) [0|0] "kWh"//to datalayer_extended } if (mux == 1) { - //battery_fully_charged = (rx_frame.data.u8[1] & 0x01); //BMS_fullyCharged m1 : 15|1@1+ (1,0) [0|1] "" X - //battery_energy_buffer_m1 = (rx_frame.data.u8[3] | rx_frame.data.u8[2]); //BMS_energyBuffer m1 : 16|16@1+ (0.01,0) [0|0] "kWh" X - //battery_expected_energy_remaining_m1 = (rx_frame.data.u8[5] | rx_frame.data.u8[4]); //BMS_expectedEnergyRemaining m1 : 32|16@1+ (0.02,0) [0|0] "kWh" X - //battery_energy_to_charge_complete_m1 = (rx_frame.data.u8[7] | rx_frame.data.u8[6]); //BMS_energyToChargeComplete m1 : 48|16@1+ (0.02,0) [0|0] "kWh" X + battery_fully_charged = (rx_frame.data.u8[1] & 0x01); //15|1@1+ (1,0) [0|1]//to datalayer_extended + battery_energy_buffer_m1 = + (rx_frame.data.u8[3] | rx_frame.data.u8[2]); //16|16@1+ (0.01,0) [0|0] "kWh"//to datalayer_extended + battery_expected_energy_remaining_m1 = + (rx_frame.data.u8[5] | rx_frame.data.u8[4]); //32|16@1+ (0.02,0) [0|0] "kWh"//to datalayer_extended + battery_energy_to_charge_complete_m1 = + (rx_frame.data.u8[7] | rx_frame.data.u8[6]); //48|16@1+ (0.02,0) [0|0] "kWh"//to datalayer_extended } if (mux == 2) {} // Additional information needed on this mux, example frame: 02 26 02 20 02 80 00 00 doesn't change @@ -511,42 +1245,122 @@ void receive_can_battery(CAN_frame rx_frame) { battery_full_charge_complete = //BMS_fullChargeComplete : 63|1@1+ (1,0) [0|1] ""//((_d[7] >> 7) & (0x01U)); ((rx_frame.data.u8[7] & 0x01) >> 7); break; - case 0x20A: //Contactor state //HVP_contactorState: - battery_packContNegativeState = (rx_frame.data.u8[0] & 0x07); //0|3@1+ (1,0) [0|7] "" - battery_packContPositiveState = (rx_frame.data.u8[0] & 0x38) >> 3; //3|3@1+ (1,0) [0|7] "" - battery_contactor = (rx_frame.data.u8[1] & 0x0F); //HVP_packContactorSetState : 8|4@1+ (1,0) [0|9] "" - battery_packContactorSetState = (rx_frame.data.u8[1] & 0x0F); //HVP_packContactorSetState : 8|4@1+ (1,0) [0|9] "" - battery_packCtrsClosingAllowed = (rx_frame.data.u8[4] & 0x08) >> 3; //35|1@1+ (1,0) [0|1] "" - battery_pyroTestInProgress = (rx_frame.data.u8[4] & 0x20) >> 5; //37|1@1+ (1,0) [0|1] "" - battery_hvil_status = (rx_frame.data.u8[5] & 0x0F); //40|4@1+ (1,0) [0|9] "" - //HVP_packCtrsOpenNowRequested : 33|1@1+ (1,0) [0|1] "" - //HVP_packCtrsOpenRequested : 34|1@1+ (1,0) [0|1] "" - //HVP_packCtrsRequestStatus : 30|2@1+ (1,0) [0|2] "" - //HVP_packCtrsResetRequestRequired : 32|1@1+ (1,0) [0|1] "" - //HVP_dcLinkAllowedToEnergize : 36|1@1+ (1,0) [0|1] "" Receiver - //HVP_fcContNegativeAuxOpen : 7|1@1+ (1,0) [0|1] "" Receiver - //HVP_fcContNegativeState : 12|3@1+ (1,0) [0|7] "" Receiver - //HVP_fcContPositiveAuxOpen : 6|1@1+ (1,0) [0|1] "" Receiver - //HVP_fcContPositiveState : 16|3@1+ (1,0) [0|7] "" Receiver - //HVP_fcContactorSetState : 19|4@1+ (1,0) [0|9] "" Receiver - //HVP_fcCtrsClosingAllowed : 29|1@1+ (1,0) [0|1] "" Receiver - //HVP_fcCtrsOpenNowRequested : 27|1@1+ (1,0) [0|1] "" Receiver - //HVP_fcCtrsOpenRequested : 28|1@1+ (1,0) [0|1] "" Receiver - //HVP_fcCtrsRequestStatus : 24|2@1+ (1,0) [0|2] "" Receiver - //HVP_fcCtrsResetRequestRequired : 26|1@1+ (1,0) [0|1] "" Receiver - //HVP_fcLinkAllowedToEnergize : 44|2@1+ (1,0) [0|2] "" Receiver + case 0x20A: //522 HVP_contactorState: + battery_packContNegativeState = + (rx_frame.data.u8[0] & 0x07); //(_d[0] & (0x07U)); 0|3@1+ (1,0) [0|7] //to datalayer_extended + battery_packContPositiveState = + (rx_frame.data.u8[0] & 0x38) >> 3; //((_d[0] >> 3) & (0x07U)); 3|3@1+ (1,0) [0|7] //to datalayer_extended + battery_contactor = (rx_frame.data.u8[1] & 0x0F); // 8|4@1+ (1,0) [0|9] //to datalayer_extended + battery_packContactorSetState = + (rx_frame.data.u8[1] & 0x0F); //(_d[1] & (0x0FU)); 8|4@1+ (1,0) [0|9] //to datalayer_extended + battery_packCtrsClosingAllowed = + (rx_frame.data.u8[4] & 0x08) >> 3; //((_d[4] >> 3) & (0x01U)); 35|1@1+ (1,0) [0|1] //to datalayer_extended + battery_pyroTestInProgress = + (rx_frame.data.u8[4] & 0x20) >> 5; //((_d[4] >> 5) & (0x01U));//37|1@1+ (1,0) [0|1] //to datalayer_extended + battery_hvil_status = + (rx_frame.data.u8[5] & 0x0F); //(_d[5] & (0x0FU)); //40|4@1+ (1,0) [0|9] //to datalayer_extended + battery_packCtrsOpenNowRequested = + ((rx_frame.data.u8[4] >> 1) & (0x01U)); //33|1@1+ (1,0) [0|1] //to datalayer_extended + battery_packCtrsOpenRequested = + ((rx_frame.data.u8[4] >> 2) & (0x01U)); //34|1@1+ (1,0) [0|1] //to datalayer_extended + battery_packCtrsRequestStatus = + ((rx_frame.data.u8[3] >> 6) & (0x03U)); //30|2@1+ (1,0) [0|2] //to datalayer_extended + battery_packCtrsResetRequestRequired = + (rx_frame.data.u8[4] & (0x01U)); //32|1@1+ (1,0) [0|1] //to datalayer_extended + battery_dcLinkAllowedToEnergize = + ((rx_frame.data.u8[4] >> 4) & (0x01U)); //36|1@1+ (1,0) [0|1] //to datalayer_extended + battery_fcContNegativeAuxOpen = ((rx_frame.data.u8[0] >> 7) & (0x01U)); //7|1@1+ (1,0) [0|1] "" Receiver + battery_fcContNegativeState = ((rx_frame.data.u8[1] >> 4) & (0x07U)); //12|3@1+ (1,0) [0|7] "" Receiver + battery_fcContPositiveAuxOpen = ((rx_frame.data.u8[0] >> 6) & (0x01U)); //6|1@1+ (1,0) [0|1] "" Receiver + battery_fcContPositiveState = (rx_frame.data.u8[2] & (0x07U)); //16|3@1+ (1,0) [0|7] "" Receiver + battery_fcContactorSetState = ((rx_frame.data.u8[2] >> 3) & (0x0FU)); //19|4@1+ (1,0) [0|9] "" Receiver + battery_fcCtrsClosingAllowed = ((rx_frame.data.u8[3] >> 5) & (0x01U)); //29|1@1+ (1,0) [0|1] "" Receiver + battery_fcCtrsOpenNowRequested = ((rx_frame.data.u8[3] >> 3) & (0x01U)); //27|1@1+ (1,0) [0|1] "" Receiver + battery_fcCtrsOpenRequested = ((rx_frame.data.u8[3] >> 4) & (0x01U)); //28|1@1+ (1,0) [0|1] "" Receiver + battery_fcCtrsRequestStatus = (rx_frame.data.u8[3] & (0x03U)); //24|2@1+ (1,0) [0|2] "" Receiver + battery_fcCtrsResetRequestRequired = ((rx_frame.data.u8[3] >> 2) & (0x01U)); //26|1@1+ (1,0) [0|1] "" Receiver + battery_fcLinkAllowedToEnergize = ((rx_frame.data.u8[5] >> 4) & (0x03U)); //44|2@1+ (1,0) [0|2] "" Receiver break; - case 0x252: //Limit //BMS_powerAvailable252: - battery_regenerative_limit = ((rx_frame.data.u8[1] << 8) | rx_frame.data.u8[0]) * - 0.01; //0|16@1+ (0.01,0) [0|655.35] "kW" //Example 4715 * 0.01 = 47.15kW - battery_discharge_limit = ((rx_frame.data.u8[3] << 8) | rx_frame.data.u8[2]) * - 0.013; //16|16@1+ (0.013,0) [0|655.35] "kW" //Example 2009 * 0.013 = 26.117??? - battery_max_heat_park = (((rx_frame.data.u8[5] & 0x03) << 8) | rx_frame.data.u8[4]) * - 0.01; //32|10@1+ (0.01,0) [0|10.23] "kW" //Example 500 * 0.01 = 5kW - battery_hvac_max_power = (((rx_frame.data.u8[7] << 6) | ((rx_frame.data.u8[6] & 0xFC) >> 2))) * - 0.02; //50|10@1+ (0.02,0) [0|20.46] "kW" //Example 1000 * 0.02 = 20kW? - //BMS_notEnoughPowerForHeatPump : 42|1@1+ (1,0) [0|1] "" Receiver - //BMS_powerLimitsState : 48|1@1+ (1,0) [0|1] "" Receiver + case 0x212: //530 BMS_status: 8 + battery_BMS_hvacPowerRequest = (rx_frame.data.u8[0] & (0x01U)); + battery_BMS_notEnoughPowerForDrive = ((rx_frame.data.u8[0] >> 1) & (0x01U)); + battery_BMS_notEnoughPowerForSupport = ((rx_frame.data.u8[0] >> 2) & (0x01U)); + battery_BMS_preconditionAllowed = ((rx_frame.data.u8[0] >> 3) & (0x01U)); + battery_BMS_updateAllowed = ((rx_frame.data.u8[0] >> 4) & (0x01U)); + battery_BMS_activeHeatingWorthwhile = ((rx_frame.data.u8[0] >> 5) & (0x01U)); + battery_BMS_cpMiaOnHvs = ((rx_frame.data.u8[0] >> 6) & (0x01U)); + battery_BMS_contactorState = + (rx_frame.data.u8[1] & + (0x07U)); //0 "SNA" 1 "OPEN" 2 "OPENING" 3 "CLOSING" 4 "CLOSED" 5 "WELDED" 6 "BLOCKED" ; + battery_BMS_state = + ((rx_frame.data.u8[1] >> 3) & + (0x0FU)); //0 "STANDBY" 1 "DRIVE" 2 "SUPPORT" 3 "CHARGE" 4 "FEIM" 5 "CLEAR_FAULT" 6 "FAULT" 7 "WELD" 8 "TEST" 9 "SNA" ; + battery_BMS_hvState = + (rx_frame.data.u8[2] & + (0x07U)); //0 "DOWN" 1 "COMING_UP" 2 "GOING_DOWN" 3 "UP_FOR_DRIVE" 4 "UP_FOR_CHARGE" 5 "UP_FOR_DC_CHARGE" 6 "UP" ; + battery_BMS_isolationResistance = + ((rx_frame.data.u8[3] & (0x1FU)) << 5) | + ((rx_frame.data.u8[2] >> 3) & (0x1FU)); //19|10@1+ (10,0) [0|0] "kOhm"/to datalayer_extended + battery_BMS_chargeRequest = ((rx_frame.data.u8[3] >> 5) & (0x01U)); + battery_BMS_keepWarmRequest = ((rx_frame.data.u8[3] >> 6) & (0x01U)); + battery_BMS_uiChargeStatus = + (rx_frame.data.u8[4] & + (0x07U)); // 0 "DISCONNECTED" 1 "NO_POWER" 2 "ABOUT_TO_CHARGE" 3 "CHARGING" 4 "CHARGE_COMPLETE" 5 "CHARGE_STOPPED" ; + battery_BMS_diLimpRequest = ((rx_frame.data.u8[4] >> 3) & (0x01U)); + battery_BMS_okToShipByAir = ((rx_frame.data.u8[4] >> 4) & (0x01U)); + battery_BMS_okToShipByLand = ((rx_frame.data.u8[4] >> 5) & (0x01U)); + battery_BMS_chgPowerAvailable = ((rx_frame.data.u8[6] & (0x01U)) << 10) | ((rx_frame.data.u8[5] & (0xFFU)) << 2) | + ((rx_frame.data.u8[4] >> 6) & (0x03U)); //38|11@1+ (0.125,0) [0|0] "kW" + battery_BMS_chargeRetryCount = ((rx_frame.data.u8[6] >> 1) & (0x0FU)); + battery_BMS_pcsPwmEnabled = ((rx_frame.data.u8[6] >> 5) & (0x01U)); + battery_BMS_ecuLogUploadRequest = ((rx_frame.data.u8[6] >> 6) & (0x03U)); + battery_BMS_minPackTemperature = (rx_frame.data.u8[7] & (0xFFU)); //56|8@1+ (0.5,-40) [0|0] "DegC + break; + case 0x224: //548 PCS_dcdcStatus: + battery_PCS_dcdcPrechargeStatus = (rx_frame.data.u8[0] & (0x03U)); //0 "IDLE" 1 "ACTIVE" 2 "FAULTED" ; + battery_PCS_dcdc12VSupportStatus = ((rx_frame.data.u8[0] >> 2) & (0x03U)); //0 "IDLE" 1 "ACTIVE" 2 "FAULTED" + battery_PCS_dcdcHvBusDischargeStatus = ((rx_frame.data.u8[0] >> 4) & (0x03U)); //0 "IDLE" 1 "ACTIVE" 2 "FAULTED" + battery_PCS_dcdcMainState = + ((rx_frame.data.u8[1] & (0x03U)) << 2) | + ((rx_frame.data.u8[0] >> 6) & + (0x03U)); //0 "STANDBY" 1 "12V_SUPPORT_ACTIVE" 2 "PRECHARGE_STARTUP" 3 "PRECHARGE_ACTIVE" 4 "DIS_HVBUS_ACTIVE" 5 "SHUTDOWN" 6 "FAULTED" ; + battery_PCS_dcdcSubState = + ((rx_frame.data.u8[1] >> 2) & + (0x1FU)); //0 "PWR_UP_INIT" 1 "STANDBY" 2 "12V_SUPPORT_ACTIVE" 3 "DIS_HVBUS" 4 "PCHG_FAST_DIS_HVBUS" 5 "PCHG_SLOW_DIS_HVBUS" 6 "PCHG_DWELL_CHARGE" 7 "PCHG_DWELL_WAIT" 8 "PCHG_DI_RECOVERY_WAIT" 9 "PCHG_ACTIVE" 10 "PCHG_FLT_FAST_DIS_HVBUS" 11 "SHUTDOWN" 12 "12V_SUPPORT_FAULTED" 13 "DIS_HVBUS_FAULTED" 14 "PCHG_FAULTED" 15 "CLEAR_FAULTS" 16 "FAULTED" 17 "NUM" ; + battery_PCS_dcdcFaulted = ((rx_frame.data.u8[1] >> 7) & (0x01U)); + battery_PCS_dcdcOutputIsLimited = ((rx_frame.data.u8[3] >> 4) & (0x01U)); + battery_PCS_dcdcMaxOutputCurrentAllowed = ((rx_frame.data.u8[5] & (0x01U)) << 11) | + ((rx_frame.data.u8[4] & (0xFFU)) << 3) | + ((rx_frame.data.u8[3] >> 5) & (0x07U)); //29|12@1+ (0.1,0) [0|0] "A" + battery_PCS_dcdcPrechargeRtyCnt = ((rx_frame.data.u8[5] >> 1) & (0x07U)); + battery_PCS_dcdc12VSupportRtyCnt = ((rx_frame.data.u8[5] >> 4) & (0x0FU)); + battery_PCS_dcdcDischargeRtyCnt = (rx_frame.data.u8[6] & (0x0FU)); + battery_PCS_dcdcPwmEnableLine = ((rx_frame.data.u8[6] >> 4) & (0x01U)); + battery_PCS_dcdcSupportingFixedLvTarget = ((rx_frame.data.u8[6] >> 5) & (0x01U)); + battery_PCS_ecuLogUploadRequest = ((rx_frame.data.u8[6] >> 6) & (0x03U)); + battery_PCS_dcdcPrechargeRestartCnt = (rx_frame.data.u8[7] & (0x07U)); + battery_PCS_dcdcInitialPrechargeSubState = + ((rx_frame.data.u8[7] >> 3) & + (0x1FU)); //0 "PWR_UP_INIT" 1 "STANDBY" 2 "12V_SUPPORT_ACTIVE" 3 "DIS_HVBUS" 4 "PCHG_FAST_DIS_HVBUS" 5 "PCHG_SLOW_DIS_HVBUS" 6 "PCHG_DWELL_CHARGE" 7 "PCHG_DWELL_WAIT" 8 "PCHG_DI_RECOVERY_WAIT" 9 "PCHG_ACTIVE" 10 "PCHG_FLT_FAST_DIS_HVBUS" 11 "SHUTDOWN" 12 "12V_SUPPORT_FAULTED" 13 "DIS_HVBUS_FAULTED" 14 "PCHG_FAULTED" 15 "CLEAR_FAULTS" 16 "FAULTED" 17 "NUM" ; + break; + case 0x252: //Limit //594 BMS_powerAvailable: + BMS_maxRegenPower = ((rx_frame.data.u8[1] << 8) | + rx_frame.data.u8[0]); //0|16@1+ (0.01,0) [0|655.35] "kW" //Example 4715 * 0.01 = 47.15kW + BMS_maxDischargePower = + ((rx_frame.data.u8[3] << 8) | + rx_frame.data.u8[2]); //16|16@1+ (0.013,0) [0|655.35] "kW" //Example 2009 * 0.013 = 26.117??? + BMS_maxStationaryHeatPower = + (((rx_frame.data.u8[5] & 0x03) << 8) | + rx_frame.data.u8[4]); //32|10@1+ (0.01,0) [0|10.23] "kW" //Example 500 * 0.01 = 5kW + BMS_hvacPowerBudget = + (((rx_frame.data.u8[7] << 6) | + ((rx_frame.data.u8[6] & 0xFC) >> 2))); //50|10@1+ (0.02,0) [0|20.46] "kW" //Example 1000 * 0.02 = 20kW? + BMS_notEnoughPowerForHeatPump = + ((rx_frame.data.u8[5] >> 2) & (0x01U)); //BMS_notEnoughPowerForHeatPump : 42|1@1+ (1,0) [0|1] "" Receiver + BMS_powerLimitState = + (rx_frame.data.u8[6] & + (0x01U)); //BMS_powerLimitsState : 48|1@1+ (1,0) [0|1] 0 "NOT_CALCULATED_FOR_DRIVE" 1 "CALCULATED_FOR_DRIVE" + BMS_inverterTQF = ((rx_frame.data.u8[7] >> 4) & (0x03U)); break; case 0x132: //battery amps/volts //HVBattAmpVolt battery_volts = ((rx_frame.data.u8[1] << 8) | rx_frame.data.u8[0]) * @@ -584,26 +1398,121 @@ void receive_can_battery(CAN_frame rx_frame) { temp = ((rx_frame.data.u8[3] << 8) | rx_frame.data.u8[2]); temp = (temp & 0xFFF); battery_cell_min_v = temp * 2; - battery_max_vno = 1 + (rx_frame.data.u8[4] & 0x7F); //This cell has highest voltage - battery_min_vno = 1 + (rx_frame.data.u8[5] & 0x7F); //This cell has lowest voltage + //BattBrickVoltageMax m1 : 2|12@1+ (0.002,0) [0|0] "V" Receiver ((_d[1] & (0x3FU)) << 6) | ((_d[0] >> 2) & (0x3FU)); + battery_BrickVoltageMax = + ((rx_frame.data.u8[1] & (0x3F)) << 6) | ((rx_frame.data.u8[0] >> 2) & (0x3F)); //to datalayer_extended + //BattBrickVoltageMin m1 : 16|12@1+ (0.002,0) [0|0] "V" Receiver ((_d[3] & (0x0FU)) << 8) | (_d[2] & (0xFFU)); + battery_BrickVoltageMin = + ((rx_frame.data.u8[3] & (0x0F)) << 8) | (rx_frame.data.u8[2] & (0xFF)); //to datalayer_extended + //BattBrickVoltageMaxNum m1 : 32|7@1+ (1,1) [0|0] "" Receiver + battery_BrickVoltageMaxNum = + 1 + (rx_frame.data.u8[4] & 0x7F); //(_d[4] & (0x7FU)); //This cell has highest voltage + //BattBrickVoltageMinNum m1 : 40|7@1+ (1,1) [0|0] "" Receiver + battery_BrickVoltageMinNum = + 1 + (rx_frame.data.u8[5] & 0x7F); //(_d[5] & (0x7FU)); //This cell has lowest voltage } if (mux == 0) //Temperature sensors - { + { //BattBrickTempMax m0 : 16|8@1+ (0.5,-40) [0|0] "C" (_d[2] & (0xFFU)); battery_max_temp = (rx_frame.data.u8[2] * 5) - 400; //Temperature values have 40.0*C offset, 0.5*C /bit + //BattBrickTempMin m0 : 24|8@1+ (0.5,-40) [0|0] "C" (_d[3] & (0xFFU)); battery_min_temp = (rx_frame.data.u8[3] * 5) - 400; //Multiply by 5 and remove offset to get C+1 (0x61*5=485-400=8.5*C) + //BattBrickTempMaxNum m0 : 2|4@1+ (1,0) [0|0] "" ((_d[0] >> 2) & (0x0FU)); + battery_BrickTempMaxNum = ((rx_frame.data.u8[0] >> 2) & (0x0F)); //to datalayer_extended + //BattBrickTempMinNum m0 : 8|4@1+ (1,0) [0|0] "" (_d[1] & (0x0FU)); + battery_BrickTempMinNum = (rx_frame.data.u8[1] & (0x0F)); //to datalayer_extended + //BattBrickModelTMax m0 : 32|8@1+ (0.5,-40) [0|0] "C" (_d[4] & (0xFFU)); + battery_BrickModelTMax = (rx_frame.data.u8[4] & (0xFFU)); //to datalayer_extended + //BattBrickModelTMin m0 : 40|8@1+ (0.5,-40) [0|0] "C" (_d[5] & (0xFFU)); + battery_BrickModelTMin = (rx_frame.data.u8[5] & (0xFFU)); //to datalayer_extended + } + break; + case 0x312: // 786 BMS_thermalStatus + BMS_powerDissipation = + ((rx_frame.data.u8[1] & (0x03U)) << 8) | (rx_frame.data.u8[0] & (0xFFU)); //0|10@1+ (0.02,0) [0|0] "kW" + BMS_flowRequest = ((rx_frame.data.u8[2] & (0x01U)) << 6) | + ((rx_frame.data.u8[1] >> 2) & (0x3FU)); //10|7@1+ (0.3,0) [0|0] "LPM" + BMS_inletActiveCoolTargetT = ((rx_frame.data.u8[3] & (0x03U)) << 7) | + ((rx_frame.data.u8[2] >> 1) & (0x7FU)); //17|9@1+ (0.25,-25) [0|0] "DegC" + BMS_inletPassiveTargetT = ((rx_frame.data.u8[4] & (0x07U)) << 6) | + ((rx_frame.data.u8[3] >> 2) & (0x3FU)); //26|9@1+ (0.25,-25) [0|0] "DegC" X + BMS_inletActiveHeatTargetT = ((rx_frame.data.u8[5] & (0x0FU)) << 5) | + ((rx_frame.data.u8[4] >> 3) & (0x1FU)); //35|9@1+ (0.25,-25) [0|0] "DegC" + BMS_packTMin = ((rx_frame.data.u8[6] & (0x1FU)) << 4) | + ((rx_frame.data.u8[5] >> 4) & (0x0FU)); //44|9@1+ (0.25,-25) [-25|100] "DegC" + BMS_packTMax = ((rx_frame.data.u8[7] & (0x3FU)) << 3) | + ((rx_frame.data.u8[6] >> 5) & (0x07U)); //53|9@1+ (0.25,-25) [-25|100] "DegC" + BMS_pcsNoFlowRequest = ((rx_frame.data.u8[7] >> 6) & (0x01U)); // 62|1@1+ (1,0) [0|0] "" + BMS_noFlowRequest = ((rx_frame.data.u8[7] >> 7) & (0x01U)); //63|1@1+ (1,0) [0|0] "" + break; + case 0x2A4: //676 PCS_thermalStatus + PCS_chgPhATemp = + ((rx_frame.data.u8[1] & (0x07U)) << 8) | (rx_frame.data.u8[0] & (0xFFU)); //0|11@1- (0.1,40) [0|0] "C + PCS_chgPhBTemp = + ((rx_frame.data.u8[2] & (0x3FU)) << 5) | ((rx_frame.data.u8[1] >> 3) & (0x1FU)); //11|11@1- (0.1,40) [0|0] "C + PCS_chgPhCTemp = + ((rx_frame.data.u8[4] & (0x07U)) << 8) | (rx_frame.data.u8[3] & (0xFFU)); //24|11@1- (0.1,40) [0|0] "C" + PCS_dcdcTemp = ((rx_frame.data.u8[5] & (0x3FU)) << 5) | + ((rx_frame.data.u8[4] >> 3) & (0x1FU)); //35|11@1- (0.1,40) [0|0] "C" + PCS_ambientTemp = + ((rx_frame.data.u8[7] & (0x07U)) << 8) | (rx_frame.data.u8[6] & (0xFFU)); //48|11@1- (0.1,40) [0|0] "C" + break; + case 0x2C4: // 708 PCS_logging: not all frames are listed, just ones relating to dcdc + mux = (rx_frame.data.u8[0] & (0x1FU)); + //PCS_logMessageSelect = (rx_frame.data.u8[0] & (0x1FU)); //0|5@1+ (1,0) [0|0] "" + if (mux == 6) { + PCS_dcdcMaxLvOutputCurrent = ((rx_frame.data.u8[4] & (0xFFU)) << 4) | + ((rx_frame.data.u8[3] >> 4) & (0x0FU)); //m6 : 28|12@1+ (0.1,0) [0|0] "A" X + PCS_dcdcCurrentLimit = ((rx_frame.data.u8[6] & (0x0FU)) << 8) | + (rx_frame.data.u8[5] & (0xFFU)); //m6 : 40|12@1+ (0.1,0) [0|0] "A" X + PCS_dcdcLvOutputCurrentTempLimit = ((rx_frame.data.u8[7] & (0xFFU)) << 4) | + ((rx_frame.data.u8[6] >> 4) & (0x0FU)); //m6 : 52|12@1+ (0.1,0) [0|0] "A" X + } + if (mux == 7) { + PCS_dcdcUnifiedCommand = ((rx_frame.data.u8[1] & (0x7FU)) << 3) | + ((rx_frame.data.u8[0] >> 5) & (0x07U)); //m7 : 5|10@1+ (0.001,0) [0|0] "1" X + PCS_dcdcCLAControllerOutput = ((rx_frame.data.u8[3] & (0x03U)) << 8) | + (rx_frame.data.u8[2] & (0xFFU)); //m7 : 16|10@1+ (0.001,0) [0|0] "1" X + PCS_dcdcTankVoltage = ((rx_frame.data.u8[4] & (0x1FU)) << 6) | + ((rx_frame.data.u8[3] >> 2) & (0x3FU)); //m7 : 26|11@1- (1,0) [0|0] "V" X + PCS_dcdcTankVoltageTarget = ((rx_frame.data.u8[5] & (0x7FU)) << 3) | + ((rx_frame.data.u8[4] >> 5) & (0x07U)); // m7 : 37|10@1+ (1,0) [0|0] "V" X + PCS_dcdcClaCurrentFreq = ((rx_frame.data.u8[7] & (0x0FU)) << 8) | + (rx_frame.data.u8[6] & (0xFFU)); //P m7 : 48|12@1+ (0.0976563,0) [0|0] "kHz" X + } + if (mux == 8) { + PCS_dcdcTCommMeasured = ((rx_frame.data.u8[2] & (0xFFU)) << 8) | + (rx_frame.data.u8[1] & (0xFFU)); // m8 : 8|16@1- (0.00195313,0) [0|0] "us" X + PCS_dcdcShortTimeUs = ((rx_frame.data.u8[4] & (0xFFU)) << 8) | + (rx_frame.data.u8[3] & (0xFFU)); // m8 : 24|16@1+ (0.000488281,0) [0|0] "us" X + PCS_dcdcHalfPeriodUs = ((rx_frame.data.u8[6] & (0xFFU)) << 8) | + (rx_frame.data.u8[5] & (0xFFU)); // m8 : 40|16@1+ (0.000488281,0) [0|0] "us" X + } + if (mux == 18) { + PCS_dcdcIntervalMaxFrequency = ((rx_frame.data.u8[2] & (0x0FU)) << 8) | + (rx_frame.data.u8[1] & (0xFFU)); // m18 : 8|12@1+ (1,0) [0|0] "kHz" X + PCS_dcdcIntervalMaxHvBusVolt = ((rx_frame.data.u8[4] & (0x1FU)) << 8) | + (rx_frame.data.u8[3] & (0xFFU)); //m18 : 24|13@1+ (0.1,0) [0|0] "V" X + PCS_dcdcIntervalMaxLvBusVolt = ((rx_frame.data.u8[5] & (0x3FU)) << 3) | + ((rx_frame.data.u8[4] >> 5) & (0x07U)); // m18 : 37|9@1+ (0.1,0) [0|0] "V" X + PCS_dcdcIntervalMaxLvOutputCurr = ((rx_frame.data.u8[7] & (0x0FU)) << 8) | + (rx_frame.data.u8[6] & (0xFFU)); //m18 : 48|12@1+ (1,0) [0|0] "A" X + } + if (mux == 19) { + PCS_dcdcIntervalMinFrequency = ((rx_frame.data.u8[2] & (0x0FU)) << 8) | + (rx_frame.data.u8[1] & (0xFFU)); //m19 : 8|12@1+ (1,0) [0|0] "kHz" X + PCS_dcdcIntervalMinHvBusVolt = ((rx_frame.data.u8[4] & (0x1FU)) << 8) | + (rx_frame.data.u8[3] & (0xFFU)); //m19 : 24|13@1+ (0.1,0) [0|0] "V" X + PCS_dcdcIntervalMinLvBusVolt = ((rx_frame.data.u8[5] & (0x3FU)) << 3) | + ((rx_frame.data.u8[4] >> 5) & (0x07U)); //m19 : 37|9@1+ (0.1,0) [0|0] "V" X + PCS_dcdcIntervalMinLvOutputCurr = ((rx_frame.data.u8[7] & (0x0FU)) << 8) | + (rx_frame.data.u8[6] & (0xFFU)); // m19 : 48|12@1+ (1,0) [0|0] "A" X + } + if (mux == 22) { + PCS_dcdc12vSupportLifetimekWh = ((rx_frame.data.u8[3] & (0xFFU)) << 16) | + ((rx_frame.data.u8[2] & (0xFFU)) << 8) | + (rx_frame.data.u8[1] & (0xFFU)); // m22 : 8|24@1+ (0.01,0) [0|0] "kWh" X } - //BattBrickMultiplexer M : 0|2@1+ (1,0) [0|0] "" Receiver - //BattBrickTempMaxNum m0 : 2|4@1+ (1,0) [0|0] "" Receiver - //BattBrickTempMinNum m0 : 8|4@1+ (1,0) [0|0] "" Receiver - //BattBrickTempMax m0 : 16|8@1+ (0.5,-40) [0|0] "C" Receiver - //BattBrickTempMin m0 : 24|8@1+ (0.5,-40) [0|0] "C" Receiver - //BattBrickModelTMax m0 : 32|8@1+ (0.5,-40) [0|0] "C" Receiver - //BattBrickModelTMin m0 : 40|8@1+ (0.5,-40) [0|0] "C" Receiver - //BattBrickVoltageMax m1 : 2|12@1+ (0.002,0) [0|0] "V" Receiver - //BattBrickVoltageMin m1 : 16|12@1+ (0.002,0) [0|0] "V" Receiver - //BattBrickVoltageMaxNum m1 : 32|7@1+ (1,1) [0|0] "" Receiver - //BattBrickVoltageMinNum m1 : 40|7@1+ (1,1) [0|0] "" Receiver break; case 0x401: // Cell stats //BrickVoltages mux = (rx_frame.data.u8[0]); //MultiplexSelector M : 0|8@1+ (1,0) [0|0] "" @@ -677,13 +1586,114 @@ void receive_can_battery(CAN_frame rx_frame) { mux = (rx_frame.data.u8[0] & (0xFF)); if (mux == 1) { battery_packConfigMultiplexer = (rx_frame.data.u8[0] & (0xff)); //0|8@1+ (1,0) [0|1] "" - battery_moduleType = (rx_frame.data.u8[1] & (0x07)); //8|3@1+ (1,0) [0|4] "" - battery_packMass = (rx_frame.data.u8[2]) + 300; //16|8@1+ (1,300) [342|469] "kg" + battery_moduleType = + (rx_frame.data.u8[1] & + (0x07)); //8|3@1+ (1,0) [0|4] ""//0 "UNKNOWN" 1 "E3_NCT" 2 "E1_NCT" 3 "E3_CT" 4 "E1_CT" 5 "E1_CP" ;//to datalayer_extended + battery_packMass = (rx_frame.data.u8[2]) + 300; //16|8@1+ (1,300) [342|469] "kg" battery_platformMaxBusVoltage = (((rx_frame.data.u8[4] & 0x03) << 8) | (rx_frame.data.u8[3])); //24|10@1+ (0.1,375) [0|0] "V" } if (mux == 0) { - battery_reservedConfig = (rx_frame.data.u8[1] & (0x1F)); //8|5@1+ (1,0) [0|31] "" + battery_reservedConfig = + (rx_frame.data.u8[1] & + (0x1F)); //8|5@1+ (1,0) [0|31] ""//0 "BMS_CONFIG_0" 1 "BMS_CONFIG_1" 10 "BMS_CONFIG_10" 11 "BMS_CONFIG_11" 12 "BMS_CONFIG_12" 13 "BMS_CONFIG_13" 14 "BMS_CONFIG_14" 15 "BMS_CONFIG_15" 16 "BMS_CONFIG_16" 17 "BMS_CONFIG_17" 18 "BMS_CONFIG_18" 19 "BMS_CONFIG_19" 2 "BMS_CONFIG_2" 20 "BMS_CONFIG_20" 21 "BMS_CONFIG_21" 22 "BMS_CONFIG_22" 23 "BMS_CONFIG_23" 24 "BMS_CONFIG_24" 25 "BMS_CONFIG_25" 26 "BMS_CONFIG_26" 27 "BMS_CONFIG_27" 28 "BMS_CONFIG_28" 29 "BMS_CONFIG_29" 3 "BMS_CONFIG_3" 30 "BMS_CONFIG_30" 31 "BMS_CONFIG_31" 4 "BMS_CONFIG_4" 5 "BMS_CONFIG_5" 6 "BMS_CONFIG_6" 7 "BMS_CONFIG_7" 8 "BMS_CONFIG_8" 9 "BMS_CONFIG_9" ; + } + break; + case 0x7AA: //1962 HVP_debugMessage: + mux = (rx_frame.data.u8[0] & (0x0FU)); + //HVP_debugMessageMultiplexer = (rx_frame.data.u8[0] & (0x0FU)); //0|4@1+ (1,0) [0|6] "" + if (mux == 0) { + HVP_gpioPassivePyroDepl = ((rx_frame.data.u8[0] >> 4) & (0x01U)); //: 4|1@1+ (1,0) [0|1] "" Receiver + HVP_gpioPyroIsoEn = ((rx_frame.data.u8[0] >> 5) & (0x01U)); //: 5|1@1+ (1,0) [0|1] "" Receiver + HVP_gpioCpFaultIn = ((rx_frame.data.u8[0] >> 6) & (0x01U)); //: 6|1@1+ (1,0) [0|1] "" Receiver + HVP_gpioPackContPowerEn = ((rx_frame.data.u8[0] >> 7) & (0x01U)); //: 7|1@1+ (1,0) [0|1] "" Receiver + HVP_gpioHvCablesOk = (rx_frame.data.u8[1] & (0x01U)); //: 8|1@1+ (1,0) [0|1] "" Receiver + HVP_gpioHvpSelfEnable = ((rx_frame.data.u8[1] >> 1) & (0x01U)); //: 9|1@1+ (1,0) [0|1] "" Receiver + HVP_gpioLed = ((rx_frame.data.u8[1] >> 2) & (0x01U)); //: 10|1@1+ (1,0) [0|1] "" Receiver + HVP_gpioCrashSignal = ((rx_frame.data.u8[1] >> 3) & (0x01U)); //: 11|1@1+ (1,0) [0|1] "" Receiver + HVP_gpioShuntDataReady = ((rx_frame.data.u8[1] >> 4) & (0x01U)); //: 12|1@1+ (1,0) [0|1] "" Receiver + HVP_gpioFcContPosAux = ((rx_frame.data.u8[1] >> 5) & (0x01U)); //: 13|1@1+ (1,0) [0|1] "" Receiver + HVP_gpioFcContNegAux = ((rx_frame.data.u8[1] >> 6) & (0x01U)); //: 14|1@1+ (1,0) [0|1] "" Receiver + HVP_gpioBmsEout = ((rx_frame.data.u8[1] >> 7) & (0x01U)); //: 15|1@1+ (1,0) [0|1] "" Receiver + HVP_gpioCpFaultOut = (rx_frame.data.u8[2] & (0x01U)); //: 16|1@1+ (1,0) [0|1] "" Receiver + HVP_gpioPyroPor = ((rx_frame.data.u8[2] >> 1) & (0x01U)); //: 17|1@1+ (1,0) [0|1] "" Receiver + HVP_gpioShuntEn = ((rx_frame.data.u8[2] >> 2) & (0x01U)); //: 18|1@1+ (1,0) [0|1] "" Receiver + HVP_gpioHvpVerEn = ((rx_frame.data.u8[2] >> 3) & (0x01U)); //: 19|1@1+ (1,0) [0|1] "" Receiver + HVP_gpioPackCoontPosFlywheel = ((rx_frame.data.u8[2] >> 4) & (0x01U)); //: 20|1@1+ (1,0) [0|1] "" Receiver + HVP_gpioCpLatchEnable = ((rx_frame.data.u8[2] >> 5) & (0x01U)); //: 21|1@1+ (1,0) [0|1] "" Receiver + HVP_gpioPcsEnable = ((rx_frame.data.u8[2] >> 6) & (0x01U)); //: 22|1@1+ (1,0) [0|1] "" Receiver + HVP_gpioPcsDcdcPwmEnable = ((rx_frame.data.u8[2] >> 7) & (0x01U)); //: 23|1@1+ (1,0) [0|1] "" Receiver + HVP_gpioPcsChargePwmEnable = (rx_frame.data.u8[3] & (0x01U)); //: 24|1@1+ (1,0) [0|1] "" Receiver + HVP_gpioFcContPowerEnable = ((rx_frame.data.u8[3] >> 1) & (0x01U)); //: 25|1@1+ (1,0) [0|1] "" Receiver + HVP_gpioHvilEnable = ((rx_frame.data.u8[3] >> 2) & (0x01U)); //: 26|1@1+ (1,0) [0|1] "" Receiver + HVP_gpioSecDrdy = ((rx_frame.data.u8[3] >> 3) & (0x01U)); //: 27|1@1+ (1,0) [0|1] "" Receiver + HVP_hvp1v5Ref = ((rx_frame.data.u8[4] & (0xFFU)) << 4) | + ((rx_frame.data.u8[3] >> 4) & (0x0FU)); //: 28|12@1+ (0.1,0) [0|3] "V" Receiver + HVP_shuntCurrentDebug = ((rx_frame.data.u8[6] & (0xFFU)) << 8) | + (rx_frame.data.u8[5] & (0xFFU)); //: 40|16@1- (0.1,0) [-3276.8|3276.7] "A" Receiver + HVP_packCurrentMia = (rx_frame.data.u8[7] & (0x01U)); //: 56|1@1+ (1,0) [0|1] "" Receiver + HVP_auxCurrentMia = ((rx_frame.data.u8[7] >> 1) & (0x01U)); //: 57|1@1+ (1,0) [0|1] "" Receiver + HVP_currentSenseMia = ((rx_frame.data.u8[7] >> 2) & (0x03U)); //: 58|1@1+ (1,0) [0|1] "" Receiver + HVP_shuntRefVoltageMismatch = ((rx_frame.data.u8[7] >> 3) & (0x01U)); //: 59|1@1+ (1,0) [0|1] "" Receiver + HVP_shuntThermistorMia = ((rx_frame.data.u8[7] >> 4) & (0x01U)); //: 60|1@1+ (1,0) [0|1] "" Receiver + HVP_shuntHwMia = ((rx_frame.data.u8[7] >> 5) & (0x01U)); //: 61|1@1+ (1,0) [0|1] "" Receiver + } + if (mux == 1) { + HVP_dcLinkVoltage = ((rx_frame.data.u8[2] & (0xFFU)) << 8) | + (rx_frame.data.u8[1] & (0xFFU)); //: 8|16@1- (0.1,0) [-3276.8|3276.7] "V" Receiver + HVP_packVoltage = ((rx_frame.data.u8[4] & (0xFFU)) << 8) | + (rx_frame.data.u8[3] & (0xFFU)); //: 24|16@1- (0.1,0) [-3276.8|3276.7] "V" Receiver + HVP_fcLinkVoltage = ((rx_frame.data.u8[6] & (0xFFU)) << 8) | + (rx_frame.data.u8[5] & (0xFFU)); //: 40|16@1- (0.1,0) [-3276.8|3276.7] "V" Receiver + } + if (mux == 2) { + HVP_packContVoltage = ((rx_frame.data.u8[1] & (0xFFU)) << 4) | + ((rx_frame.data.u8[0] >> 4) & (0x0FU)); //: 4|12@1+ (0.1,0) [0|30] "V" Receiver + HVP_packNegativeV = ((rx_frame.data.u8[3] & (0xFFU)) << 8) | + (rx_frame.data.u8[2] & (0xFFU)); //: 16|16@1- (0.1,0) [-550|550] "V" Receiver + HVP_packPositiveV = ((rx_frame.data.u8[5] & (0xFFU)) << 8) | + (rx_frame.data.u8[4] & (0xFFU)); //: 32|16@1- (0.1,0) [-550|550] "V" Receiver + HVP_pyroAnalog = ((rx_frame.data.u8[7] & (0x0FU)) << 8) | + (rx_frame.data.u8[6] & (0xFFU)); //: 48|12@1+ (0.1,0) [0|3] "V" Receiver + } + if (mux == 3) { + HVP_dcLinkNegativeV = ((rx_frame.data.u8[2] & (0xFFU)) << 8) | + (rx_frame.data.u8[1] & (0xFFU)); //: 8|16@1- (0.1,0) [-550|550] "V" Receiver + HVP_dcLinkPositiveV = ((rx_frame.data.u8[4] & (0xFFU)) << 8) | + (rx_frame.data.u8[3] & (0xFFU)); //: 24|16@1- (0.1,0) [-550|550] "V" Receiver + HVP_fcLinkNegativeV = ((rx_frame.data.u8[6] & (0xFFU)) << 8) | + (rx_frame.data.u8[5] & (0xFFU)); //: 40|16@1- (0.1,0) [-550|550] "V" Receiver + } + if (mux == 4) { + HVP_fcContCoilCurrent = ((rx_frame.data.u8[1] & (0xFFU)) << 4) | + ((rx_frame.data.u8[0] >> 4) & (0x0FU)); //: 4|12@1+ (0.1,0) [0|7.5] "A" Receiver + HVP_fcContVoltage = ((rx_frame.data.u8[3] & (0x0FU)) << 8) | + (rx_frame.data.u8[2] & (0xFFU)); //: 16|12@1+ (0.1,0) [0|30] "V" Receiver + HVP_hvilInVoltage = ((rx_frame.data.u8[4] & (0xFFU)) << 4) | + ((rx_frame.data.u8[3] >> 4) & (0x0FU)); //: 28|12@1+ (0.1,0) [0|30] "V" Receiver + HVP_hvilOutVoltage = ((rx_frame.data.u8[6] & (0x0FU)) << 8) | + (rx_frame.data.u8[5] & (0xFFU)); //: 40|12@1+ (0.1,0) [0|30] "V" Receiver + } + if (mux == 5) { + HVP_fcLinkPositiveV = ((rx_frame.data.u8[2] & (0xFFU)) << 8) | + (rx_frame.data.u8[1] & (0xFFU)); //: 8|16@1- (0.1,0) [-550|550] "V" Receiver + HVP_packContCoilCurrent = ((rx_frame.data.u8[4] & (0x0FU)) << 8) | + (rx_frame.data.u8[3] & (0xFFU)); //: 24|12@1+ (0.1,0) [0|7.5] "A" Receiver + HVP_battery12V = ((rx_frame.data.u8[5] & (0xFFU)) << 4) | + ((rx_frame.data.u8[4] >> 4) & (0x0FU)); //: 36|12@1+ (0.1,0) [0|30] "V" Receiver + HVP_shuntRefVoltageDbg = ((rx_frame.data.u8[7] & (0xFFU)) << 8) | + (rx_frame.data.u8[6] & (0xFFU)); //: 48|16@1- (0.001,0) [-32.768|32.767] "V" Receiver + } + if (mux == 6) { + HVP_shuntAuxCurrentDbg = ((rx_frame.data.u8[2] & (0xFFU)) << 8) | + (rx_frame.data.u8[1] & (0xFFU)); //: 8|16@1- (0.1,0) [-3276.8|3276.7] "A" Receiver + HVP_shuntBarTempDbg = ((rx_frame.data.u8[4] & (0xFFU)) << 8) | + (rx_frame.data.u8[3] & (0xFFU)); //: 24|16@1- (0.01,0) [-327.67|327.67] "C" Receiver + HVP_shuntAsicTempDbg = ((rx_frame.data.u8[6] & (0xFFU)) << 8) | + (rx_frame.data.u8[5] & (0xFFU)); //: 40|16@1- (0.01,0) [-327.67|327.67] "C" Receiver + HVP_shuntAuxCurrentStatus = (rx_frame.data.u8[7] & (0x03U)); //: 56|2@1+ (1,0) [0|3] "" Receiver + HVP_shuntBarTempStatus = ((rx_frame.data.u8[7] >> 2) & (0x03U)); //: 58|2@1+ (1,0) [0|3] "" Receiver + HVP_shuntAsicTempStatus = ((rx_frame.data.u8[7] >> 4) & (0x03U)); //: 60|2@1+ (1,0) [0|3] "" Receiver } break; case 0x3aa: //HVP_alertMatrix1 @@ -739,12 +1749,116 @@ void receive_can_battery(CAN_frame rx_frame) { battery_fcCtrCloseFailed = ((rx_frame.data.u8[6] & 0x02) >> 1); battery_shuntThermistorMia = ((rx_frame.data.u8[6] & 0x04) >> 2); break; + case 0x320: //800 BMS_alertMatrix //BMS_alertMatrix 800 BMS_alertMatrix: 8 VEH + mux = (rx_frame.data.u8[0] & (0x0F)); + if (mux == 0) + ; + { //mux0 + battery_BMS_matrixIndex = (rx_frame.data.u8[0] & (0x0F)); // 0|4@1+ (1,0) [0|0] "" X + battery_BMS_a017_SW_Brick_OV = ((rx_frame.data.u8[2] >> 4) & (0x01)); //20|1@1+ (1,0) [0|0] "" X + battery_BMS_a018_SW_Brick_UV = ((rx_frame.data.u8[2] >> 5) & (0x01)); //21|1@1+ (1,0) [0|0] "" X + battery_BMS_a019_SW_Module_OT = ((rx_frame.data.u8[2] >> 6) & (0x01)); //22|1@1+ (1,0) [0|0] "" X + battery_BMS_a021_SW_Dr_Limits_Regulation = (rx_frame.data.u8[3] & (0x01U)); //24|1@1+ (1,0) [0|0] "" X + battery_BMS_a022_SW_Over_Current = ((rx_frame.data.u8[3] >> 1) & (0x01U)); //25|1@1+ (1,0) [0|0] "" X + battery_BMS_a023_SW_Stack_OV = ((rx_frame.data.u8[3] >> 2) & (0x01U)); //26|1@1+ (1,0) [0|0] "" X + battery_BMS_a024_SW_Islanded_Brick = ((rx_frame.data.u8[3] >> 3) & (0x01U)); //27|1@1+ (1,0) [0|0] "" X + battery_BMS_a025_SW_PwrBalance_Anomaly = ((rx_frame.data.u8[3] >> 4) & (0x01U)); //28|1@1+ (1,0) [0|0] "" X + battery_BMS_a026_SW_HFCurrent_Anomaly = ((rx_frame.data.u8[3] >> 5) & (0x01U)); //29|1@1+ (1,0) [0|0] "" X + battery_BMS_a034_SW_Passive_Isolation = ((rx_frame.data.u8[4] >> 5) & (0x01U)); //37|1@1+ (1,0) [0|0] "" X ? + battery_BMS_a035_SW_Isolation = ((rx_frame.data.u8[4] >> 6) & (0x01U)); //38|1@1+ (1,0) [0|0] "" X + battery_BMS_a036_SW_HvpHvilFault = ((rx_frame.data.u8[4] >> 6) & (0x01U)); //39|1@1+ (1,0) [0|0] "" X + battery_BMS_a037_SW_Flood_Port_Open = (rx_frame.data.u8[5] & (0x01U)); //40|1@1+ (1,0) [0|0] "" X + battery_BMS_a039_SW_DC_Link_Over_Voltage = ((rx_frame.data.u8[5] >> 2) & (0x01U)); //42|1@1+ (1,0) [0|0] "" X + battery_BMS_a041_SW_Power_On_Reset = ((rx_frame.data.u8[5] >> 4) & (0x01U)); //44|1@1+ (1,0) [0|0] "" X + battery_BMS_a042_SW_MPU_Error = ((rx_frame.data.u8[5] >> 5) & (0x01U)); //45|1@1+ (1,0) [0|0] "" X + battery_BMS_a043_SW_Watch_Dog_Reset = ((rx_frame.data.u8[5] >> 6) & (0x01U)); //46|1@1+ (1,0) [0|0] "" X + battery_BMS_a044_SW_Assertion = ((rx_frame.data.u8[5] >> 7) & (0x01U)); //47|1@1+ (1,0) [0|0] "" X + battery_BMS_a045_SW_Exception = (rx_frame.data.u8[6] & (0x01U)); //48|1@1+ (1,0) [0|0] "" X + battery_BMS_a046_SW_Task_Stack_Usage = ((rx_frame.data.u8[6] >> 1) & (0x01U)); //49|1@1+ (1,0) [0|0] "" X + battery_BMS_a047_SW_Task_Stack_Overflow = ((rx_frame.data.u8[6] >> 2) & (0x01U)); //50|1@1+ (1,0) [0|0] "" X + battery_BMS_a048_SW_Log_Upload_Request = ((rx_frame.data.u8[6] >> 3) & (0x01U)); //51|1@1+ (1,0) [0|0] "" X + battery_BMS_a050_SW_Brick_Voltage_MIA = ((rx_frame.data.u8[6] >> 5) & (0x01U)); //53|1@1+ (1,0) [0|0] "" X + battery_BMS_a051_SW_HVC_Vref_Bad = ((rx_frame.data.u8[6] >> 6) & (0x01U)); //54|1@1+ (1,0) [0|0] "" X + battery_BMS_a052_SW_PCS_MIA = ((rx_frame.data.u8[6] >> 7) & (0x01U)); //55|1@1+ (1,0) [0|0] "" X + battery_BMS_a053_SW_ThermalModel_Sanity = (rx_frame.data.u8[7] & (0x01U)); //56|1@1+ (1,0) [0|0] "" X + battery_BMS_a054_SW_Ver_Supply_Fault = ((rx_frame.data.u8[7] >> 1) & (0x01U)); //57|1@1+ (1,0) [0|0] "" X + battery_BMS_a059_SW_Pack_Voltage_Sensing = ((rx_frame.data.u8[7] >> 6) & (0x01U)); //62|1@1+ (1,0) [0|0] "" X + battery_BMS_a060_SW_Leakage_Test_Failure = ((rx_frame.data.u8[7] >> 7) & (0x01U)); //63|1@1+ (1,0) [0|0] "" X + } + if (mux == 1) { //mux1 + battery_BMS_a061_robinBrickOverVoltage = ((rx_frame.data.u8[0] >> 4) & (0x01U)); //4|1@1+ (1,0) [0|0] "" X + battery_BMS_a062_SW_BrickV_Imbalance = ((rx_frame.data.u8[0] >> 5) & (0x01U)); //5|1@1+ (1,0) [0|0] "" X + battery_BMS_a063_SW_ChargePort_Fault = ((rx_frame.data.u8[0] >> 6) & (0x01U)); //6|1@1+ (1,0) [0|0] "" X + battery_BMS_a064_SW_SOC_Imbalance = ((rx_frame.data.u8[0] >> 7) & (0x01U)); //7|1@1+ (1,0) [0|0] "" X + battery_BMS_a069_SW_Low_Power = ((rx_frame.data.u8[1] >> 4) & (0x01U)); //12|1@1+ (1,0) [0|0] "" X + battery_BMS_a071_SW_SM_TransCon_Not_Met = ((rx_frame.data.u8[1] >> 6) & (0x01U)); //14|1@1+ (1,0) [0|0] "" X + battery_BMS_a075_SW_Chg_Disable_Failure = ((rx_frame.data.u8[2] >> 2) & (0x01U)); //18|1@1+ (1,0) [0|0] "" X + battery_BMS_a076_SW_Dch_While_Charging = ((rx_frame.data.u8[2] >> 3) & (0x01U)); //19|1@1+ (1,0) [0|0] "" X + battery_BMS_a077_SW_Charger_Regulation = ((rx_frame.data.u8[2] >> 4) & (0x01U)); //20|1@1+ (1,0) [0|0] "" X + battery_BMS_a081_SW_Ctr_Close_Blocked = (rx_frame.data.u8[3] & (0x01U)); //24|1@1+ (1,0) [0|0] "" X + battery_BMS_a082_SW_Ctr_Force_Open = ((rx_frame.data.u8[3] >> 1) & (0x01U)); //25|1@1+ (1,0) [0|0] "" X + battery_BMS_a083_SW_Ctr_Close_Failure = ((rx_frame.data.u8[3] >> 2) & (0x01U)); //26|1@1+ (1,0) [0|0] "" X + battery_BMS_a084_SW_Sleep_Wake_Aborted = ((rx_frame.data.u8[3] >> 3) & (0x01U)); //27|1@1+ (1,0) [0|0] "" X + battery_BMS_a087_SW_Feim_Test_Blocked = ((rx_frame.data.u8[3] >> 6) & (0x01U)); //30|1@1+ (1,0) [0|0] "" X + battery_BMS_a088_SW_VcFront_MIA_InDrive = ((rx_frame.data.u8[3] >> 7) & (0x01U)); //31|1@1+ (1,0) [0|0] "" X + battery_BMS_a089_SW_VcFront_MIA = (rx_frame.data.u8[4] & (0x01U)); //32|1@1+ (1,0) [0|0] "" X + battery_BMS_a090_SW_Gateway_MIA = ((rx_frame.data.u8[4] >> 1) & (0x01U)); //33|1@1+ (1,0) [0|0] "" X + battery_BMS_a091_SW_ChargePort_MIA = ((rx_frame.data.u8[4] >> 2) & (0x01U)); //34|1@1+ (1,0) [0|0] "" X + battery_BMS_a092_SW_ChargePort_Mia_On_Hv = ((rx_frame.data.u8[4] >> 3) & (0x01U)); //35|1@1+ (1,0) [0|0] "" X + battery_BMS_a094_SW_Drive_Inverter_MIA = ((rx_frame.data.u8[4] >> 5) & (0x01U)); //37|1@1+ (1,0) [0|0] "" X + battery_BMS_a099_SW_BMB_Communication = ((rx_frame.data.u8[5] >> 2) & (0x01U)); //42|1@1+ (1,0) [0|0] "" X + battery_BMS_a105_SW_One_Module_Tsense = (rx_frame.data.u8[6] & (0x01U)); //48|1@1+ (1,0) [0|0] "" X + battery_BMS_a106_SW_All_Module_Tsense = ((rx_frame.data.u8[6] >> 1) & (0x01U)); //49|1@1+ (1,0) [0|0] "" X + battery_BMS_a107_SW_Stack_Voltage_MIA = ((rx_frame.data.u8[6] >> 2) & (0x01U)); //50|1@1+ (1,0) [0|0] "" X + } + if (mux == 2) { //mux2 + battery_BMS_a121_SW_NVRAM_Config_Error = ((rx_frame.data.u8[0] >> 4) & (0x01U)); // 4|1@1+ (1,0) [0|0] "" X + battery_BMS_a122_SW_BMS_Therm_Irrational = ((rx_frame.data.u8[0] >> 5) & (0x01U)); //5|1@1+ (1,0) [0|0] "" X + battery_BMS_a123_SW_Internal_Isolation = ((rx_frame.data.u8[0] >> 6) & (0x01U)); //6|1@1+ (1,0) [0|0] "" X + battery_BMS_a127_SW_shunt_SNA = ((rx_frame.data.u8[1] >> 2) & (0x01U)); //10|1@1+ (1,0) [0|0] "" X + battery_BMS_a128_SW_shunt_MIA = ((rx_frame.data.u8[1] >> 3) & (0x01U)); //11|1@1+ (1,0) [0|0] "" X + battery_BMS_a129_SW_VSH_Failure = ((rx_frame.data.u8[1] >> 4) & (0x01U)); //12|1@1+ (1,0) [0|0] "" X + battery_BMS_a130_IO_CAN_Error = ((rx_frame.data.u8[1] >> 5) & (0x01U)); //13|1@1+ (1,0) [0|0] "" X + battery_BMS_a131_Bleed_FET_Failure = ((rx_frame.data.u8[1] >> 6) & (0x01U)); //14|1@1+ (1,0) [0|0] "" X + battery_BMS_a132_HW_BMB_OTP_Uncorrctbl = ((rx_frame.data.u8[1] >> 7) & (0x01U)); //15|1@1+ (1,0) [0|0] "" X + battery_BMS_a134_SW_Delayed_Ctr_Off = ((rx_frame.data.u8[2] >> 1) & (0x01U)); //17|1@1+ (1,0) [0|0] "" X + battery_BMS_a136_SW_Module_OT_Warning = ((rx_frame.data.u8[2] >> 3) & (0x01U)); //19|1@1+ (1,0) [0|0] "" X + battery_BMS_a137_SW_Brick_UV_Warning = ((rx_frame.data.u8[2] >> 4) & (0x01U)); //20|1@1+ (1,0) [0|0] "" X + battery_BMS_a138_SW_Brick_OV_Warning = ((rx_frame.data.u8[2] >> 5) & (0x01U)); //21|1@1+ (1,0) [0|0] "" X + battery_BMS_a139_SW_DC_Link_V_Irrational = ((rx_frame.data.u8[2] >> 6) & (0x01U)); //22|1@1+ (1,0) [0|0] "" X + battery_BMS_a141_SW_BMB_Status_Warning = (rx_frame.data.u8[3] & (0x01U)); //24|1@1+ (1,0) [0|0] "" X + battery_BMS_a144_Hvp_Config_Mismatch = ((rx_frame.data.u8[3] >> 3) & (0x01U)); //27|1@1+ (1,0) [0|0] "" X + battery_BMS_a145_SW_SOC_Change = ((rx_frame.data.u8[3] >> 4) & (0x01U)); //28|1@1+ (1,0) [0|0] "" X + battery_BMS_a146_SW_Brick_Overdischarged = ((rx_frame.data.u8[3] >> 5) & (0x01U)); //29|1@1+ (1,0) [0|0] "" X + battery_BMS_a149_SW_Missing_Config_Block = (rx_frame.data.u8[4] & (0x01U)); //32|1@1+ (1,0) [0|0] "" X + battery_BMS_a151_SW_external_isolation = ((rx_frame.data.u8[4] >> 2) & (0x01U)); //34|1@1+ (1,0) [0|0] "" X + battery_BMS_a156_SW_BMB_Vref_bad = ((rx_frame.data.u8[4] >> 7) & (0x01U)); //39|1@1+ (1,0) [0|0] "" X + battery_BMS_a157_SW_HVP_HVS_Comms = (rx_frame.data.u8[5] & (0x01U)); //40|1@1+ (1,0) [0|0] "" X + battery_BMS_a158_SW_HVP_HVI_Comms = ((rx_frame.data.u8[5] >> 1) & (0x01U)); //41|1@1+ (1,0) [0|0] "" X + battery_BMS_a159_SW_HVP_ECU_Error = ((rx_frame.data.u8[5] >> 2) & (0x01U)); //42|1@1+ (1,0) [0|0] "" X + battery_BMS_a161_SW_DI_Open_Request = ((rx_frame.data.u8[5] >> 4) & (0x01U)); //44|1@1+ (1,0) [0|0] "" X + battery_BMS_a162_SW_No_Power_For_Support = ((rx_frame.data.u8[5] >> 5) & (0x01U)); //45|1@1+ (1,0) [0|0] "" X + battery_BMS_a163_SW_Contactor_Mismatch = ((rx_frame.data.u8[5] >> 6) & (0x01U)); //46|1@1+ (1,0) [0|0] "" X + battery_BMS_a164_SW_Uncontrolled_Regen = ((rx_frame.data.u8[5] >> 7) & (0x01U)); //47|1@1+ (1,0) [0|0] "" X + battery_BMS_a165_SW_Pack_Partial_Weld = (rx_frame.data.u8[6] & (0x01U)); //48|1@1+ (1,0) [0|0] "" X + battery_BMS_a166_SW_Pack_Full_Weld = ((rx_frame.data.u8[6] >> 1) & (0x01U)); //49|1@1+ (1,0) [0|0] "" X + battery_BMS_a167_SW_FC_Partial_Weld = ((rx_frame.data.u8[6] >> 2) & (0x01U)); //50|1@1+ (1,0) [0|0] "" X + battery_BMS_a168_SW_FC_Full_Weld = ((rx_frame.data.u8[6] >> 3) & (0x01U)); //51|1@1+ (1,0) [0|0] "" X + battery_BMS_a169_SW_FC_Pack_Weld = ((rx_frame.data.u8[6] >> 4) & (0x01U)); //52|1@1+ (1,0) [0|0] "" X + battery_BMS_a170_SW_Limp_Mode = ((rx_frame.data.u8[6] >> 5) & (0x01U)); //53|1@1+ (1,0) [0|0] "" X + battery_BMS_a171_SW_Stack_Voltage_Sense = ((rx_frame.data.u8[6] >> 6) & (0x01U)); //54|1@1+ (1,0) [0|0] "" X + battery_BMS_a174_SW_Charge_Failure = ((rx_frame.data.u8[7] >> 1) & (0x01U)); //57|1@1+ (1,0) [0|0] "" X + battery_BMS_a176_SW_GracefulPowerOff = ((rx_frame.data.u8[7] >> 3) & (0x01U)); //59|1@1+ (1,0) [0|0] "" X + battery_BMS_a179_SW_Hvp_12V_Fault = ((rx_frame.data.u8[7] >> 6) & (0x01U)); //62|1@1+ (1,0) [0|0] "" X + battery_BMS_a180_SW_ECU_reset_blocked = ((rx_frame.data.u8[7] >> 7) & (0x01U)); //63|1@1+ (1,0) [0|0] "" X + } + break; default: break; } } -#ifdef DOUBLE_BATTERY +#ifdef DOUBLE_BATTERY //Need to update battery2 void receive_can_battery2(CAN_frame rx_frame) { static uint8_t mux = 0; @@ -779,24 +1893,23 @@ void receive_can_battery2(CAN_frame rx_frame) { if (mux == 2) {} // Additional information needed on this mux, example frame: 02 26 02 20 02 80 00 00 doesn't change // older BMS <2021 without mux - //battery2_nominal_full_pack_energy = //BMS_nominalFullPackEnergy : 0|11@1+ (0.1,0) [0|204.6] "KWh" //((_d[1] & (0x07U)) << 8) | (_d[0] & (0xFFU)); - (((rx_frame.data.u8[1] & 0x07) << 8) | (rx_frame.data.u8[0])); //Example 752 (75.2kWh) - //battery2_nominal_energy_remaining = //BMS_nominalEnergyRemaining : 11|11@1+ (0.1,0) [0|204.6] "KWh" //((_d[2] & (0x3FU)) << 5) | ((_d[1] >> 3) & (0x1FU)); - (((rx_frame.data.u8[2] & 0x3F) << 5) | ((rx_frame.data.u8[1] & 0x1F) >> 3)); //Example 1247 * 0.1 = 124.7kWh - //battery2_expected_energy_remaining = //BMS_expectedEnergyRemaining : 22|11@1+ (0.1,0) [0|204.6] "KWh"// ((_d[4] & (0x01U)) << 10) | ((_d[3] & (0xFFU)) << 2) | ((_d[2] >> 6) & (0x03U)); - (((rx_frame.data.u8[4] & 0x01) << 10) | (rx_frame.data.u8[3] << 2) | - ((rx_frame.data.u8[2] & 0x03) >> 6)); //Example 622 (62.2kWh) - //battery2_ideal_energy_remaining = //BMS_idealEnergyRemaining : 33|11@1+ (0.1,0) [0|204.6] "KWh" //((_d[5] & (0x0FU)) << 7) | ((_d[4] >> 1) & (0x7FU)); - (((rx_frame.data.u8[5] & 0x0F) << 7) | ((rx_frame.data.u8[4] & 0x7F) >> 1)); //Example 311 * 0.1 = 31.1kWh - //battery2_energy_to_charge_complete = // BMS_energyToChargeComplete : 44|11@1+ (0.1,0) [0|204.6] "KWh"// ((_d[6] & (0x7FU)) << 4) | ((_d[5] >> 4) & (0x0FU)); - (((rx_frame.data.u8[6] & 0x7F) << 4) | ((rx_frame.data.u8[5] & 0x0F) << 4)); //Example 147 * 0.1 = 14.7kWh - //battery2_energy_buffer = //BMS_energyBuffer : 55|8@1+ (0.1,0) [0|25.4] "KWh"// ((_d[7] & (0x7FU)) << 1) | ((_d[6] >> 7) & (0x01U)); - (((rx_frame.data.u8[7] & 0x7F) << 1) | ((rx_frame.data.u8[6] & 0x01) >> 7)); //Example 1 * 0.1 = 0 - //battery2_full_charge_complete = //BMS_fullChargeComplete : 63|1@1+ (1,0) [0|1] ""//((_d[7] >> 7) & (0x01U)); - ((rx_frame.data.u8[7] & 0x01) >> 7); + battery2_nominal_full_pack_energy = //BMS_nominalFullPackEnergy : 0|11@1+ (0.1,0) [0|204.6] "KWh" //((_d[1] & (0x07U)) << 8) | (_d[0] & (0xFFU)); + (((rx_frame.data.u8[1] & 0x07) << 8) | (rx_frame.data.u8[0])); //Example 752 (75.2kWh) + battery2_nominal_energy_remaining = //BMS_nominalEnergyRemaining : 11|11@1+ (0.1,0) [0|204.6] "KWh" //((_d[2] & (0x3FU)) << 5) | ((_d[1] >> 3) & (0x1FU)); + (((rx_frame.data.u8[2] & 0x3F) << 5) | ((rx_frame.data.u8[1] & 0x1F) >> 3)); //Example 1247 * 0.1 = 124.7kWh + battery2_expected_energy_remaining = //BMS_expectedEnergyRemaining : 22|11@1+ (0.1,0) [0|204.6] "KWh"// ((_d[4] & (0x01U)) << 10) | ((_d[3] & (0xFFU)) << 2) | ((_d[2] >> 6) & (0x03U)); + (((rx_frame.data.u8[4] & 0x01) << 10) | (rx_frame.data.u8[3] << 2) | + ((rx_frame.data.u8[2] & 0x03) >> 6)); //Example 622 (62.2kWh) + battery2_ideal_energy_remaining = //BMS_idealEnergyRemaining : 33|11@1+ (0.1,0) [0|204.6] "KWh" //((_d[5] & (0x0FU)) << 7) | ((_d[4] >> 1) & (0x7FU)); + (((rx_frame.data.u8[5] & 0x0F) << 7) | ((rx_frame.data.u8[4] & 0x7F) >> 1)); //Example 311 * 0.1 = 31.1kWh + battery2_energy_to_charge_complete = // BMS_energyToChargeComplete : 44|11@1+ (0.1,0) [0|204.6] "KWh"// ((_d[6] & (0x7FU)) << 4) | ((_d[5] >> 4) & (0x0FU)); + (((rx_frame.data.u8[6] & 0x7F) << 4) | ((rx_frame.data.u8[5] & 0x0F) << 4)); //Example 147 * 0.1 = 14.7kWh + battery2_energy_buffer = //BMS_energyBuffer : 55|8@1+ (0.1,0) [0|25.4] "KWh"// ((_d[7] & (0x7FU)) << 1) | ((_d[6] >> 7) & (0x01U)); + (((rx_frame.data.u8[7] & 0x7F) << 1) | ((rx_frame.data.u8[6] & 0x01) >> 7)); //Example 1 * 0.1 = 0 + battery2_full_charge_complete = //BMS_fullChargeComplete : 63|1@1+ (1,0) [0|1] ""//((_d[7] >> 7) & (0x01U)); + ((rx_frame.data.u8[7] & 0x01) >> 7); break; - case 0x20A: - //Contactor state + case 0x20A: //522 HVP_contactorState: battery2_packContNegativeState = (rx_frame.data.u8[0] & 0x07); battery2_packContPositiveState = (rx_frame.data.u8[0] & 0x38) >> 3; battery2_contactor = (rx_frame.data.u8[1] & 0x0F); @@ -804,22 +1917,90 @@ void receive_can_battery2(CAN_frame rx_frame) { battery2_packCtrsClosingAllowed = (rx_frame.data.u8[4] & 0x08) >> 3; battery2_pyroTestInProgress = (rx_frame.data.u8[4] & 0x20) >> 5; battery2_hvil_status = (rx_frame.data.u8[5] & 0x0F); - //HVP_packCtrsOpenNowRequested : 33|1@1+ (1,0) [0|1] "" - //HVP_packCtrsOpenRequested : 34|1@1+ (1,0) [0|1] "" - //HVP_packCtrsRequestStatus : 30|2@1+ (1,0) [0|2] "" - //HVP_packCtrsResetRequestRequired : 32|1@1+ (1,0) [0|1] "" - //HVP_dcLinkAllowedToEnergize : 36|1@1+ (1,0) [0|1] "" Receiver - //HVP_fcContNegativeAuxOpen : 7|1@1+ (1,0) [0|1] "" Receiver - //HVP_fcContNegativeState : 12|3@1+ (1,0) [0|7] "" Receiver - //HVP_fcContPositiveAuxOpen : 6|1@1+ (1,0) [0|1] "" Receiver - //HVP_fcContPositiveState : 16|3@1+ (1,0) [0|7] "" Receiver - //HVP_fcContactorSetState : 19|4@1+ (1,0) [0|9] "" Receiver - //HVP_fcCtrsClosingAllowed : 29|1@1+ (1,0) [0|1] "" Receiver - //HVP_fcCtrsOpenNowRequested : 27|1@1+ (1,0) [0|1] "" Receiver - //HVP_fcCtrsOpenRequested : 28|1@1+ (1,0) [0|1] "" Receiver - //HVP_fcCtrsRequestStatus : 24|2@1+ (1,0) [0|2] "" Receiver - //HVP_fcCtrsResetRequestRequired : 26|1@1+ (1,0) [0|1] "" Receiver - //HVP_fcLinkAllowedToEnergize : 44|2@1+ (1,0) [0|2] "" Receiver + battery2_packCtrsOpenNowRequested = + ((rx_frame.data.u8[4] >> 1) & (0x01U)); //33|1@1+ (1,0) [0|1] //to datalayer_extended + battery2_packCtrsOpenRequested = + ((rx_frame.data.u8[4] >> 2) & (0x01U)); //34|1@1+ (1,0) [0|1] //to datalayer_extended + battery2_packCtrsRequestStatus = + ((rx_frame.data.u8[3] >> 6) & (0x03U)); //30|2@1+ (1,0) [0|2] //to datalayer_extended + battery2_packCtrsResetRequestRequired = + (rx_frame.data.u8[4] & (0x01U)); //32|1@1+ (1,0) [0|1] //to datalayer_extended + battery2_dcLinkAllowedToEnergize = + ((rx_frame.data.u8[4] >> 4) & (0x01U)); //36|1@1+ (1,0) [0|1] //to datalayer_extended + battery2_fcContNegativeAuxOpen = ((rx_frame.data.u8[0] >> 7) & (0x01U)); //7|1@1+ (1,0) [0|1] "" Receiver + battery2_fcContNegativeState = ((rx_frame.data.u8[1] >> 4) & (0x07U)); //12|3@1+ (1,0) [0|7] "" Receiver + battery2_fcContPositiveAuxOpen = ((rx_frame.data.u8[0] >> 6) & (0x01U)); //6|1@1+ (1,0) [0|1] "" Receiver + battery2_fcContPositiveState = (rx_frame.data.u8[2] & (0x07U)); //16|3@1+ (1,0) [0|7] "" Receiver + battery2_fcContactorSetState = ((rx_frame.data.u8[2] >> 3) & (0x0FU)); //19|4@1+ (1,0) [0|9] "" Receiver + battery2_fcCtrsClosingAllowed = ((rx_frame.data.u8[3] >> 5) & (0x01U)); //29|1@1+ (1,0) [0|1] "" Receiver + battery2_fcCtrsOpenNowRequested = ((rx_frame.data.u8[3] >> 3) & (0x01U)); //27|1@1+ (1,0) [0|1] "" Receiver + battery2_fcCtrsOpenRequested = ((rx_frame.data.u8[3] >> 4) & (0x01U)); //28|1@1+ (1,0) [0|1] "" Receiver + battery2_fcCtrsRequestStatus = (rx_frame.data.u8[3] & (0x03U)); //24|2@1+ (1,0) [0|2] "" Receiver + battery2_fcCtrsResetRequestRequired = ((rx_frame.data.u8[3] >> 2) & (0x01U)); //26|1@1+ (1,0) [0|1] "" Receiver + battery2_fcLinkAllowedToEnergize = ((rx_frame.data.u8[5] >> 4) & (0x03U)); //44|2@1+ (1,0) [0|2] "" Receiver + break; + case 0x212: //530 BMS_status: 8 + battery2_BMS_hvacPowerRequest = (rx_frame.data.u8[0] & (0x01U)); + battery2_BMS_notEnoughPowerForDrive = ((rx_frame.data.u8[0] >> 1) & (0x01U)); + battery2_BMS_notEnoughPowerForSupport = ((rx_frame.data.u8[0] >> 2) & (0x01U)); + battery2_BMS_preconditionAllowed = ((rx_frame.data.u8[0] >> 3) & (0x01U)); + battery2_BMS_updateAllowed = ((rx_frame.data.u8[0] >> 4) & (0x01U)); + battery2_BMS_activeHeatingWorthwhile = ((rx_frame.data.u8[0] >> 5) & (0x01U)); + battery2_BMS_cpMiaOnHvs = ((rx_frame.data.u8[0] >> 6) & (0x01U)); + battery2_BMS_contactorState = + (rx_frame.data.u8[1] & + (0x07U)); //0 "SNA" 1 "OPEN" 2 "OPENING" 3 "CLOSING" 4 "CLOSED" 5 "WELDED" 6 "BLOCKED" ; + battery2_BMS_state = + ((rx_frame.data.u8[1] >> 3) & + (0x0FU)); //0 "STANDBY" 1 "DRIVE" 2 "SUPPORT" 3 "CHARGE" 4 "FEIM" 5 "CLEAR_FAULT" 6 "FAULT" 7 "WELD" 8 "TEST" 9 "SNA" ; + battery2_BMS_hvState = + (rx_frame.data.u8[2] & + (0x07U)); //0 "DOWN" 1 "COMING_UP" 2 "GOING_DOWN" 3 "UP_FOR_DRIVE" 4 "UP_FOR_CHARGE" 5 "UP_FOR_DC_CHARGE" 6 "UP" ; + battery2_BMS_isolationResistance = + ((rx_frame.data.u8[3] & (0x1FU)) << 5) | + ((rx_frame.data.u8[2] >> 3) & (0x1FU)); //19|10@1+ (10,0) [0|0] "kOhm"/to datalayer_extended + battery2_BMS_chargeRequest = ((rx_frame.data.u8[3] >> 5) & (0x01U)); + battery2_BMS_keepWarmRequest = ((rx_frame.data.u8[3] >> 6) & (0x01U)); + battery2_BMS_uiChargeStatus = + (rx_frame.data.u8[4] & + (0x07U)); // 0 "DISCONNECTED" 1 "NO_POWER" 2 "ABOUT_TO_CHARGE" 3 "CHARGING" 4 "CHARGE_COMPLETE" 5 "CHARGE_STOPPED" ; + battery2_BMS_diLimpRequest = ((rx_frame.data.u8[4] >> 3) & (0x01U)); + battery2_BMS_okToShipByAir = ((rx_frame.data.u8[4] >> 4) & (0x01U)); + battery2_BMS_okToShipByLand = ((rx_frame.data.u8[4] >> 5) & (0x01U)); + battery2_BMS_chgPowerAvailable = ((rx_frame.data.u8[6] & (0x01U)) << 10) | + ((rx_frame.data.u8[5] & (0xFFU)) << 2) | + ((rx_frame.data.u8[4] >> 6) & (0x03U)); //38|11@1+ (0.125,0) [0|0] "kW" + battery2_BMS_chargeRetryCount = ((rx_frame.data.u8[6] >> 1) & (0x0FU)); + battery2_BMS_pcsPwmEnabled = ((rx_frame.data.u8[6] >> 5) & (0x01U)); + battery2_BMS_ecuLogUploadRequest = ((rx_frame.data.u8[6] >> 6) & (0x03U)); + battery2_BMS_minPackTemperature = (rx_frame.data.u8[7] & (0xFFU)); //56|8@1+ (0.5,-40) [0|0] "DegC + break; + case 0x224: //548 PCS_dcdcStatus: + battery2_PCS_dcdcPrechargeStatus = (rx_frame.data.u8[0] & (0x03U)); //0 "IDLE" 1 "ACTIVE" 2 "FAULTED" ; + battery2_PCS_dcdc12VSupportStatus = ((rx_frame.data.u8[0] >> 2) & (0x03U)); //0 "IDLE" 1 "ACTIVE" 2 "FAULTED" + battery2_PCS_dcdcHvBusDischargeStatus = ((rx_frame.data.u8[0] >> 4) & (0x03U)); //0 "IDLE" 1 "ACTIVE" 2 "FAULTED" + battery2_PCS_dcdcMainState = + ((rx_frame.data.u8[1] & (0x03U)) << 2) | + ((rx_frame.data.u8[0] >> 6) & + (0x03U)); //0 "STANDBY" 1 "12V_SUPPORT_ACTIVE" 2 "PRECHARGE_STARTUP" 3 "PRECHARGE_ACTIVE" 4 "DIS_HVBUS_ACTIVE" 5 "SHUTDOWN" 6 "FAULTED" ; + battery2_PCS_dcdcSubState = + ((rx_frame.data.u8[1] >> 2) & + (0x1FU)); //0 "PWR_UP_INIT" 1 "STANDBY" 2 "12V_SUPPORT_ACTIVE" 3 "DIS_HVBUS" 4 "PCHG_FAST_DIS_HVBUS" 5 "PCHG_SLOW_DIS_HVBUS" 6 "PCHG_DWELL_CHARGE" 7 "PCHG_DWELL_WAIT" 8 "PCHG_DI_RECOVERY_WAIT" 9 "PCHG_ACTIVE" 10 "PCHG_FLT_FAST_DIS_HVBUS" 11 "SHUTDOWN" 12 "12V_SUPPORT_FAULTED" 13 "DIS_HVBUS_FAULTED" 14 "PCHG_FAULTED" 15 "CLEAR_FAULTS" 16 "FAULTED" 17 "NUM" ; + battery2_PCS_dcdcFaulted = ((rx_frame.data.u8[1] >> 7) & (0x01U)); + battery2_PCS_dcdcOutputIsLimited = ((rx_frame.data.u8[3] >> 4) & (0x01U)); + battery2_PCS_dcdcMaxOutputCurrentAllowed = ((rx_frame.data.u8[5] & (0x01U)) << 11) | + ((rx_frame.data.u8[4] & (0xFFU)) << 3) | + ((rx_frame.data.u8[3] >> 5) & (0x07U)); //29|12@1+ (0.1,0) [0|0] "A" + battery2_PCS_dcdcPrechargeRtyCnt = ((rx_frame.data.u8[5] >> 1) & (0x07U)); + battery2_PCS_dcdc12VSupportRtyCnt = ((rx_frame.data.u8[5] >> 4) & (0x0FU)); + battery2_PCS_dcdcDischargeRtyCnt = (rx_frame.data.u8[6] & (0x0FU)); + battery2_PCS_dcdcPwmEnableLine = ((rx_frame.data.u8[6] >> 4) & (0x01U)); + battery2_PCS_dcdcSupportingFixedLvTarget = ((rx_frame.data.u8[6] >> 5) & (0x01U)); + battery2_PCS_ecuLogUploadRequest = ((rx_frame.data.u8[6] >> 6) & (0x03U)); + battery2_PCS_dcdcPrechargeRestartCnt = (rx_frame.data.u8[7] & (0x07U)); + battery2_PCS_dcdcInitialPrechargeSubState = + ((rx_frame.data.u8[7] >> 3) & + (0x1FU)); //0 "PWR_UP_INIT" 1 "STANDBY" 2 "12V_SUPPORT_ACTIVE" 3 "DIS_HVBUS" 4 "PCHG_FAST_DIS_HVBUS" 5 "PCHG_SLOW_DIS_HVBUS" 6 "PCHG_DWELL_CHARGE" 7 "PCHG_DWELL_WAIT" 8 "PCHG_DI_RECOVERY_WAIT" 9 "PCHG_ACTIVE" 10 "PCHG_FLT_FAST_DIS_HVBUS" 11 "SHUTDOWN" 12 "12V_SUPPORT_FAULTED" 13 "DIS_HVBUS_FAULTED" 14 "PCHG_FAULTED" 15 "CLEAR_FAULTS" 16 "FAULTED" 17 "NUM" ; break; case 0x252: //Limits @@ -842,10 +2023,8 @@ void receive_can_battery2(CAN_frame rx_frame) { if (battery2_charge_time_remaining == 4095) { battery2_charge_time_remaining = 0; } - break; - case 0x3D2: - // total charge/discharge kwh + case 0x3D2: // total charge/discharge kwh battery2_total_discharge = ((rx_frame.data.u8[3] << 24) | (rx_frame.data.u8[2] << 16) | (rx_frame.data.u8[1] << 8) | rx_frame.data.u8[0]) * 0.001; @@ -853,8 +2032,7 @@ void receive_can_battery2(CAN_frame rx_frame) { rx_frame.data.u8[4]) * 0.001; break; - case 0x332: - //min/max hist values + case 0x332: //min/max hist values //BattBrickMinMax: mux = (rx_frame.data.u8[0] & 0x03); if (mux == 1) //Cell voltages @@ -865,14 +2043,117 @@ void receive_can_battery2(CAN_frame rx_frame) { temp = ((rx_frame.data.u8[3] << 8) | rx_frame.data.u8[2]); temp = (temp & 0xFFF); battery2_cell_min_v = temp * 2; - battery2_max_vno = 1 + (rx_frame.data.u8[4] & 0x7F); //This cell has highest voltage - battery2_min_vno = 1 + (rx_frame.data.u8[5] & 0x7F); //This cell has lowest voltage + //BattBrickVoltageMax m1 : 2|12@1+ (0.002,0) [0|0] "V" Receiver ((_d[1] & (0x3FU)) << 6) | ((_d[0] >> 2) & (0x3FU)); + battery2_BrickVoltageMax = + ((rx_frame.data.u8[1] & (0x3F)) << 6) | ((rx_frame.data.u8[0] >> 2) & (0x3F)); //to datalayer_extended + //BattBrickVoltageMin m1 : 16|12@1+ (0.002,0) [0|0] "V" Receiver ((_d[3] & (0x0FU)) << 8) | (_d[2] & (0xFFU)); + battery2_BrickVoltageMin = + ((rx_frame.data.u8[3] & (0x0F)) << 8) | (rx_frame.data.u8[2] & (0xFF)); //to datalayer_extended + //BattBrickVoltageMaxNum m1 : 32|7@1+ (1,1) [0|0] "" Receiver + battery2_BrickVoltageMaxNum = 1 + (rx_frame.data.u8[4] & 0x7F); //This cell has highest voltage + battery2_BrickVoltageMinNum = 1 + (rx_frame.data.u8[5] & 0x7F); //This cell has lowest voltage } if (mux == 0) //Temperature sensors { battery2_max_temp = (rx_frame.data.u8[2] * 5) - 400; //Temperature values have 40.0*C offset, 0.5*C /bit battery2_min_temp = (rx_frame.data.u8[3] * 5) - 400; //Multiply by 5 and remove offset to get C+1 (0x61*5=485-400=8.5*C) + //BattBrickTempMaxNum m0 : 2|4@1+ (1,0) [0|0] "" ((_d[0] >> 2) & (0x0FU)); + battery2_BrickTempMaxNum = ((rx_frame.data.u8[0] >> 2) & (0x0F)); //to datalayer_extended + //BattBrickTempMinNum m0 : 8|4@1+ (1,0) [0|0] "" (_d[1] & (0x0FU)); + battery2_BrickTempMinNum = (rx_frame.data.u8[1] & (0x0F)); //to datalayer_extended + //BattBrickModelTMax m0 : 32|8@1+ (0.5,-40) [0|0] "C" (_d[4] & (0xFFU)); + battery2_BrickModelTMax = (rx_frame.data.u8[4] & (0xFFU)); //to datalayer_extended + //BattBrickModelTMin m0 : 40|8@1+ (0.5,-40) [0|0] "C" (_d[5] & (0xFFU)); + battery2_BrickModelTMin = (rx_frame.data.u8[5] & (0xFFU)); //to datalayer_extended + } + break; + case 0x312: // 786 BMS_thermalStatus + BMS2_powerDissipation = + ((rx_frame.data.u8[1] & (0x03U)) << 8) | (rx_frame.data.u8[0] & (0xFFU)); //0|10@1+ (0.02,0) [0|0] "kW" + BMS2_flowRequest = ((rx_frame.data.u8[2] & (0x01U)) << 6) | + ((rx_frame.data.u8[1] >> 2) & (0x3FU)); //10|7@1+ (0.3,0) [0|0] "LPM" + BMS2_inletActiveCoolTargetT = ((rx_frame.data.u8[3] & (0x03U)) << 7) | + ((rx_frame.data.u8[2] >> 1) & (0x7FU)); //17|9@1+ (0.25,-25) [0|0] "DegC" + BMS2_inletPassiveTargetT = ((rx_frame.data.u8[4] & (0x07U)) << 6) | + ((rx_frame.data.u8[3] >> 2) & (0x3FU)); //26|9@1+ (0.25,-25) [0|0] "DegC" X + BMS2_inletActiveHeatTargetT = ((rx_frame.data.u8[5] & (0x0FU)) << 5) | + ((rx_frame.data.u8[4] >> 3) & (0x1FU)); //35|9@1+ (0.25,-25) [0|0] "DegC" + BMS2_packTMin = ((rx_frame.data.u8[6] & (0x1FU)) << 4) | + ((rx_frame.data.u8[5] >> 4) & (0x0FU)); //44|9@1+ (0.25,-25) [-25|100] "DegC" + BMS2_packTMax = ((rx_frame.data.u8[7] & (0x3FU)) << 3) | + ((rx_frame.data.u8[6] >> 5) & (0x07U)); //53|9@1+ (0.25,-25) [-25|100] "DegC" + BMS2_pcsNoFlowRequest = ((rx_frame.data.u8[7] >> 6) & (0x01U)); // 62|1@1+ (1,0) [0|0] "" + BMS2_noFlowRequest = ((rx_frame.data.u8[7] >> 7) & (0x01U)); //63|1@1+ (1,0) [0|0] "" + break; + case 0x2A4: //676 PCS_thermalStatus + PCS2_chgPhATemp = + ((rx_frame.data.u8[1] & (0x07U)) << 8) | (rx_frame.data.u8[0] & (0xFFU)); //0|11@1- (0.1,40) [0|0] "C + PCS2_chgPhBTemp = + ((rx_frame.data.u8[2] & (0x3FU)) << 5) | ((rx_frame.data.u8[1] >> 3) & (0x1FU)); //11|11@1- (0.1,40) [0|0] "C + PCS2_chgPhCTemp = + ((rx_frame.data.u8[4] & (0x07U)) << 8) | (rx_frame.data.u8[3] & (0xFFU)); //24|11@1- (0.1,40) [0|0] "C" + PCS2_dcdcTemp = ((rx_frame.data.u8[5] & (0x3FU)) << 5) | + ((rx_frame.data.u8[4] >> 3) & (0x1FU)); //35|11@1- (0.1,40) [0|0] "C" + PCS2_ambientTemp = + ((rx_frame.data.u8[7] & (0x07U)) << 8) | (rx_frame.data.u8[6] & (0xFFU)); //48|11@1- (0.1,40) [0|0] "C" + break; + case 0x2C4: // 708 PCS_logging: not all frames are listed, just ones relating to dcdc + mux = (rx_frame.data.u8[0] & (0x1FU)); + //PCS_logMessageSelect = (rx_frame.data.u8[0] & (0x1FU)); //0|5@1+ (1,0) [0|0] "" + if (mux == 6) { + PCS2_dcdcMaxLvOutputCurrent = ((rx_frame.data.u8[4] & (0xFFU)) << 4) | + ((rx_frame.data.u8[3] >> 4) & (0x0FU)); //m6 : 28|12@1+ (0.1,0) [0|0] "A" X + PCS2_dcdcCurrentLimit = ((rx_frame.data.u8[6] & (0x0FU)) << 8) | + (rx_frame.data.u8[5] & (0xFFU)); //m6 : 40|12@1+ (0.1,0) [0|0] "A" X + PCS2_dcdcLvOutputCurrentTempLimit = + ((rx_frame.data.u8[7] & (0xFFU)) << 4) | + ((rx_frame.data.u8[6] >> 4) & (0x0FU)); //m6 : 52|12@1+ (0.1,0) [0|0] "A" X + } + if (mux == 7) { + PCS2_dcdcUnifiedCommand = ((rx_frame.data.u8[1] & (0x7FU)) << 3) | + ((rx_frame.data.u8[0] >> 5) & (0x07U)); //m7 : 5|10@1+ (0.001,0) [0|0] "1" X + PCS2_dcdcCLAControllerOutput = ((rx_frame.data.u8[3] & (0x03U)) << 8) | + (rx_frame.data.u8[2] & (0xFFU)); //m7 : 16|10@1+ (0.001,0) [0|0] "1" X + PCS2_dcdcTankVoltage = ((rx_frame.data.u8[4] & (0x1FU)) << 6) | + ((rx_frame.data.u8[3] >> 2) & (0x3FU)); //m7 : 26|11@1- (1,0) [0|0] "V" X + PCS2_dcdcTankVoltageTarget = ((rx_frame.data.u8[5] & (0x7FU)) << 3) | + ((rx_frame.data.u8[4] >> 5) & (0x07U)); // m7 : 37|10@1+ (1,0) [0|0] "V" X + PCS2_dcdcClaCurrentFreq = ((rx_frame.data.u8[7] & (0x0FU)) << 8) | + (rx_frame.data.u8[6] & (0xFFU)); //P m7 : 48|12@1+ (0.0976563,0) [0|0] "kHz" X + } + if (mux == 8) { + PCS2_dcdcTCommMeasured = ((rx_frame.data.u8[2] & (0xFFU)) << 8) | + (rx_frame.data.u8[1] & (0xFFU)); // m8 : 8|16@1- (0.00195313,0) [0|0] "us" X + PCS2_dcdcShortTimeUs = ((rx_frame.data.u8[4] & (0xFFU)) << 8) | + (rx_frame.data.u8[3] & (0xFFU)); // m8 : 24|16@1+ (0.000488281,0) [0|0] "us" X + PCS2_dcdcHalfPeriodUs = ((rx_frame.data.u8[6] & (0xFFU)) << 8) | + (rx_frame.data.u8[5] & (0xFFU)); // m8 : 40|16@1+ (0.000488281,0) [0|0] "us" X + } + if (mux == 18) { + PCS2_dcdcIntervalMaxFrequency = ((rx_frame.data.u8[2] & (0x0FU)) << 8) | + (rx_frame.data.u8[1] & (0xFFU)); // m18 : 8|12@1+ (1,0) [0|0] "kHz" X + PCS2_dcdcIntervalMaxHvBusVolt = ((rx_frame.data.u8[4] & (0x1FU)) << 8) | + (rx_frame.data.u8[3] & (0xFFU)); //m18 : 24|13@1+ (0.1,0) [0|0] "V" X + PCS2_dcdcIntervalMaxLvBusVolt = ((rx_frame.data.u8[5] & (0x3FU)) << 3) | + ((rx_frame.data.u8[4] >> 5) & (0x07U)); // m18 : 37|9@1+ (0.1,0) [0|0] "V" X + PCS2_dcdcIntervalMaxLvOutputCurr = ((rx_frame.data.u8[7] & (0x0FU)) << 8) | + (rx_frame.data.u8[6] & (0xFFU)); //m18 : 48|12@1+ (1,0) [0|0] "A" X + } + if (mux == 19) { + PCS2_dcdcIntervalMinFrequency = ((rx_frame.data.u8[2] & (0x0FU)) << 8) | + (rx_frame.data.u8[1] & (0xFFU)); //m19 : 8|12@1+ (1,0) [0|0] "kHz" X + PCS2_dcdcIntervalMinHvBusVolt = ((rx_frame.data.u8[4] & (0x1FU)) << 8) | + (rx_frame.data.u8[3] & (0xFFU)); //m19 : 24|13@1+ (0.1,0) [0|0] "V" X + PCS2_dcdcIntervalMinLvBusVolt = ((rx_frame.data.u8[5] & (0x3FU)) << 3) | + ((rx_frame.data.u8[4] >> 5) & (0x07U)); //m19 : 37|9@1+ (0.1,0) [0|0] "V" X + PCS2_dcdcIntervalMinLvOutputCurr = ((rx_frame.data.u8[7] & (0x0FU)) << 8) | + (rx_frame.data.u8[6] & (0xFFU)); // m19 : 48|12@1+ (1,0) [0|0] "A" X + } + if (mux == 22) { + PCS2_dcdc12vSupportLifetimekWh = ((rx_frame.data.u8[3] & (0xFFU)) << 16) | + ((rx_frame.data.u8[2] & (0xFFU)) << 8) | + (rx_frame.data.u8[1] & (0xFFU)); // m22 : 8|24@1+ (0.01,0) [0|0] "kWh" X } break; case 0x401: // Cell stats @@ -943,6 +2224,104 @@ void receive_can_battery2(CAN_frame rx_frame) { battery2_reservedConfig = (rx_frame.data.u8[1] & (0x1F)); } break; + case 0x7AA: //1962 HVP_debugMessage: + mux = (rx_frame.data.u8[0] & (0x0FU)); + //HVP_debugMessageMultiplexer = (rx_frame.data.u8[0] & (0x0FU)); //0|4@1+ (1,0) [0|6] "" + if (mux == 0) { + HVP2_gpioPassivePyroDepl = ((rx_frame.data.u8[0] >> 4) & (0x01U)); //: 4|1@1+ (1,0) [0|1] "" Receiver + HVP2_gpioPyroIsoEn = ((rx_frame.data.u8[0] >> 5) & (0x01U)); //: 5|1@1+ (1,0) [0|1] "" Receiver + HVP2_gpioCpFaultIn = ((rx_frame.data.u8[0] >> 6) & (0x01U)); //: 6|1@1+ (1,0) [0|1] "" Receiver + HVP2_gpioPackContPowerEn = ((rx_frame.data.u8[0] >> 7) & (0x01U)); //: 7|1@1+ (1,0) [0|1] "" Receiver + HVP2_gpioHvCablesOk = (rx_frame.data.u8[1] & (0x01U)); //: 8|1@1+ (1,0) [0|1] "" Receiver + HVP2_gpioHvpSelfEnable = ((rx_frame.data.u8[1] >> 1) & (0x01U)); //: 9|1@1+ (1,0) [0|1] "" Receiver + HVP2_gpioLed = ((rx_frame.data.u8[1] >> 2) & (0x01U)); //: 10|1@1+ (1,0) [0|1] "" Receiver + HVP2_gpioCrashSignal = ((rx_frame.data.u8[1] >> 3) & (0x01U)); //: 11|1@1+ (1,0) [0|1] "" Receiver + HVP2_gpioShuntDataReady = ((rx_frame.data.u8[1] >> 4) & (0x01U)); //: 12|1@1+ (1,0) [0|1] "" Receiver + HVP2_gpioFcContPosAux = ((rx_frame.data.u8[1] >> 5) & (0x01U)); //: 13|1@1+ (1,0) [0|1] "" Receiver + HVP2_gpioFcContNegAux = ((rx_frame.data.u8[1] >> 6) & (0x01U)); //: 14|1@1+ (1,0) [0|1] "" Receiver + HVP2_gpioBmsEout = ((rx_frame.data.u8[1] >> 7) & (0x01U)); //: 15|1@1+ (1,0) [0|1] "" Receiver + HVP2_gpioCpFaultOut = (rx_frame.data.u8[2] & (0x01U)); //: 16|1@1+ (1,0) [0|1] "" Receiver + HVP2_gpioPyroPor = ((rx_frame.data.u8[2] >> 1) & (0x01U)); //: 17|1@1+ (1,0) [0|1] "" Receiver + HVP2_gpioShuntEn = ((rx_frame.data.u8[2] >> 2) & (0x01U)); //: 18|1@1+ (1,0) [0|1] "" Receiver + HVP2_gpioHvpVerEn = ((rx_frame.data.u8[2] >> 3) & (0x01U)); //: 19|1@1+ (1,0) [0|1] "" Receiver + HVP2_gpioPackCoontPosFlywheel = ((rx_frame.data.u8[2] >> 4) & (0x01U)); //: 20|1@1+ (1,0) [0|1] "" Receiver + HVP2_gpioCpLatchEnable = ((rx_frame.data.u8[2] >> 5) & (0x01U)); //: 21|1@1+ (1,0) [0|1] "" Receiver + HVP2_gpioPcsEnable = ((rx_frame.data.u8[2] >> 6) & (0x01U)); //: 22|1@1+ (1,0) [0|1] "" Receiver + HVP2_gpioPcsDcdcPwmEnable = ((rx_frame.data.u8[2] >> 7) & (0x01U)); //: 23|1@1+ (1,0) [0|1] "" Receiver + HVP2_gpioPcsChargePwmEnable = (rx_frame.data.u8[3] & (0x01U)); //: 24|1@1+ (1,0) [0|1] "" Receiver + HVP2_gpioFcContPowerEnable = ((rx_frame.data.u8[3] >> 1) & (0x01U)); //: 25|1@1+ (1,0) [0|1] "" Receiver + HVP2_gpioHvilEnable = ((rx_frame.data.u8[3] >> 2) & (0x01U)); //: 26|1@1+ (1,0) [0|1] "" Receiver + HVP2_gpioSecDrdy = ((rx_frame.data.u8[3] >> 3) & (0x01U)); //: 27|1@1+ (1,0) [0|1] "" Receiver + HVP2_hvp1v5Ref = ((rx_frame.data.u8[4] & (0xFFU)) << 4) | + ((rx_frame.data.u8[3] >> 4) & (0x0FU)); //: 28|12@1+ (0.1,0) [0|3] "V" Receiver + HVP2_shuntCurrentDebug = ((rx_frame.data.u8[6] & (0xFFU)) << 8) | + (rx_frame.data.u8[5] & (0xFFU)); //: 40|16@1- (0.1,0) [-3276.8|3276.7] "A" Receiver + HVP2_packCurrentMia = (rx_frame.data.u8[7] & (0x01U)); //: 56|1@1+ (1,0) [0|1] "" Receiver + HVP2_auxCurrentMia = ((rx_frame.data.u8[7] >> 1) & (0x01U)); //: 57|1@1+ (1,0) [0|1] "" Receiver + HVP2_currentSenseMia = ((rx_frame.data.u8[7] >> 2) & (0x03U)); //: 58|1@1+ (1,0) [0|1] "" Receiver + HVP2_shuntRefVoltageMismatch = ((rx_frame.data.u8[7] >> 3) & (0x01U)); //: 59|1@1+ (1,0) [0|1] "" Receiver + HVP2_shuntThermistorMia = ((rx_frame.data.u8[7] >> 4) & (0x01U)); //: 60|1@1+ (1,0) [0|1] "" Receiver + HVP2_shuntHwMia = ((rx_frame.data.u8[7] >> 5) & (0x01U)); //: 61|1@1+ (1,0) [0|1] "" Receiver + } + if (mux == 1) { + HVP2_dcLinkVoltage = ((rx_frame.data.u8[2] & (0xFFU)) << 8) | + (rx_frame.data.u8[1] & (0xFFU)); //: 8|16@1- (0.1,0) [-3276.8|3276.7] "V" Receiver + HVP2_packVoltage = ((rx_frame.data.u8[4] & (0xFFU)) << 8) | + (rx_frame.data.u8[3] & (0xFFU)); //: 24|16@1- (0.1,0) [-3276.8|3276.7] "V" Receiver + HVP2_fcLinkVoltage = ((rx_frame.data.u8[6] & (0xFFU)) << 8) | + (rx_frame.data.u8[5] & (0xFFU)); //: 40|16@1- (0.1,0) [-3276.8|3276.7] "V" Receiver + } + if (mux == 2) { + HVP2_packContVoltage = ((rx_frame.data.u8[1] & (0xFFU)) << 4) | + ((rx_frame.data.u8[0] >> 4) & (0x0FU)); //: 4|12@1+ (0.1,0) [0|30] "V" Receiver + HVP2_packNegativeV = ((rx_frame.data.u8[3] & (0xFFU)) << 8) | + (rx_frame.data.u8[2] & (0xFFU)); //: 16|16@1- (0.1,0) [-550|550] "V" Receiver + HVP2_packPositiveV = ((rx_frame.data.u8[5] & (0xFFU)) << 8) | + (rx_frame.data.u8[4] & (0xFFU)); //: 32|16@1- (0.1,0) [-550|550] "V" Receiver + HVP2_pyroAnalog = ((rx_frame.data.u8[7] & (0x0FU)) << 8) | + (rx_frame.data.u8[6] & (0xFFU)); //: 48|12@1+ (0.1,0) [0|3] "V" Receiver + } + if (mux == 3) { + HVP2_dcLinkNegativeV = ((rx_frame.data.u8[2] & (0xFFU)) << 8) | + (rx_frame.data.u8[1] & (0xFFU)); //: 8|16@1- (0.1,0) [-550|550] "V" Receiver + HVP2_dcLinkPositiveV = ((rx_frame.data.u8[4] & (0xFFU)) << 8) | + (rx_frame.data.u8[3] & (0xFFU)); //: 24|16@1- (0.1,0) [-550|550] "V" Receiver + HVP2_fcLinkNegativeV = ((rx_frame.data.u8[6] & (0xFFU)) << 8) | + (rx_frame.data.u8[5] & (0xFFU)); //: 40|16@1- (0.1,0) [-550|550] "V" Receiver + } + if (mux == 4) { + HVP2_fcContCoilCurrent = ((rx_frame.data.u8[1] & (0xFFU)) << 4) | + ((rx_frame.data.u8[0] >> 4) & (0x0FU)); //: 4|12@1+ (0.1,0) [0|7.5] "A" Receiver + HVP2_fcContVoltage = ((rx_frame.data.u8[3] & (0x0FU)) << 8) | + (rx_frame.data.u8[2] & (0xFFU)); //: 16|12@1+ (0.1,0) [0|30] "V" Receiver + HVP2_hvilInVoltage = ((rx_frame.data.u8[4] & (0xFFU)) << 4) | + ((rx_frame.data.u8[3] >> 4) & (0x0FU)); //: 28|12@1+ (0.1,0) [0|30] "V" Receiver + HVP2_hvilOutVoltage = ((rx_frame.data.u8[6] & (0x0FU)) << 8) | + (rx_frame.data.u8[5] & (0xFFU)); //: 40|12@1+ (0.1,0) [0|30] "V" Receiver + } + if (mux == 5) { + HVP2_fcLinkPositiveV = ((rx_frame.data.u8[2] & (0xFFU)) << 8) | + (rx_frame.data.u8[1] & (0xFFU)); //: 8|16@1- (0.1,0) [-550|550] "V" Receiver + HVP2_packContCoilCurrent = ((rx_frame.data.u8[4] & (0x0FU)) << 8) | + (rx_frame.data.u8[3] & (0xFFU)); //: 24|12@1+ (0.1,0) [0|7.5] "A" Receiver + HVP2_battery12V = ((rx_frame.data.u8[5] & (0xFFU)) << 4) | + ((rx_frame.data.u8[4] >> 4) & (0x0FU)); //: 36|12@1+ (0.1,0) [0|30] "V" Receiver + HVP2_shuntRefVoltageDbg = + ((rx_frame.data.u8[7] & (0xFFU)) << 8) | + (rx_frame.data.u8[6] & (0xFFU)); //: 48|16@1- (0.001,0) [-32.768|32.767] "V" Receiver + } + if (mux == 6) { + HVP2_shuntAuxCurrentDbg = ((rx_frame.data.u8[2] & (0xFFU)) << 8) | + (rx_frame.data.u8[1] & (0xFFU)); //: 8|16@1- (0.1,0) [-3276.8|3276.7] "A" Receiver + HVP2_shuntBarTempDbg = ((rx_frame.data.u8[4] & (0xFFU)) << 8) | + (rx_frame.data.u8[3] & (0xFFU)); //: 24|16@1- (0.01,0) [-327.67|327.67] "C" Receiver + HVP2_shuntAsicTempDbg = ((rx_frame.data.u8[6] & (0xFFU)) << 8) | + (rx_frame.data.u8[5] & (0xFFU)); //: 40|16@1- (0.01,0) [-327.67|327.67] "C" Receiver + HVP2_shuntAuxCurrentStatus = (rx_frame.data.u8[7] & (0x03U)); //: 56|2@1+ (1,0) [0|3] "" Receiver + HVP2_shuntBarTempStatus = ((rx_frame.data.u8[7] >> 2) & (0x03U)); //: 58|2@1+ (1,0) [0|3] "" Receiver + HVP2_shuntAsicTempStatus = ((rx_frame.data.u8[7] >> 4) & (0x03U)); //: 60|2@1+ (1,0) [0|3] "" Receiver + } + break; case 0x3aa: //HVP_alertMatrix1 battery2_WatchdogReset = (rx_frame.data.u8[0] & 0x01); battery2_PowerLossReset = ((rx_frame.data.u8[0] & 0x02) >> 1); @@ -996,6 +2375,110 @@ void receive_can_battery2(CAN_frame rx_frame) { battery2_fcCtrCloseFailed = ((rx_frame.data.u8[6] & 0x02) >> 1); battery2_shuntThermistorMia = ((rx_frame.data.u8[6] & 0x04) >> 2); break; + case 0x320: //800 BMS_alertMatrix //BMS_alertMatrix 800 BMS_alertMatrix: 8 VEH + mux = (rx_frame.data.u8[0] & (0x0F)); + if (mux == 0) + ; + { //mux0 + battery2_BMS_matrixIndex = (rx_frame.data.u8[0] & (0x0F)); // 0|4@1+ (1,0) [0|0] "" X + battery2_BMS_a017_SW_Brick_OV = ((rx_frame.data.u8[2] >> 4) & (0x01)); //20|1@1+ (1,0) [0|0] "" X + battery2_BMS_a018_SW_Brick_UV = ((rx_frame.data.u8[2] >> 5) & (0x01)); //21|1@1+ (1,0) [0|0] "" X + battery2_BMS_a019_SW_Module_OT = ((rx_frame.data.u8[2] >> 6) & (0x01)); //22|1@1+ (1,0) [0|0] "" X + battery2_BMS_a021_SW_Dr_Limits_Regulation = (rx_frame.data.u8[3] & (0x01U)); //24|1@1+ (1,0) [0|0] "" X + battery2_BMS_a022_SW_Over_Current = ((rx_frame.data.u8[3] >> 1) & (0x01U)); //25|1@1+ (1,0) [0|0] "" X + battery2_BMS_a023_SW_Stack_OV = ((rx_frame.data.u8[3] >> 2) & (0x01U)); //26|1@1+ (1,0) [0|0] "" X + battery2_BMS_a024_SW_Islanded_Brick = ((rx_frame.data.u8[3] >> 3) & (0x01U)); //27|1@1+ (1,0) [0|0] "" X + battery2_BMS_a025_SW_PwrBalance_Anomaly = ((rx_frame.data.u8[3] >> 4) & (0x01U)); //28|1@1+ (1,0) [0|0] "" X + battery2_BMS_a026_SW_HFCurrent_Anomaly = ((rx_frame.data.u8[3] >> 5) & (0x01U)); //29|1@1+ (1,0) [0|0] "" X + battery2_BMS_a034_SW_Passive_Isolation = ((rx_frame.data.u8[4] >> 5) & (0x01U)); //37|1@1+ (1,0) [0|0] "" X ? + battery2_BMS_a035_SW_Isolation = ((rx_frame.data.u8[4] >> 6) & (0x01U)); //38|1@1+ (1,0) [0|0] "" X + battery2_BMS_a036_SW_HvpHvilFault = ((rx_frame.data.u8[4] >> 6) & (0x01U)); //39|1@1+ (1,0) [0|0] "" X + battery2_BMS_a037_SW_Flood_Port_Open = (rx_frame.data.u8[5] & (0x01U)); //40|1@1+ (1,0) [0|0] "" X + battery2_BMS_a039_SW_DC_Link_Over_Voltage = ((rx_frame.data.u8[5] >> 2) & (0x01U)); //42|1@1+ (1,0) [0|0] "" X + battery2_BMS_a041_SW_Power_On_Reset = ((rx_frame.data.u8[5] >> 4) & (0x01U)); //44|1@1+ (1,0) [0|0] "" X + battery2_BMS_a042_SW_MPU_Error = ((rx_frame.data.u8[5] >> 5) & (0x01U)); //45|1@1+ (1,0) [0|0] "" X + battery2_BMS_a043_SW_Watch_Dog_Reset = ((rx_frame.data.u8[5] >> 6) & (0x01U)); //46|1@1+ (1,0) [0|0] "" X + battery2_BMS_a044_SW_Assertion = ((rx_frame.data.u8[5] >> 7) & (0x01U)); //47|1@1+ (1,0) [0|0] "" X + battery2_BMS_a045_SW_Exception = (rx_frame.data.u8[6] & (0x01U)); //48|1@1+ (1,0) [0|0] "" X + battery2_BMS_a046_SW_Task_Stack_Usage = ((rx_frame.data.u8[6] >> 1) & (0x01U)); //49|1@1+ (1,0) [0|0] "" X + battery2_BMS_a047_SW_Task_Stack_Overflow = ((rx_frame.data.u8[6] >> 2) & (0x01U)); //50|1@1+ (1,0) [0|0] "" X + battery2_BMS_a048_SW_Log_Upload_Request = ((rx_frame.data.u8[6] >> 3) & (0x01U)); //51|1@1+ (1,0) [0|0] "" X + battery2_BMS_a050_SW_Brick_Voltage_MIA = ((rx_frame.data.u8[6] >> 5) & (0x01U)); //53|1@1+ (1,0) [0|0] "" X + battery2_BMS_a051_SW_HVC_Vref_Bad = ((rx_frame.data.u8[6] >> 6) & (0x01U)); //54|1@1+ (1,0) [0|0] "" X + battery2_BMS_a052_SW_PCS_MIA = ((rx_frame.data.u8[6] >> 7) & (0x01U)); //55|1@1+ (1,0) [0|0] "" X + battery2_BMS_a053_SW_ThermalModel_Sanity = (rx_frame.data.u8[7] & (0x01U)); //56|1@1+ (1,0) [0|0] "" X + battery2_BMS_a054_SW_Ver_Supply_Fault = ((rx_frame.data.u8[7] >> 1) & (0x01U)); //57|1@1+ (1,0) [0|0] "" X + battery2_BMS_a059_SW_Pack_Voltage_Sensing = ((rx_frame.data.u8[7] >> 6) & (0x01U)); //62|1@1+ (1,0) [0|0] "" X + battery2_BMS_a060_SW_Leakage_Test_Failure = ((rx_frame.data.u8[7] >> 7) & (0x01U)); //63|1@1+ (1,0) [0|0] "" X + } + if (mux == 1) { //mux1 + battery2_BMS_a061_robinBrickOverVoltage = ((rx_frame.data.u8[0] >> 4) & (0x01U)); //4|1@1+ (1,0) [0|0] "" X + battery2_BMS_a062_SW_BrickV_Imbalance = ((rx_frame.data.u8[0] >> 5) & (0x01U)); //5|1@1+ (1,0) [0|0] "" X + battery2_BMS_a063_SW_ChargePort_Fault = ((rx_frame.data.u8[0] >> 6) & (0x01U)); //6|1@1+ (1,0) [0|0] "" X + battery2_BMS_a064_SW_SOC_Imbalance = ((rx_frame.data.u8[0] >> 7) & (0x01U)); //7|1@1+ (1,0) [0|0] "" X + battery2_BMS_a069_SW_Low_Power = ((rx_frame.data.u8[1] >> 4) & (0x01U)); //12|1@1+ (1,0) [0|0] "" X + battery2_BMS_a071_SW_SM_TransCon_Not_Met = ((rx_frame.data.u8[1] >> 6) & (0x01U)); //14|1@1+ (1,0) [0|0] "" X + battery2_BMS_a075_SW_Chg_Disable_Failure = ((rx_frame.data.u8[2] >> 2) & (0x01U)); //18|1@1+ (1,0) [0|0] "" X + battery2_BMS_a076_SW_Dch_While_Charging = ((rx_frame.data.u8[2] >> 3) & (0x01U)); //19|1@1+ (1,0) [0|0] "" X + battery2_BMS_a077_SW_Charger_Regulation = ((rx_frame.data.u8[2] >> 4) & (0x01U)); //20|1@1+ (1,0) [0|0] "" X + battery2_BMS_a081_SW_Ctr_Close_Blocked = (rx_frame.data.u8[3] & (0x01U)); //24|1@1+ (1,0) [0|0] "" X + battery2_BMS_a082_SW_Ctr_Force_Open = ((rx_frame.data.u8[3] >> 1) & (0x01U)); //25|1@1+ (1,0) [0|0] "" X + battery2_BMS_a083_SW_Ctr_Close_Failure = ((rx_frame.data.u8[3] >> 2) & (0x01U)); //26|1@1+ (1,0) [0|0] "" X + battery2_BMS_a084_SW_Sleep_Wake_Aborted = ((rx_frame.data.u8[3] >> 3) & (0x01U)); //27|1@1+ (1,0) [0|0] "" X + battery2_BMS_a087_SW_Feim_Test_Blocked = ((rx_frame.data.u8[3] >> 6) & (0x01U)); //30|1@1+ (1,0) [0|0] "" X + battery2_BMS_a088_SW_VcFront_MIA_InDrive = ((rx_frame.data.u8[3] >> 7) & (0x01U)); //31|1@1+ (1,0) [0|0] "" X + battery2_BMS_a089_SW_VcFront_MIA = (rx_frame.data.u8[4] & (0x01U)); //32|1@1+ (1,0) [0|0] "" X + battery2_BMS_a090_SW_Gateway_MIA = ((rx_frame.data.u8[4] >> 1) & (0x01U)); //33|1@1+ (1,0) [0|0] "" X + battery2_BMS_a091_SW_ChargePort_MIA = ((rx_frame.data.u8[4] >> 2) & (0x01U)); //34|1@1+ (1,0) [0|0] "" X + battery2_BMS_a092_SW_ChargePort_Mia_On_Hv = ((rx_frame.data.u8[4] >> 3) & (0x01U)); //35|1@1+ (1,0) [0|0] "" X + battery2_BMS_a094_SW_Drive_Inverter_MIA = ((rx_frame.data.u8[4] >> 5) & (0x01U)); //37|1@1+ (1,0) [0|0] "" X + battery2_BMS_a099_SW_BMB_Communication = ((rx_frame.data.u8[5] >> 2) & (0x01U)); //42|1@1+ (1,0) [0|0] "" X + battery2_BMS_a105_SW_One_Module_Tsense = (rx_frame.data.u8[6] & (0x01U)); //48|1@1+ (1,0) [0|0] "" X + battery2_BMS_a106_SW_All_Module_Tsense = ((rx_frame.data.u8[6] >> 1) & (0x01U)); //49|1@1+ (1,0) [0|0] "" X + battery2_BMS_a107_SW_Stack_Voltage_MIA = ((rx_frame.data.u8[6] >> 2) & (0x01U)); //50|1@1+ (1,0) [0|0] "" X + } + if (mux == 2) { //mux2 + battery2_BMS_a121_SW_NVRAM_Config_Error = ((rx_frame.data.u8[0] >> 4) & (0x01U)); // 4|1@1+ (1,0) [0|0] "" X + battery2_BMS_a122_SW_BMS_Therm_Irrational = ((rx_frame.data.u8[0] >> 5) & (0x01U)); //5|1@1+ (1,0) [0|0] "" X + battery2_BMS_a123_SW_Internal_Isolation = ((rx_frame.data.u8[0] >> 6) & (0x01U)); //6|1@1+ (1,0) [0|0] "" X + battery2_BMS_a127_SW_shunt_SNA = ((rx_frame.data.u8[1] >> 2) & (0x01U)); //10|1@1+ (1,0) [0|0] "" X + battery2_BMS_a128_SW_shunt_MIA = ((rx_frame.data.u8[1] >> 3) & (0x01U)); //11|1@1+ (1,0) [0|0] "" X + battery2_BMS_a129_SW_VSH_Failure = ((rx_frame.data.u8[1] >> 4) & (0x01U)); //12|1@1+ (1,0) [0|0] "" X + battery2_BMS_a130_IO_CAN_Error = ((rx_frame.data.u8[1] >> 5) & (0x01U)); //13|1@1+ (1,0) [0|0] "" X + battery2_BMS_a131_Bleed_FET_Failure = ((rx_frame.data.u8[1] >> 6) & (0x01U)); //14|1@1+ (1,0) [0|0] "" X + battery2_BMS_a132_HW_BMB_OTP_Uncorrctbl = ((rx_frame.data.u8[1] >> 7) & (0x01U)); //15|1@1+ (1,0) [0|0] "" X + battery2_BMS_a134_SW_Delayed_Ctr_Off = ((rx_frame.data.u8[2] >> 1) & (0x01U)); //17|1@1+ (1,0) [0|0] "" X + battery2_BMS_a136_SW_Module_OT_Warning = ((rx_frame.data.u8[2] >> 3) & (0x01U)); //19|1@1+ (1,0) [0|0] "" X + battery2_BMS_a137_SW_Brick_UV_Warning = ((rx_frame.data.u8[2] >> 4) & (0x01U)); //20|1@1+ (1,0) [0|0] "" X + battery2_BMS_a138_SW_Brick_OV_Warning = ((rx_frame.data.u8[2] >> 5) & (0x01U)); //21|1@1+ (1,0) [0|0] "" X + battery2_BMS_a139_SW_DC_Link_V_Irrational = ((rx_frame.data.u8[2] >> 6) & (0x01U)); //22|1@1+ (1,0) [0|0] "" X + battery2_BMS_a141_SW_BMB_Status_Warning = (rx_frame.data.u8[3] & (0x01U)); //24|1@1+ (1,0) [0|0] "" X + battery2_BMS_a144_Hvp_Config_Mismatch = ((rx_frame.data.u8[3] >> 3) & (0x01U)); //27|1@1+ (1,0) [0|0] "" X + battery2_BMS_a145_SW_SOC_Change = ((rx_frame.data.u8[3] >> 4) & (0x01U)); //28|1@1+ (1,0) [0|0] "" X + battery2_BMS_a146_SW_Brick_Overdischarged = ((rx_frame.data.u8[3] >> 5) & (0x01U)); //29|1@1+ (1,0) [0|0] "" X + battery2_BMS_a149_SW_Missing_Config_Block = (rx_frame.data.u8[4] & (0x01U)); //32|1@1+ (1,0) [0|0] "" X + battery2_BMS_a151_SW_external_isolation = ((rx_frame.data.u8[4] >> 2) & (0x01U)); //34|1@1+ (1,0) [0|0] "" X + battery2_BMS_a156_SW_BMB_Vref_bad = ((rx_frame.data.u8[4] >> 7) & (0x01U)); //39|1@1+ (1,0) [0|0] "" X + battery2_BMS_a157_SW_HVP_HVS_Comms = (rx_frame.data.u8[5] & (0x01U)); //40|1@1+ (1,0) [0|0] "" X + battery2_BMS_a158_SW_HVP_HVI_Comms = ((rx_frame.data.u8[5] >> 1) & (0x01U)); //41|1@1+ (1,0) [0|0] "" X + battery2_BMS_a159_SW_HVP_ECU_Error = ((rx_frame.data.u8[5] >> 2) & (0x01U)); //42|1@1+ (1,0) [0|0] "" X + battery2_BMS_a161_SW_DI_Open_Request = ((rx_frame.data.u8[5] >> 4) & (0x01U)); //44|1@1+ (1,0) [0|0] "" X + battery2_BMS_a162_SW_No_Power_For_Support = ((rx_frame.data.u8[5] >> 5) & (0x01U)); //45|1@1+ (1,0) [0|0] "" X + battery2_BMS_a163_SW_Contactor_Mismatch = ((rx_frame.data.u8[5] >> 6) & (0x01U)); //46|1@1+ (1,0) [0|0] "" X + battery2_BMS_a164_SW_Uncontrolled_Regen = ((rx_frame.data.u8[5] >> 7) & (0x01U)); //47|1@1+ (1,0) [0|0] "" X + battery2_BMS_a165_SW_Pack_Partial_Weld = (rx_frame.data.u8[6] & (0x01U)); //48|1@1+ (1,0) [0|0] "" X + battery2_BMS_a166_SW_Pack_Full_Weld = ((rx_frame.data.u8[6] >> 1) & (0x01U)); //49|1@1+ (1,0) [0|0] "" X + battery2_BMS_a167_SW_FC_Partial_Weld = ((rx_frame.data.u8[6] >> 2) & (0x01U)); //50|1@1+ (1,0) [0|0] "" X + battery2_BMS_a168_SW_FC_Full_Weld = ((rx_frame.data.u8[6] >> 3) & (0x01U)); //51|1@1+ (1,0) [0|0] "" X + battery2_BMS_a169_SW_FC_Pack_Weld = ((rx_frame.data.u8[6] >> 4) & (0x01U)); //52|1@1+ (1,0) [0|0] "" X + battery2_BMS_a170_SW_Limp_Mode = ((rx_frame.data.u8[6] >> 5) & (0x01U)); //53|1@1+ (1,0) [0|0] "" X + battery2_BMS_a171_SW_Stack_Voltage_Sense = ((rx_frame.data.u8[6] >> 6) & (0x01U)); //54|1@1+ (1,0) [0|0] "" X + battery2_BMS_a174_SW_Charge_Failure = ((rx_frame.data.u8[7] >> 1) & (0x01U)); //57|1@1+ (1,0) [0|0] "" X + battery2_BMS_a176_SW_GracefulPowerOff = ((rx_frame.data.u8[7] >> 3) & (0x01U)); //59|1@1+ (1,0) [0|0] "" X + battery2_BMS_a179_SW_Hvp_12V_Fault = ((rx_frame.data.u8[7] >> 6) & (0x01U)); //62|1@1+ (1,0) [0|0] "" X + battery2_BMS_a180_SW_ECU_reset_blocked = ((rx_frame.data.u8[7] >> 7) & (0x01U)); //63|1@1+ (1,0) [0|0] "" X + } + break; default: break; } @@ -1292,6 +2775,7 @@ void printFaultCodesIfActive() { "disable the inverter protocol to proceed with contactor closing"); } // Check each symbol and print debug information if its value is 1 + // 0X3AA: 938 HVP_alertMatrix1 printDebugIfActive(battery_WatchdogReset, "ERROR: The processor has experienced a reset due to watchdog reset"); printDebugIfActive(battery_PowerLossReset, "ERROR: The processor has experienced a reset due to power loss"); printDebugIfActive(battery_SwAssertion, "ERROR: An internal software assertion has failed"); @@ -1350,9 +2834,101 @@ void printFaultCodesIfActive() { printDebugIfActive(battery_packCtrCloseFailed, "ERROR: packCtrCloseFailed is active"); printDebugIfActive(battery_fcCtrCloseFailed, "ERROR: fcCtrCloseFailed is active"); printDebugIfActive(battery_shuntThermistorMia, "ERROR: shuntThermistorMia is active"); + // 0x320 800 BMS_alertMatrix + printDebugIfActive(battery_BMS_a017_SW_Brick_OV, "ERROR: BMS_a017_SW_Brick_OV"); + printDebugIfActive(battery_BMS_a018_SW_Brick_UV, "ERROR: BMS_a018_SW_Brick_UV"); + printDebugIfActive(battery_BMS_a019_SW_Module_OT, "ERROR: BMS_a019_SW_Module_OT"); + printDebugIfActive(battery_BMS_a021_SW_Dr_Limits_Regulation, "ERROR: BMS_a021_SW_Dr_Limits_Regulation"); + printDebugIfActive(battery_BMS_a022_SW_Over_Current, "ERROR: BMS_a022_SW_Over_Current"); + printDebugIfActive(battery_BMS_a023_SW_Stack_OV, "ERROR: BMS_a023_SW_Stack_OV"); + printDebugIfActive(battery_BMS_a024_SW_Islanded_Brick, "ERROR: BMS_a024_SW_Islanded_Brick"); + printDebugIfActive(battery_BMS_a025_SW_PwrBalance_Anomaly, "ERROR: BMS_a025_SW_PwrBalance_Anomaly"); + printDebugIfActive(battery_BMS_a026_SW_HFCurrent_Anomaly, "ERROR: BMS_a026_SW_HFCurrent_Anomaly"); + printDebugIfActive(battery_BMS_a034_SW_Passive_Isolation, "ERROR: BMS_a034_SW_Passive_Isolation"); + printDebugIfActive(battery_BMS_a035_SW_Isolation, "ERROR: BMS_a035_SW_Isolation"); + printDebugIfActive(battery_BMS_a036_SW_HvpHvilFault, "ERROR: BMS_a036_SW_HvpHvilFault"); + printDebugIfActive(battery_BMS_a037_SW_Flood_Port_Open, "ERROR: BMS_a037_SW_Flood_Port_Open"); + printDebugIfActive(battery_BMS_a039_SW_DC_Link_Over_Voltage, "ERROR: BMS_a039_SW_DC_Link_Over_Voltage"); + printDebugIfActive(battery_BMS_a041_SW_Power_On_Reset, "ERROR: BMS_a041_SW_Power_On_Reset"); + printDebugIfActive(battery_BMS_a042_SW_MPU_Error, "ERROR: BMS_a042_SW_MPU_Error"); + printDebugIfActive(battery_BMS_a043_SW_Watch_Dog_Reset, "ERROR: BMS_a043_SW_Watch_Dog_Reset"); + printDebugIfActive(battery_BMS_a044_SW_Assertion, "ERROR: BMS_a044_SW_Assertion"); + printDebugIfActive(battery_BMS_a045_SW_Exception, "ERROR: BMS_a045_SW_Exception"); + printDebugIfActive(battery_BMS_a046_SW_Task_Stack_Usage, "ERROR: BMS_a046_SW_Task_Stack_Usage"); + printDebugIfActive(battery_BMS_a047_SW_Task_Stack_Overflow, "ERROR: BMS_a047_SW_Task_Stack_Overflow"); + printDebugIfActive(battery_BMS_a048_SW_Log_Upload_Request, "ERROR: BMS_a048_SW_Log_Upload_Request"); + printDebugIfActive(battery_BMS_a050_SW_Brick_Voltage_MIA, "ERROR: BMS_a050_SW_Brick_Voltage_MIA"); + printDebugIfActive(battery_BMS_a051_SW_HVC_Vref_Bad, "ERROR: BMS_a051_SW_HVC_Vref_Bad"); + printDebugIfActive(battery_BMS_a052_SW_PCS_MIA, "ERROR: BMS_a052_SW_PCS_MIA"); + printDebugIfActive(battery_BMS_a053_SW_ThermalModel_Sanity, "ERROR: BMS_a053_SW_ThermalModel_Sanity"); + printDebugIfActive(battery_BMS_a054_SW_Ver_Supply_Fault, "ERROR: BMS_a054_SW_Ver_Supply_Fault"); + printDebugIfActive(battery_BMS_a059_SW_Pack_Voltage_Sensing, "ERROR: BMS_a059_SW_Pack_Voltage_Sensing"); + printDebugIfActive(battery_BMS_a060_SW_Leakage_Test_Failure, "ERROR: BMS_a060_SW_Leakage_Test_Failure"); + printDebugIfActive(battery_BMS_a061_robinBrickOverVoltage, "ERROR: BMS_a061_robinBrickOverVoltage"); + printDebugIfActive(battery_BMS_a062_SW_BrickV_Imbalance, "ERROR: BMS_a062_SW_BrickV_Imbalance"); + printDebugIfActive(battery_BMS_a063_SW_ChargePort_Fault, "ERROR: BMS_a063_SW_ChargePort_Fault"); + printDebugIfActive(battery_BMS_a064_SW_SOC_Imbalance, "ERROR: BMS_a064_SW_SOC_Imbalance"); + printDebugIfActive(battery_BMS_a069_SW_Low_Power, "ERROR: BMS_a069_SW_Low_Power"); + printDebugIfActive(battery_BMS_a071_SW_SM_TransCon_Not_Met, "ERROR: BMS_a071_SW_SM_TransCon_Not_Met"); + printDebugIfActive(battery_BMS_a075_SW_Chg_Disable_Failure, "ERROR: BMS_a075_SW_Chg_Disable_Failure"); + printDebugIfActive(battery_BMS_a076_SW_Dch_While_Charging, "ERROR: BMS_a076_SW_Dch_While_Charging"); + printDebugIfActive(battery_BMS_a077_SW_Charger_Regulation, "ERROR: BMS_a077_SW_Charger_Regulation"); + printDebugIfActive(battery_BMS_a081_SW_Ctr_Close_Blocked, "ERROR: BMS_a081_SW_Ctr_Close_Blocked"); + printDebugIfActive(battery_BMS_a082_SW_Ctr_Force_Open, "ERROR: BMS_a082_SW_Ctr_Force_Open"); + printDebugIfActive(battery_BMS_a083_SW_Ctr_Close_Failure, "ERROR: BMS_a083_SW_Ctr_Close_Failure"); + printDebugIfActive(battery_BMS_a084_SW_Sleep_Wake_Aborted, "ERROR: BMS_a084_SW_Sleep_Wake_Aborted"); + printDebugIfActive(battery_BMS_a087_SW_Feim_Test_Blocked, "ERROR: BMS_a087_SW_Feim_Test_Blocked"); + printDebugIfActive(battery_BMS_a088_SW_VcFront_MIA_InDrive, "ERROR: BMS_a088_SW_VcFront_MIA_InDrive"); + printDebugIfActive(battery_BMS_a089_SW_VcFront_MIA, "ERROR: BMS_a089_SW_VcFront_MIA"); + printDebugIfActive(battery_BMS_a090_SW_Gateway_MIA, "ERROR: BMS_a090_SW_Gateway_MIA"); + printDebugIfActive(battery_BMS_a091_SW_ChargePort_MIA, "ERROR: BMS_a091_SW_ChargePort_MIA"); + printDebugIfActive(battery_BMS_a092_SW_ChargePort_Mia_On_Hv, "ERROR: BMS_a092_SW_ChargePort_Mia_On_Hv"); + printDebugIfActive(battery_BMS_a094_SW_Drive_Inverter_MIA, "ERROR: BMS_a094_SW_Drive_Inverter_MIA"); + printDebugIfActive(battery_BMS_a099_SW_BMB_Communication, "ERROR: BMS_a099_SW_BMB_Communication"); + printDebugIfActive(battery_BMS_a105_SW_One_Module_Tsense, "ERROR: BMS_a105_SW_One_Module_Tsense"); + printDebugIfActive(battery_BMS_a106_SW_All_Module_Tsense, "ERROR: BMS_a106_SW_All_Module_Tsense"); + printDebugIfActive(battery_BMS_a107_SW_Stack_Voltage_MIA, "ERROR: BMS_a107_SW_Stack_Voltage_MIA"); + printDebugIfActive(battery_BMS_a121_SW_NVRAM_Config_Error, "ERROR: BMS_a121_SW_NVRAM_Config_Error"); + printDebugIfActive(battery_BMS_a122_SW_BMS_Therm_Irrational, "ERROR: BMS_a122_SW_BMS_Therm_Irrational"); + printDebugIfActive(battery_BMS_a123_SW_Internal_Isolation, "ERROR: BMS_a123_SW_Internal_Isolation"); + printDebugIfActive(battery_BMS_a127_SW_shunt_SNA, "ERROR: BMS_a127_SW_shunt_SNA"); + printDebugIfActive(battery_BMS_a128_SW_shunt_MIA, "ERROR: BMS_a128_SW_shunt_MIA"); + printDebugIfActive(battery_BMS_a129_SW_VSH_Failure, "ERROR: BMS_a129_SW_VSH_Failure"); + printDebugIfActive(battery_BMS_a130_IO_CAN_Error, "ERROR: BMS_a130_IO_CAN_Error"); + printDebugIfActive(battery_BMS_a131_Bleed_FET_Failure, "ERROR: BMS_a131_Bleed_FET_Failure"); + printDebugIfActive(battery_BMS_a132_HW_BMB_OTP_Uncorrctbl, "ERROR: BMS_a132_HW_BMB_OTP_Uncorrctbl"); + printDebugIfActive(battery_BMS_a134_SW_Delayed_Ctr_Off, "ERROR: BMS_a134_SW_Delayed_Ctr_Off"); + printDebugIfActive(battery_BMS_a136_SW_Module_OT_Warning, "ERROR: BMS_a136_SW_Module_OT_Warning"); + printDebugIfActive(battery_BMS_a137_SW_Brick_UV_Warning, "ERROR: BMS_a137_SW_Brick_UV_Warning"); + printDebugIfActive(battery_BMS_a139_SW_DC_Link_V_Irrational, "ERROR: BMS_a139_SW_DC_Link_V_Irrational"); + printDebugIfActive(battery_BMS_a141_SW_BMB_Status_Warning, "ERROR: BMS_a141_SW_BMB_Status_Warning"); + printDebugIfActive(battery_BMS_a144_Hvp_Config_Mismatch, "ERROR: BMS_a144_Hvp_Config_Mismatch"); + printDebugIfActive(battery_BMS_a145_SW_SOC_Change, "ERROR: BMS_a145_SW_SOC_Change"); + printDebugIfActive(battery_BMS_a146_SW_Brick_Overdischarged, "ERROR: BMS_a146_SW_Brick_Overdischarged"); + printDebugIfActive(battery_BMS_a149_SW_Missing_Config_Block, "ERROR: BMS_a149_SW_Missing_Config_Block"); + printDebugIfActive(battery_BMS_a151_SW_external_isolation, "ERROR: BMS_a151_SW_external_isolation"); + printDebugIfActive(battery_BMS_a156_SW_BMB_Vref_bad, "ERROR: BMS_a156_SW_BMB_Vref_bad"); + printDebugIfActive(battery_BMS_a157_SW_HVP_HVS_Comms, "ERROR: BMS_a157_SW_HVP_HVS_Comms"); + printDebugIfActive(battery_BMS_a158_SW_HVP_HVI_Comms, "ERROR: BMS_a158_SW_HVP_HVI_Comms"); + printDebugIfActive(battery_BMS_a159_SW_HVP_ECU_Error, "ERROR: BMS_a159_SW_HVP_ECU_Error"); + printDebugIfActive(battery_BMS_a161_SW_DI_Open_Request, "ERROR: BMS_a161_SW_DI_Open_Request"); + printDebugIfActive(battery_BMS_a162_SW_No_Power_For_Support, "ERROR: BMS_a162_SW_No_Power_For_Support"); + printDebugIfActive(battery_BMS_a163_SW_Contactor_Mismatch, "ERROR: BMS_a163_SW_Contactor_Mismatch"); + printDebugIfActive(battery_BMS_a164_SW_Uncontrolled_Regen, "ERROR: BMS_a164_SW_Uncontrolled_Regen"); + printDebugIfActive(battery_BMS_a165_SW_Pack_Partial_Weld, "ERROR: BMS_a165_SW_Pack_Partial_Weld"); + printDebugIfActive(battery_BMS_a166_SW_Pack_Full_Weld, "ERROR: BMS_a166_SW_Pack_Full_Weld"); + printDebugIfActive(battery_BMS_a167_SW_FC_Partial_Weld, "ERROR: BMS_a167_SW_FC_Partial_Weld"); + printDebugIfActive(battery_BMS_a168_SW_FC_Full_Weld, "ERROR: BMS_a168_SW_FC_Full_Weld"); + printDebugIfActive(battery_BMS_a169_SW_FC_Pack_Weld, "ERROR: BMS_a169_SW_FC_Pack_Weld"); + printDebugIfActive(battery_BMS_a170_SW_Limp_Mode, "ERROR: BMS_a170_SW_Limp_Mode"); + printDebugIfActive(battery_BMS_a171_SW_Stack_Voltage_Sense, "ERROR: BMS_a171_SW_Stack_Voltage_Sense"); + printDebugIfActive(battery_BMS_a174_SW_Charge_Failure, "ERROR: BMS_a174_SW_Charge_Failure"); + printDebugIfActive(battery_BMS_a176_SW_GracefulPowerOff, "ERROR: BMS_a176_SW_GracefulPowerOff"); + printDebugIfActive(battery_BMS_a179_SW_Hvp_12V_Fault, "ERROR: BMS_a179_SW_Hvp_12V_Fault"); + printDebugIfActive(battery_BMS_a180_SW_ECU_reset_blocked, "ERROR: BMS_a180_SW_ECU_reset_blocked"); } -#ifdef DOUBLE_BATTERY +#ifdef DOUBLE_BATTERY //need to update battery2 void printFaultCodesIfActive_battery2() { if (battery2_packCtrsClosingAllowed == 0) { logging.println( @@ -1428,6 +3004,98 @@ void printFaultCodesIfActive_battery2() { printDebugIfActive(battery2_packCtrCloseFailed, "ERROR: packCtrCloseFailed is active"); printDebugIfActive(battery2_fcCtrCloseFailed, "ERROR: fcCtrCloseFailed is active"); printDebugIfActive(battery2_shuntThermistorMia, "ERROR: shuntThermistorMia is active"); + // 0x320 800 BMS_alertMatrix + printDebugIfActive(battery2_BMS_a017_SW_Brick_OV, "ERROR: BMS_a017_SW_Brick_OV"); + printDebugIfActive(battery2_BMS_a018_SW_Brick_UV, "ERROR: BMS_a018_SW_Brick_UV"); + printDebugIfActive(battery2_BMS_a019_SW_Module_OT, "ERROR: BMS_a019_SW_Module_OT"); + printDebugIfActive(battery2_BMS_a021_SW_Dr_Limits_Regulation, "ERROR: BMS_a021_SW_Dr_Limits_Regulation"); + printDebugIfActive(battery2_BMS_a022_SW_Over_Current, "ERROR: BMS_a022_SW_Over_Current"); + printDebugIfActive(battery2_BMS_a023_SW_Stack_OV, "ERROR: BMS_a023_SW_Stack_OV"); + printDebugIfActive(battery2_BMS_a024_SW_Islanded_Brick, "ERROR: BMS_a024_SW_Islanded_Brick"); + printDebugIfActive(battery2_BMS_a025_SW_PwrBalance_Anomaly, "ERROR: BMS_a025_SW_PwrBalance_Anomaly"); + printDebugIfActive(battery2_BMS_a026_SW_HFCurrent_Anomaly, "ERROR: BMS_a026_SW_HFCurrent_Anomaly"); + printDebugIfActive(battery2_BMS_a034_SW_Passive_Isolation, "ERROR: BMS_a034_SW_Passive_Isolation"); + printDebugIfActive(battery2_BMS_a035_SW_Isolation, "ERROR: BMS_a035_SW_Isolation"); + printDebugIfActive(battery2_BMS_a036_SW_HvpHvilFault, "ERROR: BMS_a036_SW_HvpHvilFault"); + printDebugIfActive(battery2_BMS_a037_SW_Flood_Port_Open, "ERROR: BMS_a037_SW_Flood_Port_Open"); + printDebugIfActive(battery2_BMS_a039_SW_DC_Link_Over_Voltage, "ERROR: BMS_a039_SW_DC_Link_Over_Voltage"); + printDebugIfActive(battery2_BMS_a041_SW_Power_On_Reset, "ERROR: BMS_a041_SW_Power_On_Reset"); + printDebugIfActive(battery2_BMS_a042_SW_MPU_Error, "ERROR: BMS_a042_SW_MPU_Error"); + printDebugIfActive(battery2_BMS_a043_SW_Watch_Dog_Reset, "ERROR: BMS_a043_SW_Watch_Dog_Reset"); + printDebugIfActive(battery2_BMS_a044_SW_Assertion, "ERROR: BMS_a044_SW_Assertion"); + printDebugIfActive(battery2_BMS_a045_SW_Exception, "ERROR: BMS_a045_SW_Exception"); + printDebugIfActive(battery2_BMS_a046_SW_Task_Stack_Usage, "ERROR: BMS_a046_SW_Task_Stack_Usage"); + printDebugIfActive(battery2_BMS_a047_SW_Task_Stack_Overflow, "ERROR: BMS_a047_SW_Task_Stack_Overflow"); + printDebugIfActive(battery2_BMS_a048_SW_Log_Upload_Request, "ERROR: BMS_a048_SW_Log_Upload_Request"); + printDebugIfActive(battery2_BMS_a050_SW_Brick_Voltage_MIA, "ERROR: BMS_a050_SW_Brick_Voltage_MIA"); + printDebugIfActive(battery2_BMS_a051_SW_HVC_Vref_Bad, "ERROR: BMS_a051_SW_HVC_Vref_Bad"); + printDebugIfActive(battery2_BMS_a052_SW_PCS_MIA, "ERROR: BMS_a052_SW_PCS_MIA"); + printDebugIfActive(battery2_BMS_a053_SW_ThermalModel_Sanity, "ERROR: BMS_a053_SW_ThermalModel_Sanity"); + printDebugIfActive(battery2_BMS_a054_SW_Ver_Supply_Fault, "ERROR: BMS_a054_SW_Ver_Supply_Fault"); + printDebugIfActive(battery2_BMS_a059_SW_Pack_Voltage_Sensing, "ERROR: BMS_a059_SW_Pack_Voltage_Sensing"); + printDebugIfActive(battery2_BMS_a060_SW_Leakage_Test_Failure, "ERROR: BMS_a060_SW_Leakage_Test_Failure"); + printDebugIfActive(battery2_BMS_a061_robinBrickOverVoltage, "ERROR: BMS_a061_robinBrickOverVoltage"); + printDebugIfActive(battery2_BMS_a062_SW_BrickV_Imbalance, "ERROR: BMS_a062_SW_BrickV_Imbalance"); + printDebugIfActive(battery2_BMS_a063_SW_ChargePort_Fault, "ERROR: BMS_a063_SW_ChargePort_Fault"); + printDebugIfActive(battery2_BMS_a064_SW_SOC_Imbalance, "ERROR: BMS_a064_SW_SOC_Imbalance"); + printDebugIfActive(battery2_BMS_a069_SW_Low_Power, "ERROR: BMS_a069_SW_Low_Power"); + printDebugIfActive(battery2_BMS_a071_SW_SM_TransCon_Not_Met, "ERROR: BMS_a071_SW_SM_TransCon_Not_Met"); + printDebugIfActive(battery2_BMS_a075_SW_Chg_Disable_Failure, "ERROR: BMS_a075_SW_Chg_Disable_Failure"); + printDebugIfActive(battery2_BMS_a076_SW_Dch_While_Charging, "ERROR: BMS_a076_SW_Dch_While_Charging"); + printDebugIfActive(battery2_BMS_a077_SW_Charger_Regulation, "ERROR: BMS_a077_SW_Charger_Regulation"); + printDebugIfActive(battery2_BMS_a081_SW_Ctr_Close_Blocked, "ERROR: BMS_a081_SW_Ctr_Close_Blocked"); + printDebugIfActive(battery2_BMS_a082_SW_Ctr_Force_Open, "ERROR: BMS_a082_SW_Ctr_Force_Open"); + printDebugIfActive(battery2_BMS_a083_SW_Ctr_Close_Failure, "ERROR: BMS_a083_SW_Ctr_Close_Failure"); + printDebugIfActive(battery2_BMS_a084_SW_Sleep_Wake_Aborted, "ERROR: BMS_a084_SW_Sleep_Wake_Aborted"); + printDebugIfActive(battery2_BMS_a087_SW_Feim_Test_Blocked, "ERROR: BMS_a087_SW_Feim_Test_Blocked"); + printDebugIfActive(battery2_BMS_a088_SW_VcFront_MIA_InDrive, "ERROR: BMS_a088_SW_VcFront_MIA_InDrive"); + printDebugIfActive(battery2_BMS_a089_SW_VcFront_MIA, "ERROR: BMS_a089_SW_VcFront_MIA"); + printDebugIfActive(battery2_BMS_a090_SW_Gateway_MIA, "ERROR: BMS_a090_SW_Gateway_MIA"); + printDebugIfActive(battery2_BMS_a091_SW_ChargePort_MIA, "ERROR: BMS_a091_SW_ChargePort_MIA"); + printDebugIfActive(battery2_BMS_a092_SW_ChargePort_Mia_On_Hv, "ERROR: BMS_a092_SW_ChargePort_Mia_On_Hv"); + printDebugIfActive(battery2_BMS_a094_SW_Drive_Inverter_MIA, "ERROR: BMS_a094_SW_Drive_Inverter_MIA"); + printDebugIfActive(battery2_BMS_a099_SW_BMB_Communication, "ERROR: BMS_a099_SW_BMB_Communication"); + printDebugIfActive(battery2_BMS_a105_SW_One_Module_Tsense, "ERROR: BMS_a105_SW_One_Module_Tsense"); + printDebugIfActive(battery2_BMS_a106_SW_All_Module_Tsense, "ERROR: BMS_a106_SW_All_Module_Tsense"); + printDebugIfActive(battery2_BMS_a107_SW_Stack_Voltage_MIA, "ERROR: BMS_a107_SW_Stack_Voltage_MIA"); + printDebugIfActive(battery2_BMS_a121_SW_NVRAM_Config_Error, "ERROR: BMS_a121_SW_NVRAM_Config_Error"); + printDebugIfActive(battery2_BMS_a122_SW_BMS_Therm_Irrational, "ERROR: BMS_a122_SW_BMS_Therm_Irrational"); + printDebugIfActive(battery2_BMS_a123_SW_Internal_Isolation, "ERROR: BMS_a123_SW_Internal_Isolation"); + printDebugIfActive(battery2_BMS_a127_SW_shunt_SNA, "ERROR: BMS_a127_SW_shunt_SNA"); + printDebugIfActive(battery2_BMS_a128_SW_shunt_MIA, "ERROR: BMS_a128_SW_shunt_MIA"); + printDebugIfActive(battery2_BMS_a129_SW_VSH_Failure, "ERROR: BMS_a129_SW_VSH_Failure"); + printDebugIfActive(battery2_BMS_a130_IO_CAN_Error, "ERROR: BMS_a130_IO_CAN_Error"); + printDebugIfActive(battery2_BMS_a131_Bleed_FET_Failure, "ERROR: BMS_a131_Bleed_FET_Failure"); + printDebugIfActive(battery2_BMS_a132_HW_BMB_OTP_Uncorrctbl, "ERROR: BMS_a132_HW_BMB_OTP_Uncorrctbl"); + printDebugIfActive(battery2_BMS_a134_SW_Delayed_Ctr_Off, "ERROR: BMS_a134_SW_Delayed_Ctr_Off"); + printDebugIfActive(battery2_BMS_a136_SW_Module_OT_Warning, "ERROR: BMS_a136_SW_Module_OT_Warning"); + printDebugIfActive(battery2_BMS_a137_SW_Brick_UV_Warning, "ERROR: BMS_a137_SW_Brick_UV_Warning"); + printDebugIfActive(battery2_BMS_a139_SW_DC_Link_V_Irrational, "ERROR: BMS_a139_SW_DC_Link_V_Irrational"); + printDebugIfActive(battery2_BMS_a141_SW_BMB_Status_Warning, "ERROR: BMS_a141_SW_BMB_Status_Warning"); + printDebugIfActive(battery2_BMS_a144_Hvp_Config_Mismatch, "ERROR: BMS_a144_Hvp_Config_Mismatch"); + printDebugIfActive(battery2_BMS_a145_SW_SOC_Change, "ERROR: BMS_a145_SW_SOC_Change"); + printDebugIfActive(battery2_BMS_a146_SW_Brick_Overdischarged, "ERROR: BMS_a146_SW_Brick_Overdischarged"); + printDebugIfActive(battery2_BMS_a149_SW_Missing_Config_Block, "ERROR: BMS_a149_SW_Missing_Config_Block"); + printDebugIfActive(battery2_BMS_a151_SW_external_isolation, "ERROR: BMS_a151_SW_external_isolation"); + printDebugIfActive(battery2_BMS_a156_SW_BMB_Vref_bad, "ERROR: BMS_a156_SW_BMB_Vref_bad"); + printDebugIfActive(battery2_BMS_a157_SW_HVP_HVS_Comms, "ERROR: BMS_a157_SW_HVP_HVS_Comms"); + printDebugIfActive(battery2_BMS_a158_SW_HVP_HVI_Comms, "ERROR: BMS_a158_SW_HVP_HVI_Comms"); + printDebugIfActive(battery2_BMS_a159_SW_HVP_ECU_Error, "ERROR: BMS_a159_SW_HVP_ECU_Error"); + printDebugIfActive(battery2_BMS_a161_SW_DI_Open_Request, "ERROR: BMS_a161_SW_DI_Open_Request"); + printDebugIfActive(battery2_BMS_a162_SW_No_Power_For_Support, "ERROR: BMS_a162_SW_No_Power_For_Support"); + printDebugIfActive(battery2_BMS_a163_SW_Contactor_Mismatch, "ERROR: BMS_a163_SW_Contactor_Mismatch"); + printDebugIfActive(battery2_BMS_a164_SW_Uncontrolled_Regen, "ERROR: BMS_a164_SW_Uncontrolled_Regen"); + printDebugIfActive(battery2_BMS_a165_SW_Pack_Partial_Weld, "ERROR: BMS_a165_SW_Pack_Partial_Weld"); + printDebugIfActive(battery2_BMS_a166_SW_Pack_Full_Weld, "ERROR: BMS_a166_SW_Pack_Full_Weld"); + printDebugIfActive(battery2_BMS_a167_SW_FC_Partial_Weld, "ERROR: BMS_a167_SW_FC_Partial_Weld"); + printDebugIfActive(battery2_BMS_a168_SW_FC_Full_Weld, "ERROR: BMS_a168_SW_FC_Full_Weld"); + printDebugIfActive(battery2_BMS_a169_SW_FC_Pack_Weld, "ERROR: BMS_a169_SW_FC_Pack_Weld"); + printDebugIfActive(battery2_BMS_a170_SW_Limp_Mode, "ERROR: BMS_a170_SW_Limp_Mode"); + printDebugIfActive(battery2_BMS_a171_SW_Stack_Voltage_Sense, "ERROR: BMS_a171_SW_Stack_Voltage_Sense"); + printDebugIfActive(battery2_BMS_a174_SW_Charge_Failure, "ERROR: BMS_a174_SW_Charge_Failure"); + printDebugIfActive(battery2_BMS_a176_SW_GracefulPowerOff, "ERROR: BMS_a176_SW_GracefulPowerOff"); + printDebugIfActive(battery2_BMS_a179_SW_Hvp_12V_Fault, "ERROR: BMS_a179_SW_Hvp_12V_Fault"); + printDebugIfActive(battery2_BMS_a180_SW_ECU_reset_blocked, "ERROR: BMS_a180_SW_ECU_reset_blocked"); } #endif //DOUBLE_BATTERY diff --git a/Software/src/communication/can/comm_can.cpp b/Software/src/communication/can/comm_can.cpp index 8fa2ab3d..b9aa2259 100644 --- a/Software/src/communication/can/comm_can.cpp +++ b/Software/src/communication/can/comm_can.cpp @@ -9,11 +9,13 @@ volatile bool send_ok = 0; #ifdef CAN_ADDON static const uint32_t QUARTZ_FREQUENCY = CRYSTAL_FREQUENCY_MHZ * 1000000UL; //MHZ configured in USER_SETTINGS.h -ACAN2515 can(MCP2515_CS, SPI, MCP2515_INT); +SPIClass SPI2515; +ACAN2515 can(MCP2515_CS, SPI2515, MCP2515_INT); static ACAN2515_Buffer16 gBuffer; #endif //CAN_ADDON #ifdef CANFD_ADDON -ACAN2517FD canfd(MCP2517_CS, SPI, MCP2517_INT); +SPIClass SPI2517; +ACAN2517FD canfd(MCP2517_CS, SPI2517, MCP2517_INT); #endif //CANFD_ADDON // Initialization functions @@ -39,20 +41,20 @@ void init_CAN() { logging.println("Dual CAN Bus (ESP32+MCP2515) selected"); #endif // DEBUG_LOG gBuffer.initWithSize(25); - SPI.begin(MCP2515_SCK, MCP2515_MISO, MCP2515_MOSI); - ACAN2515Settings settings(QUARTZ_FREQUENCY, 500UL * 1000UL); // CAN bit rate 500 kb/s - settings.mRequestedMode = ACAN2515Settings::NormalMode; - const uint16_t errorCodeMCP = can.begin(settings, [] { can.isr(); }); - if (errorCodeMCP == 0) { + SPI2515.begin(MCP2515_SCK, MCP2515_MISO, MCP2515_MOSI); + ACAN2515Settings settings2515(QUARTZ_FREQUENCY, 500UL * 1000UL); // CAN bit rate 500 kb/s + settings2515.mRequestedMode = ACAN2515Settings::NormalMode; + const uint16_t errorCode2515 = can.begin(settings2515, [] { can.isr(); }); + if (errorCode2515 == 0) { #ifdef DEBUG_LOG logging.println("Can ok"); #endif // DEBUG_LOG } else { #ifdef DEBUG_LOG logging.print("Error Can: 0x"); - logging.println(errorCodeMCP, HEX); + logging.println(errorCode2515, HEX); #endif // DEBUG_LOG - set_event(EVENT_CANMCP_INIT_FAILURE, (uint8_t)errorCodeMCP); + set_event(EVENT_CANMCP2515_INIT_FAILURE, (uint8_t)errorCode2515); } #endif // CAN_ADDON @@ -60,41 +62,41 @@ void init_CAN() { #ifdef DEBUG_LOG logging.println("CAN FD add-on (ESP32+MCP2517) selected"); #endif // DEBUG_LOG - SPI.begin(MCP2517_SCK, MCP2517_SDO, MCP2517_SDI); - ACAN2517FDSettings settings(CANFD_ADDON_CRYSTAL_FREQUENCY_MHZ, 500 * 1000, - DataBitRateFactor::x4); // Arbitration bit rate: 500 kbit/s, data bit rate: 2 Mbit/s + SPI2517.begin(MCP2517_SCK, MCP2517_SDO, MCP2517_SDI); + ACAN2517FDSettings settings2517(CANFD_ADDON_CRYSTAL_FREQUENCY_MHZ, 500 * 1000, + DataBitRateFactor::x4); // Arbitration bit rate: 500 kbit/s, data bit rate: 2 Mbit/s #ifdef USE_CANFD_INTERFACE_AS_CLASSIC_CAN - settings.mRequestedMode = ACAN2517FDSettings::Normal20B; // ListenOnly / Normal20B / NormalFD -#else // not USE_CANFD_INTERFACE_AS_CLASSIC_CAN - settings.mRequestedMode = ACAN2517FDSettings::NormalFD; // ListenOnly / Normal20B / NormalFD -#endif // USE_CANFD_INTERFACE_AS_CLASSIC_CAN - const uint32_t errorCode = canfd.begin(settings, [] { canfd.isr(); }); + settings2517.mRequestedMode = ACAN2517FDSettings::Normal20B; // ListenOnly / Normal20B / NormalFD +#else // not USE_CANFD_INTERFACE_AS_CLASSIC_CAN + settings2517.mRequestedMode = ACAN2517FDSettings::NormalFD; // ListenOnly / Normal20B / NormalFD +#endif // USE_CANFD_INTERFACE_AS_CLASSIC_CAN + const uint32_t errorCode2517 = canfd.begin(settings2517, [] { canfd.isr(); }); canfd.poll(); - if (errorCode == 0) { + if (errorCode2517 == 0) { #ifdef DEBUG_LOG logging.print("Bit Rate prescaler: "); - logging.println(settings.mBitRatePrescaler); + logging.println(settings2517.mBitRatePrescaler); logging.print("Arbitration Phase segment 1: "); - logging.print(settings.mArbitrationPhaseSegment1); + logging.print(settings2517.mArbitrationPhaseSegment1); logging.print(" segment 2: "); - logging.print(settings.mArbitrationPhaseSegment2); + logging.print(settings2517.mArbitrationPhaseSegment2); logging.print(" SJW: "); - logging.println(settings.mArbitrationSJW); + logging.println(settings2517.mArbitrationSJW); logging.print("Actual Arbitration Bit Rate: "); - logging.print(settings.actualArbitrationBitRate()); + logging.print(settings2517.actualArbitrationBitRate()); logging.print(" bit/s"); logging.print(" (Exact:"); - logging.println(settings.exactArbitrationBitRate() ? "yes)" : "no)"); + logging.println(settings2517.exactArbitrationBitRate() ? "yes)" : "no)"); logging.print("Arbitration Sample point: "); - logging.print(settings.arbitrationSamplePointFromBitStart()); + logging.print(settings2517.arbitrationSamplePointFromBitStart()); logging.println("%"); #endif // DEBUG_LOG } else { #ifdef DEBUG_LOG logging.print("CAN-FD Configuration error 0x"); - logging.println(errorCode, HEX); + logging.println(errorCode2517, HEX); #endif // DEBUG_LOG - set_event(EVENT_CANFD_INIT_FAILURE, (uint8_t)errorCode); + set_event(EVENT_CANMCP2517FD_INIT_FAILURE, (uint8_t)errorCode2517); } #endif // CANFD_ADDON } diff --git a/Software/src/communication/contactorcontrol/comm_contactorcontrol.cpp b/Software/src/communication/contactorcontrol/comm_contactorcontrol.cpp index c09e6c17..9a93936a 100644 --- a/Software/src/communication/contactorcontrol/comm_contactorcontrol.cpp +++ b/Software/src/communication/contactorcontrol/comm_contactorcontrol.cpp @@ -90,9 +90,9 @@ void init_contactors() { // Main functions void handle_contactors() { -#ifdef BYD_SMA +#if defined(BYD_SMA) || defined(SMA_TRIPOWER_CAN) datalayer.system.status.inverter_allows_contactor_closing = digitalRead(INVERTER_CONTACTOR_ENABLE_PIN); -#endif // BYD_SMA +#endif #ifdef CONTACTOR_CONTROL_DOUBLE_BATTERY handle_contactors_battery2(); diff --git a/Software/src/datalayer/datalayer_extended.h b/Software/src/datalayer/datalayer_extended.h index 3b6e57b1..19064035 100644 --- a/Software/src/datalayer/datalayer_extended.h +++ b/Software/src/datalayer/datalayer_extended.h @@ -215,7 +215,12 @@ typedef struct { uint8_t packCtrsClosingAllowed = 0; /** uint8_t */ /** Pyro test in progress */ - uint8_t pyroTestInProgress = 0; + bool pyroTestInProgress = false; + bool battery_packCtrsOpenNowRequested = false; + bool battery_packCtrsOpenRequested = false; + uint8_t battery_packCtrsRequestStatus = 0; + bool battery_packCtrsResetRequestRequired = false; + bool battery_dcLinkAllowedToEnergize = false; uint8_t battery_beginning_of_life = 0; uint8_t battery_battTempPct = 0; uint16_t battery_dcdcLvBusVolt = 0; @@ -231,10 +236,20 @@ typedef struct { uint16_t battery_energy_to_charge_complete_m1 = 0; uint16_t battery_energy_buffer = 0; uint16_t battery_energy_buffer_m1 = 0; - uint16_t battery_full_charge_complete = 0; - uint8_t battery_fully_charged = 0; + uint16_t battery_expected_energy_remaining = 0; + uint16_t battery_expected_energy_remaining_m1 = 0; + bool battery_full_charge_complete = false; + bool battery_fully_charged = false; uint16_t battery_total_discharge = 0; uint16_t battery_total_charge = 0; + uint16_t battery_BrickVoltageMax = 0; + uint16_t battery_BrickVoltageMin = 0; + uint8_t battery_BrickVoltageMaxNum = 0; + uint8_t battery_BrickVoltageMinNum = 0; + uint8_t battery_BrickTempMaxNum = 0; + uint8_t battery_BrickTempMinNum = 0; + uint8_t battery_BrickModelTMax = 0; + uint8_t battery_BrickModelTMin = 0; uint16_t battery_packConfigMultiplexer = 0; uint16_t battery_moduleType = 0; uint16_t battery_reservedConfig = 0; @@ -248,6 +263,123 @@ typedef struct { uint32_t battery_soc_max = 0; uint32_t battery_soc_ave = 0; uint32_t battery_soc_ui = 0; + uint8_t battery_BMS_contactorState = 0; + uint8_t battery_BMS_state = 0; + uint8_t battery_BMS_hvState = 0; + uint16_t battery_BMS_isolationResistance = 0; + uint8_t battery_BMS_uiChargeStatus = 0; + bool battery_BMS_diLimpRequest = false; + uint16_t battery_BMS_chgPowerAvailable = 0; + bool battery_BMS_pcsPwmEnabled = false; + uint8_t battery_PCS_dcdcPrechargeStatus = 0; + uint8_t battery_PCS_dcdc12VSupportStatus = 0; + uint8_t battery_PCS_dcdcHvBusDischargeStatus = 0; + uint8_t battery_PCS_dcdcMainState = 0; + uint8_t battery_PCS_dcdcSubState = 0; + bool battery_PCS_dcdcFaulted = false; + bool battery_PCS_dcdcOutputIsLimited = false; + uint16_t battery_PCS_dcdcMaxOutputCurrentAllowed = 0; + uint8_t battery_PCS_dcdcPrechargeRtyCnt = 0; + uint8_t battery_PCS_dcdc12VSupportRtyCnt = 0; + uint8_t battery_PCS_dcdcDischargeRtyCnt = 0; + uint8_t battery_PCS_dcdcPwmEnableLine = 0; + uint8_t battery_PCS_dcdcSupportingFixedLvTarget = 0; + uint8_t battery_PCS_dcdcPrechargeRestartCnt = 0; + uint8_t battery_PCS_dcdcInitialPrechargeSubState = 0; + uint16_t BMS_maxRegenPower = 0; + uint16_t BMS_maxDischargePower = 0; + uint16_t BMS_maxStationaryHeatPower = 0; + uint16_t BMS_hvacPowerBudget = 0; + uint8_t BMS_notEnoughPowerForHeatPump = 0; + uint8_t BMS_powerLimitState = 0; + uint8_t BMS_inverterTQF = 0; + uint16_t BMS_powerDissipation = 0; + uint8_t BMS_flowRequest = 0; + uint16_t BMS_inletActiveCoolTargetT = 0; + uint16_t BMS_inletPassiveTargetT = 0; + uint16_t BMS_inletActiveHeatTargetT = 0; + uint16_t BMS_packTMin = 0; + uint16_t BMS_packTMax = 0; + bool BMS_pcsNoFlowRequest = false; + bool BMS_noFlowRequest = false; + uint16_t PCS_dcdcTemp = 0; + uint16_t PCS_ambientTemp = 0; + uint16_t PCS_dcdcMaxLvOutputCurrent = 0; + uint16_t PCS_dcdcCurrentLimit = 0; + uint16_t PCS_dcdcLvOutputCurrentTempLimit = 0; + uint16_t PCS_dcdcUnifiedCommand = 0; + uint16_t PCS_dcdcCLAControllerOutput = 0; + uint16_t PCS_dcdcTankVoltage = 0; + uint16_t PCS_dcdcTankVoltageTarget = 0; + uint16_t PCS_dcdcClaCurrentFreq = 0; + uint16_t PCS_dcdcTCommMeasured = 0; + uint16_t PCS_dcdcShortTimeUs = 0; + uint16_t PCS_dcdcHalfPeriodUs = 0; + uint16_t PCS_dcdcIntervalMaxFrequency = 0; + uint16_t PCS_dcdcIntervalMaxHvBusVolt = 0; + uint16_t PCS_dcdcIntervalMaxLvBusVolt = 0; + uint16_t PCS_dcdcIntervalMaxLvOutputCurr = 0; + uint16_t PCS_dcdcIntervalMinFrequency = 0; + uint16_t PCS_dcdcIntervalMinHvBusVolt = 0; + uint16_t PCS_dcdcIntervalMinLvBusVolt = 0; + uint16_t PCS_dcdcIntervalMinLvOutputCurr = 0; + uint32_t PCS_dcdc12vSupportLifetimekWh = 0; + bool HVP_gpioPassivePyroDepl = false; + bool HVP_gpioPyroIsoEn = false; + bool HVP_gpioCpFaultIn = false; + bool HVP_gpioPackContPowerEn = false; + bool HVP_gpioHvCablesOk = false; + bool HVP_gpioHvpSelfEnable = false; + bool HVP_gpioLed = false; + bool HVP_gpioCrashSignal = false; + bool HVP_gpioShuntDataReady = false; + bool HVP_gpioFcContPosAux = false; + bool HVP_gpioFcContNegAux = false; + bool HVP_gpioBmsEout = false; + bool HVP_gpioCpFaultOut = false; + bool HVP_gpioPyroPor = false; + bool HVP_gpioShuntEn = false; + bool HVP_gpioHvpVerEn = false; + bool HVP_gpioPackCoontPosFlywheel = false; + bool HVP_gpioCpLatchEnable = false; + bool HVP_gpioPcsEnable = false; + bool HVP_gpioPcsDcdcPwmEnable = false; + bool HVP_gpioPcsChargePwmEnable = false; + bool HVP_gpioFcContPowerEnable = false; + bool HVP_gpioHvilEnable = false; + bool HVP_gpioSecDrdy = false; + uint16_t HVP_hvp1v5Ref = 0; + uint16_t HVP_shuntCurrentDebug = 0; + bool HVP_packCurrentMia = false; + bool HVP_auxCurrentMia = false; + bool HVP_currentSenseMia = false; + bool HVP_shuntRefVoltageMismatch = false; + bool HVP_shuntThermistorMia = false; + uint8_t HVP_shuntHwMia = 0; + uint16_t HVP_dcLinkVoltage = 0; + uint16_t HVP_packVoltage = 0; + uint16_t HVP_fcLinkVoltage = 0; + uint16_t HVP_packContVoltage = 0; + uint16_t HVP_packNegativeV = 0; + uint16_t HVP_packPositiveV = 0; + uint16_t HVP_pyroAnalog = 0; + uint16_t HVP_dcLinkNegativeV = 0; + uint16_t HVP_dcLinkPositiveV = 0; + uint16_t HVP_fcLinkNegativeV = 0; + uint16_t HVP_fcContCoilCurrent = 0; + uint16_t HVP_fcContVoltage = 0; + uint16_t HVP_hvilInVoltage = 0; + uint16_t HVP_hvilOutVoltage = 0; + uint16_t HVP_fcLinkPositiveV = 0; + uint16_t HVP_packContCoilCurrent = 0; + uint16_t HVP_battery12V = 0; + uint16_t HVP_shuntRefVoltageDbg = 0; + uint16_t HVP_shuntAuxCurrentDbg = 0; + uint16_t HVP_shuntBarTempDbg = 0; + uint16_t HVP_shuntAsicTempDbg = 0; + uint8_t HVP_shuntAuxCurrentStatus = 0; + uint8_t HVP_shuntBarTempStatus = 0; + uint8_t HVP_shuntAsicTempStatus = 0; } DATALAYER_INFO_TESLA; typedef struct { diff --git a/Software/src/devboard/utils/events.cpp b/Software/src/devboard/utils/events.cpp index 021b1660..88546af3 100644 --- a/Software/src/devboard/utils/events.cpp +++ b/Software/src/devboard/utils/events.cpp @@ -140,8 +140,8 @@ void init_events(void) { events.entries[i].MQTTpublished = false; // Not published by default } - events.entries[EVENT_CANFD_INIT_FAILURE].level = EVENT_LEVEL_WARNING; - events.entries[EVENT_CANMCP_INIT_FAILURE].level = EVENT_LEVEL_WARNING; + events.entries[EVENT_CANMCP2517FD_INIT_FAILURE].level = EVENT_LEVEL_WARNING; + events.entries[EVENT_CANMCP2515_INIT_FAILURE].level = EVENT_LEVEL_WARNING; events.entries[EVENT_CANFD_BUFFER_FULL].level = EVENT_LEVEL_WARNING; events.entries[EVENT_CAN_OVERRUN].level = EVENT_LEVEL_INFO; events.entries[EVENT_CANFD_RX_OVERRUN].level = EVENT_LEVEL_WARNING; @@ -264,9 +264,9 @@ void set_event_MQTTpublished(EVENTS_ENUM_TYPE event) { const char* get_event_message_string(EVENTS_ENUM_TYPE event) { switch (event) { - case EVENT_CANFD_INIT_FAILURE: + case EVENT_CANMCP2517FD_INIT_FAILURE: return "CAN-FD initialization failed. Check hardware or bitrate settings"; - case EVENT_CANMCP_INIT_FAILURE: + case EVENT_CANMCP2515_INIT_FAILURE: return "CAN-MCP addon initialization failed. Check hardware"; case EVENT_CANFD_BUFFER_FULL: return "CAN-FD buffer overflowed. Some CAN messages were not sent. Contact developers."; diff --git a/Software/src/devboard/utils/events.h b/Software/src/devboard/utils/events.h index d410d66f..972842fd 100644 --- a/Software/src/devboard/utils/events.h +++ b/Software/src/devboard/utils/events.h @@ -26,8 +26,8 @@ */ #define EVENTS_ENUM_TYPE(XX) \ - XX(EVENT_CANFD_INIT_FAILURE) \ - XX(EVENT_CANMCP_INIT_FAILURE) \ + XX(EVENT_CANMCP2517FD_INIT_FAILURE) \ + XX(EVENT_CANMCP2515_INIT_FAILURE) \ XX(EVENT_CANFD_BUFFER_FULL) \ XX(EVENT_CAN_OVERRUN) \ XX(EVENT_CANFD_RX_OVERRUN) \ diff --git a/Software/src/devboard/webserver/advanced_battery_html.cpp b/Software/src/devboard/webserver/advanced_battery_html.cpp index a634ef7c..c1569714 100644 --- a/Software/src/devboard/webserver/advanced_battery_html.cpp +++ b/Software/src/devboard/webserver/advanced_battery_html.cpp @@ -349,6 +349,8 @@ String advanced_battery_processor(const String& var) { static_cast(datalayer_extended.tesla.battery_energy_to_charge_complete_m1) * 0.02; float energy_buffer = static_cast(datalayer_extended.tesla.battery_energy_buffer) * 0.1; float energy_buffer_m1 = static_cast(datalayer_extended.tesla.battery_energy_buffer_m1) * 0.01; + float expected_energy_remaining_m1 = + static_cast(datalayer_extended.tesla.battery_expected_energy_remaining_m1) * 0.02; float total_discharge = static_cast(datalayer_extended.tesla.battery_total_discharge); float total_charge = static_cast(datalayer_extended.tesla.battery_total_charge); float packMass = static_cast(datalayer_extended.tesla.battery_packMass); @@ -362,50 +364,85 @@ String advanced_battery_processor(const String& var) { float soc_max = static_cast(datalayer_extended.tesla.battery_soc_max) * 0.1; float soc_min = static_cast(datalayer_extended.tesla.battery_soc_min) * 0.1; float soc_ui = static_cast(datalayer_extended.tesla.battery_soc_ui) * 0.1; - - // Comment what data you would like to dislay, order can be changed. - content += "

Battery Beginning of Life: " + String(beginning_of_life) + " kWh

"; - content += "

BattTempPct: " + String(battTempPct) + "

"; - content += "

PCS Lv Bus: " + String(dcdcLvBusVolt) + " V

"; - content += "

PCS Hv Bus: " + String(dcdcHvBusVolt) + " V

"; - content += "

PCS Lv Output: " + String(dcdcLvOutputCurrent) + " A

"; - - //if using older BMS <2021 and comment 0x352 without MUX - //content += "

Nominal Full Pack Energy: " + String(nominal_full_pack_energy) + " kWh

"; - //content += "

Nominal Energy Remaining: " + String(nominal_energy_remaining) + " kWh

"; - //content += "

Ideal Energy Remaining: " + String(ideal_energy_remaining) + " kWh

"; - //content += "

Energy to Charge Complete: " + String(energy_to_charge_complete) + " kWh

"; - //content += "

Energy Buffer: " + String(energy_buffer) + " kWh

"; - - //if using newer BMS >2021 and comment 0x352 with MUX - content += "

Nominal Full Pack Energy m0: " + String(nominal_full_pack_energy_m0) + " kWh

"; - content += "

Nominal Energy Remaining m0: " + String(nominal_energy_remaining_m0) + " kWh

"; - content += "

Ideal Energy Remaining m0: " + String(ideal_energy_remaining_m0) + " kWh

"; - content += "

Energy to Charge Complete m1: " + String(energy_to_charge_complete_m1) + " kWh

"; - content += "

Energy Buffer m1: " + String(energy_buffer_m1) + " kWh

"; - - content += "

packConfigMultiplexer: " + String(datalayer_extended.tesla.battery_packConfigMultiplexer) + "

"; - content += "

moduleType: " + String(datalayer_extended.tesla.battery_moduleType) + "

"; - content += "

reserveConfig: " + String(datalayer_extended.tesla.battery_reservedConfig) + "

"; - content += "

Full Charge Complete: " + String(datalayer_extended.tesla.battery_full_charge_complete) + "

"; - content += "

Total Discharge: " + String(total_discharge) + " kWh

"; - content += "

Total Charge: " + String(total_charge) + " kWh

"; - content += "

Battery Pack Mass: " + String(packMass) + " KG

"; - content += "

Platform Max Bus Voltage: " + String(platformMaxBusVoltage) + " V

"; - content += "

BMS Min Voltage: " + String(bms_min_voltage) + " V

"; - content += "

BMS Max Voltage: " + String(bms_max_voltage) + " V

"; - content += "

Max Charge Current: " + String(max_charge_current) + " A

"; - content += "

Max Discharge Current: " + String(max_discharge_current) + " A

"; - content += "

Battery SOC Ave: " + String(soc_ave) + "

"; - content += "

Battery SOC Max: " + String(soc_max) + "

"; - content += "

Battery SOC Min: " + String(soc_min) + "

"; - content += "

Battery SOC UI: " + String(soc_ui) + "

"; + float BrickVoltageMax = static_cast(datalayer_extended.tesla.battery_BrickVoltageMax) * 0.002; + float BrickVoltageMin = static_cast(datalayer_extended.tesla.battery_BrickVoltageMin) * 0.002; + float BrickModelTMax = static_cast(datalayer_extended.tesla.battery_BrickTempMinNum) * 0.5 - 40; + float BrickModelTMin = static_cast(datalayer_extended.tesla.battery_BrickModelTMin) * 0.5 - 40; + float isolationResistance = static_cast(datalayer_extended.tesla.battery_BMS_isolationResistance) * 10; + float PCS_dcdcMaxOutputCurrentAllowed = + static_cast(datalayer_extended.tesla.battery_PCS_dcdcMaxOutputCurrentAllowed) * 0.1; + float PCS_dcdcTemp = static_cast(datalayer_extended.tesla.PCS_dcdcTemp) * 0.1 - 40; + float PCS_ambientTemp = static_cast(datalayer_extended.tesla.PCS_ambientTemp) * 0.1 - 40; + float BMS_maxRegenPower = static_cast(datalayer_extended.tesla.BMS_maxRegenPower) * 0.01; + float BMS_maxDischargePower = static_cast(datalayer_extended.tesla.BMS_maxDischargePower) * 0.013; + float BMS_maxStationaryHeatPower = static_cast(datalayer_extended.tesla.BMS_maxStationaryHeatPower) * 0.01; + float BMS_hvacPowerBudget = static_cast(datalayer_extended.tesla.BMS_hvacPowerBudget) * 0.02; + float BMS_powerDissipation = static_cast(datalayer_extended.tesla.BMS_powerDissipation) * 0.02; + float BMS_flowRequest = static_cast(datalayer_extended.tesla.BMS_flowRequest) * 0.3; + float BMS_inletActiveCoolTargetT = + static_cast(datalayer_extended.tesla.BMS_inletActiveCoolTargetT) * 0.25 - 25; + float BMS_inletPassiveTargetT = static_cast(datalayer_extended.tesla.BMS_inletPassiveTargetT) * 0.25 - 25; + float BMS_inletActiveHeatTargetT = + static_cast(datalayer_extended.tesla.BMS_inletActiveHeatTargetT) * 0.25 - 25; + float BMS_packTMin = static_cast(datalayer_extended.tesla.BMS_packTMin) * 0.25 - 25; + float BMS_packTMax = static_cast(datalayer_extended.tesla.BMS_packTMax) * 0.25 - 25; + float PCS_dcdcMaxLvOutputCurrent = static_cast(datalayer_extended.tesla.PCS_dcdcMaxLvOutputCurrent) * 0.1; + float PCS_dcdcCurrentLimit = static_cast(datalayer_extended.tesla.PCS_dcdcCurrentLimit) * 0.1; + float PCS_dcdcLvOutputCurrentTempLimit = + static_cast(datalayer_extended.tesla.PCS_dcdcLvOutputCurrentTempLimit) * 0.1; + float PCS_dcdcUnifiedCommand = static_cast(datalayer_extended.tesla.PCS_dcdcUnifiedCommand) * 0.001; + float PCS_dcdcCLAControllerOutput = + static_cast(datalayer_extended.tesla.PCS_dcdcCLAControllerOutput * 0.001); + float PCS_dcdcTankVoltage = static_cast(datalayer_extended.tesla.PCS_dcdcTankVoltage); + float PCS_dcdcTankVoltageTarget = static_cast(datalayer_extended.tesla.PCS_dcdcTankVoltageTarget); + float PCS_dcdcClaCurrentFreq = static_cast(datalayer_extended.tesla.PCS_dcdcClaCurrentFreq) * 0.0976563; + float PCS_dcdcTCommMeasured = static_cast(datalayer_extended.tesla.PCS_dcdcTCommMeasured) * 0.00195313; + float PCS_dcdcShortTimeUs = static_cast(datalayer_extended.tesla.PCS_dcdcShortTimeUs) * 0.000488281; + float PCS_dcdcHalfPeriodUs = static_cast(datalayer_extended.tesla.PCS_dcdcHalfPeriodUs) * 0.000488281; + float PCS_dcdcIntervalMaxFrequency = static_cast(datalayer_extended.tesla.PCS_dcdcIntervalMaxFrequency); + float PCS_dcdcIntervalMaxHvBusVolt = + static_cast(datalayer_extended.tesla.PCS_dcdcIntervalMaxHvBusVolt) * 0.1; + float PCS_dcdcIntervalMaxLvBusVolt = + static_cast(datalayer_extended.tesla.PCS_dcdcIntervalMaxLvBusVolt) * 0.1; + float PCS_dcdcIntervalMaxLvOutputCurr = + static_cast(datalayer_extended.tesla.PCS_dcdcIntervalMaxLvOutputCurr); + float PCS_dcdcIntervalMinFrequency = static_cast(datalayer_extended.tesla.PCS_dcdcIntervalMinFrequency); + float PCS_dcdcIntervalMinHvBusVolt = + static_cast(datalayer_extended.tesla.PCS_dcdcIntervalMinHvBusVolt) * 0.1; + float PCS_dcdcIntervalMinLvBusVolt = + static_cast(datalayer_extended.tesla.PCS_dcdcIntervalMinLvBusVolt) * 0.1; + float PCS_dcdcIntervalMinLvOutputCurr = + static_cast(datalayer_extended.tesla.PCS_dcdcIntervalMinLvOutputCurr); + float PCS_dcdc12vSupportLifetimekWh = + static_cast(datalayer_extended.tesla.PCS_dcdc12vSupportLifetimekWh) * 0.01; + float HVP_hvp1v5Ref = static_cast(datalayer_extended.tesla.HVP_hvp1v5Ref) * 0.1; + float HVP_shuntCurrentDebug = static_cast(datalayer_extended.tesla.HVP_shuntCurrentDebug) * 0.1; + float HVP_dcLinkVoltage = static_cast(datalayer_extended.tesla.HVP_dcLinkVoltage) * 0.1; + float HVP_packVoltage = static_cast(datalayer_extended.tesla.HVP_packVoltage) * 0.1; + float HVP_fcLinkVoltage = static_cast(datalayer_extended.tesla.HVP_fcLinkVoltage) * 0.1; + float HVP_packContVoltage = static_cast(datalayer_extended.tesla.HVP_packContVoltage) * 0.1; + float HVP_packNegativeV = static_cast(datalayer_extended.tesla.HVP_packNegativeV) * 0.1; + float HVP_packPositiveV = static_cast(datalayer_extended.tesla.HVP_packPositiveV) * 0.1; + float HVP_pyroAnalog = static_cast(datalayer_extended.tesla.HVP_pyroAnalog) * 0.1; + float HVP_dcLinkNegativeV = static_cast(datalayer_extended.tesla.HVP_dcLinkNegativeV) * 0.1; + float HVP_dcLinkPositiveV = static_cast(datalayer_extended.tesla.HVP_dcLinkPositiveV) * 0.1; + float HVP_fcLinkNegativeV = static_cast(datalayer_extended.tesla.HVP_fcLinkNegativeV) * 0.1; + float HVP_fcContCoilCurrent = static_cast(datalayer_extended.tesla.HVP_fcContCoilCurrent) * 0.1; + float HVP_fcContVoltage = static_cast(datalayer_extended.tesla.HVP_fcContVoltage) * 0.1; + float HVP_hvilInVoltage = static_cast(datalayer_extended.tesla.HVP_hvilInVoltage) * 0.1; + float HVP_hvilOutVoltage = static_cast(datalayer_extended.tesla.HVP_hvilOutVoltage) * 0.1; + float HVP_fcLinkPositiveV = static_cast(datalayer_extended.tesla.HVP_fcLinkPositiveV) * 0.1; + float HVP_packContCoilCurrent = static_cast(datalayer_extended.tesla.HVP_packContCoilCurrent) * 0.1; + float HVP_battery12V = static_cast(datalayer_extended.tesla.HVP_battery12V) * 0.1; + float HVP_shuntRefVoltageDbg = static_cast(datalayer_extended.tesla.HVP_shuntRefVoltageDbg) * 0.001; + float HVP_shuntAuxCurrentDbg = static_cast(datalayer_extended.tesla.HVP_shuntAuxCurrentDbg) * 0.1; + float HVP_shuntBarTempDbg = static_cast(datalayer_extended.tesla.HVP_shuntBarTempDbg) * 0.01; + float HVP_shuntAsicTempDbg = static_cast(datalayer_extended.tesla.HVP_shuntAsicTempDbg) * 0.01; static const char* contactorText[] = {"UNKNOWN(0)", "OPEN", "CLOSING", "BLOCKED", "OPENING", "CLOSED", "UNKNOWN(6)", "WELDED", "POS_CL", "NEG_CL", "UNKNOWN(10)", "UNKNOWN(11)", "UNKNOWN(12)"}; - content += "

Contactor Status: " + String(contactorText[datalayer_extended.tesla.status_contactor]) + "

"; - static const char* hvilStatusState[] = {"NOT OK", + static const char* hvilStatusState[] = {"NOT Ok", "STATUS_OK", "CURRENT_SOURCE_FAULT", "INTERNAL_OPEN_FAULT", @@ -421,17 +458,292 @@ String advanced_battery_processor(const String& var) { "UNKNOWN(13)", "UNKNOWN(14)", "UNKNOWN(15)"}; - content += "

HVIL: " + String(hvilStatusState[datalayer_extended.tesla.hvil_status]) + "

"; static const char* contactorState[] = {"SNA", "OPEN", "PRECHARGE", "BLOCKED", "PULLED_IN", "OPENING", "ECONOMIZED", "WELDED", "UNKNOWN(8)", "UNKNOWN(9)", "UNKNOWN(10)", "UNKNOWN(11)"}; + static const char* BMS_state[] = {"STANDBY", "DRIVE", "SUPPORT", "CHARGE", "FEIM", + "CLEAR_FAULT", "FAULT", "WELD", "TEST", "SNA"}; + static const char* BMS_contactorState[] = {"SNA", "OPEN", "OPENING", "CLOSING", "CLOSED", "WELDED", "BLOCKED"}; + static const char* BMS_hvState[] = {"DOWN", "COMING_UP", "GOING_DOWN", "UP_FOR_DRIVE", + "UP_FOR_CHARGE", "UP_FOR_DC_CHARGE", "UP"}; + static const char* BMS_uiChargeStatus[] = {"DISCONNECTED", "NO_POWER", "ABOUT_TO_CHARGE", + "CHARGING", "CHARGE_COMPLETE", "CHARGE_STOPPED"}; + static const char* PCS_dcdcStatus[] = {"IDLE", "ACTIVE", "FAULTED"}; + static const char* PCS_dcdcMainState[] = {"STANDBY", "12V_SUPPORT_ACTIVE", "PRECHARGE_STARTUP", + "PRECHARGE_ACTIVE", "DIS_HVBUS_ACTIVE", "SHUTDOWN", + "FAULTED"}; + static const char* PCS_dcdcSubState[] = {"PWR_UP_INIT", + "STANDBY", + "12V_SUPPORT_ACTIVE", + "DIS_HVBUS", + "PCHG_FAST_DIS_HVBUS", + "PCHG_SLOW_DIS_HVBUS", + "PCHG_DWELL_CHARGE", + "PCHG_DWELL_WAIT", + "PCHG_DI_RECOVERY_WAIT", + "PCHG_ACTIVE", + "PCHG_FLT_FAST_DIS_HVBUS", + "SHUTDOWN", + "12V_SUPPORT_FAULTED", + "DIS_HVBUS_FAULTED", + "PCHG_FAULTED", + "CLEAR_FAULTS", + "FAULTED", + "NUM"}; + static const char* BMS_powerLimitState[] = {"NOT_CALCULATED_FOR_DRIVE", "CALCULATED_FOR_DRIVE"}; + static const char* HVP_status[] = {"INVALID", "NOT_AVAILABLE", "STALE", "VALID"}; + static const char* HVP_contactor[] = {"NOT_ACTIVE", "ACTIVE", "COMPLETED"}; + static const char* falseTrue[] = {"False", "True"}; + static const char* noYes[] = {"No", "Yes"}; + static const char* Fault[] = {"NOT_ACTIVE", "ACTIVE"}; + //0x20A 522 HVP_contatorState + content += "

Contactor Status: " + String(contactorText[datalayer_extended.tesla.status_contactor]) + "

"; + content += "

HVIL: " + String(hvilStatusState[datalayer_extended.tesla.hvil_status]) + "

"; content += "

Negative contactor: " + String(contactorState[datalayer_extended.tesla.packContNegativeState]) + "

"; content += "

Positive contactor: " + String(contactorState[datalayer_extended.tesla.packContPositiveState]) + "

"; - static const char* falseTrue[] = {"False", "True"}; - content += "

Closing allowed?: " + String(falseTrue[datalayer_extended.tesla.packCtrsClosingAllowed]) + "

"; - content += "

Pyrotest: " + String(falseTrue[datalayer_extended.tesla.pyroTestInProgress]) + "

"; + content += + "

Closing allowed?: " + String(noYes[datalayer_extended.tesla.packCtrsClosingAllowed]) + "

"; //bool + content += + "

Pyrotest in Progress: " + String(noYes[datalayer_extended.tesla.pyroTestInProgress]) + "

"; //bool + content += "

Contactors Open Now Requested: " + + String(noYes[datalayer_extended.tesla.battery_packCtrsOpenNowRequested]) + "

"; //bool + content += + "

Contactors Open Requested: " + String(noYes[datalayer_extended.tesla.battery_packCtrsOpenRequested]) + + "

"; //bool + content += "

Contactors Request Status: " + + String(HVP_contactor[datalayer_extended.tesla.battery_packCtrsRequestStatus]) + "

"; + content += "

Contactors Reset Request Required: " + + String(noYes[datalayer_extended.tesla.battery_packCtrsResetRequestRequired]) + "

"; //bool + content += + "

DC Link Allowed to Energize: " + String(noYes[datalayer_extended.tesla.battery_dcLinkAllowedToEnergize]) + + "

"; //bool + // Comment what data you would like to dislay, order can be changed. + //0x292 658 BMS_socStates + content += "

Battery Beginning of Life: " + String(beginning_of_life) + " KWh

"; + content += "

BattTempPct: " + String(battTempPct) + "

"; + content += "

Battery SOC Ave: " + String(soc_ave) + "

"; + content += "

Battery SOC Max: " + String(soc_max) + "

"; + content += "

Battery SOC Min: " + String(soc_min) + "

"; + content += "

Battery SOC UI: " + String(soc_ui) + "

"; + //0x2B4 PCS_dcdcRailStatus + content += "

PCS Lv Bus: " + String(dcdcLvBusVolt) + " V

"; + content += "

PCS Hv Bus: " + String(dcdcHvBusVolt) + " V

"; + content += "

PCS Lv Output: " + String(dcdcLvOutputCurrent) + " A

"; + //0x2A4 676 PCS_thermalStatus + content += "

PCS dcdc Temp: " + String(PCS_dcdcTemp) + " DegC

"; + content += "

PCS Ambient Temp: " + String(PCS_ambientTemp) + " DegC

"; + //0x224 548 PCS_dcdcStatus + content += + "

Precharge Status: " + String(PCS_dcdcStatus[datalayer_extended.tesla.battery_PCS_dcdcPrechargeStatus]) + + "

"; + content += + "

12V Support Status: " + String(PCS_dcdcStatus[datalayer_extended.tesla.battery_PCS_dcdc12VSupportStatus]) + + "

"; + content += "

HV Bus Discharge Status: " + + String(PCS_dcdcStatus[datalayer_extended.tesla.battery_PCS_dcdcHvBusDischargeStatus]) + "

"; + content += + "

Main State: " + String(PCS_dcdcMainState[datalayer_extended.tesla.battery_PCS_dcdcMainState]) + "

"; + content += + "

Sub State: " + String(PCS_dcdcSubState[datalayer_extended.tesla.battery_PCS_dcdcSubState]) + "

"; + content += "

PCS Faulted: " + String(Fault[datalayer_extended.tesla.battery_PCS_dcdcFaulted]) + "

"; //bool + content += "

Output Is Limited: " + String(Fault[datalayer_extended.tesla.battery_PCS_dcdcOutputIsLimited]) + + "

"; //bool + content += "

Max Output Current Allowed: " + String(PCS_dcdcMaxOutputCurrentAllowed) + " A

"; + content += "

Precharge Rty Cnt: " + String(falseTrue[datalayer_extended.tesla.battery_PCS_dcdcPrechargeRtyCnt]) + + "

"; //bool + content += + "

12V Support Rty Cnt: " + String(falseTrue[datalayer_extended.tesla.battery_PCS_dcdc12VSupportRtyCnt]) + + "

"; // bool + content += "

Discharge Rty Cnt: " + String(falseTrue[datalayer_extended.tesla.battery_PCS_dcdcDischargeRtyCnt]) + + "

"; //bool + content += "

PWM Enable Line: " + String(Fault[datalayer_extended.tesla.battery_PCS_dcdcPwmEnableLine]) + + "

"; //bool + content += "

Supporting Fixed LV Target: " + + String(Fault[datalayer_extended.tesla.battery_PCS_dcdcSupportingFixedLvTarget]) + "

"; //bool + content += "

Precharge Restart Cnt: " + + String(falseTrue[datalayer_extended.tesla.battery_PCS_dcdcPrechargeRestartCnt]) + "

"; //bool + content += "

Initial Precharge Substate: " + + String(PCS_dcdcSubState[datalayer_extended.tesla.battery_PCS_dcdcInitialPrechargeSubState]) + "

"; + //0x2C4 708 PCS_logging + content += "

PCS_dcdcMaxLvOutputCurrent: " + String(PCS_dcdcMaxLvOutputCurrent) + " A

"; + content += "

PCS_dcdcCurrentLimit: " + String(PCS_dcdcCurrentLimit) + " A

"; + content += "

PCS_dcdcLvOutputCurrentTempLimit: " + String(PCS_dcdcLvOutputCurrentTempLimit) + " A

"; + content += "

PCS_dcdcUnifiedCommand: " + String(PCS_dcdcUnifiedCommand) + "

"; + content += "

PCS_dcdcCLAControllerOutput: " + String(PCS_dcdcCLAControllerOutput) + "

"; + content += "

PCS_dcdcTankVoltage: " + String(PCS_dcdcTankVoltage) + " V

"; + content += "

PCS_dcdcTankVoltageTarget: " + String(PCS_dcdcTankVoltageTarget) + " V

"; + content += "

PCS_dcdcClaCurrentFreq: " + String(PCS_dcdcClaCurrentFreq) + " kHz

"; + content += "

PCS_dcdcTCommMeasured: " + String(PCS_dcdcTCommMeasured) + " us

"; + content += "

PCS_dcdcShortTimeUs: " + String(PCS_dcdcShortTimeUs) + " us

"; + content += "

PCS_dcdcHalfPeriodUs: " + String(PCS_dcdcHalfPeriodUs) + " us

"; + content += "

PCS_dcdcIntervalMaxFrequency: " + String(PCS_dcdcIntervalMaxFrequency) + " kHz

"; + content += "

PCS_dcdcIntervalMaxHvBusVolt: " + String(PCS_dcdcIntervalMaxHvBusVolt) + " V

"; + content += "

PCS_dcdcIntervalMaxLvBusVolt: " + String(PCS_dcdcIntervalMaxLvBusVolt) + " V

"; + content += "

PCS_dcdcIntervalMaxLvOutputCurr: " + String(PCS_dcdcIntervalMaxLvOutputCurr) + " A

"; + content += "

PCS_dcdcIntervalMinFrequency: " + String(PCS_dcdcIntervalMinFrequency) + " kHz

"; + content += "

PCS_dcdcIntervalMinHvBusVolt: " + String(PCS_dcdcIntervalMinHvBusVolt) + " V

"; + content += "

PCS_dcdcIntervalMinLvBusVolt: " + String(PCS_dcdcIntervalMinLvBusVolt) + " V

"; + content += "

PCS_dcdcIntervalMinLvOutputCurr: " + String(PCS_dcdcIntervalMinLvOutputCurr) + " A

"; + content += "

PCS_dcdc12vSupportLifetimekWh: " + String(PCS_dcdc12vSupportLifetimekWh) + " kWh

"; + //0x3D2 978 BMS_kwhCounter + content += "

Total Discharge: " + String(total_discharge) + " KWh

"; + content += "

Total Charge: " + String(total_charge) + " KWh

"; + //0x212 530 BMS_status + content += "

Isolation Resistance: " + String(isolationResistance) + " kOhms

"; + content += + "

BMS Contactor State: " + String(BMS_contactorState[datalayer_extended.tesla.battery_BMS_contactorState]) + + "

"; + content += "

BMS State: " + String(BMS_state[datalayer_extended.tesla.battery_BMS_state]) + "

"; + content += "

BMS HV State: " + String(BMS_hvState[datalayer_extended.tesla.battery_BMS_hvState]) + "

"; + content += "

BMS UI Charge Status: " + String(BMS_uiChargeStatus[datalayer_extended.tesla.battery_BMS_hvState]) + + "

"; + content += "

BMS PCS PWM Enabled: " + String(Fault[datalayer_extended.tesla.battery_BMS_pcsPwmEnabled]) + + "

"; //bool + //0x352 850 BMS_energyStatus + content += "

Early BMS 0x352:

"; //if using older BMS <2021 and comment 0x352 without MUX + content += "

Calculated SOH: " + String(nominal_full_pack_energy * 100 / beginning_of_life) + "

"; + content += "

Nominal Full Pack Energy: " + String(nominal_full_pack_energy) + " KWh

"; + content += "

Nominal Energy Remaining: " + String(nominal_energy_remaining) + " KWh

"; + content += "

Ideal Energy Remaining: " + String(ideal_energy_remaining) + " KWh

"; + content += "

Energy to Charge Complete: " + String(energy_to_charge_complete) + " KWh

"; + content += "

Energy Buffer: " + String(energy_buffer) + " KWh

"; + content += "

Full Charge Complete: " + String(noYes[datalayer_extended.tesla.battery_full_charge_complete]) + + "

"; //bool + //0x352 850 BMS_energyStatus + content += "

Late BMS 0x352 with Mux:

"; //if using newer BMS >2021 and comment 0x352 with MUX + content += "

Calculated SOH: " + String(nominal_full_pack_energy_m0 * 100 / beginning_of_life) + "

"; + content += "

Nominal Full Pack Energy: " + String(nominal_full_pack_energy_m0) + " KWh

"; + content += "

Nominal Energy Remaining: " + String(nominal_energy_remaining_m0) + " KWh

"; + content += "

Ideal Energy Remaining: " + String(ideal_energy_remaining_m0) + " KWh

"; + content += "

Energy to Charge Complete: " + String(energy_to_charge_complete_m1) + " KWh

"; + content += "

Energy Buffer: " + String(energy_buffer_m1) + " KWh

"; + content += "

Expected Energy Remaining: " + String(expected_energy_remaining_m1) + " KWh

"; + content += "

Fully Charged: " + String(noYes[datalayer_extended.tesla.battery_fully_charged]) + "

"; //bool + //0x392 BMS_packConfig + //content += "

packConfigMultiplexer: " + String(datalayer_extended.tesla.battery_packConfigMultiplexer) + "

"; + //content += "

moduleType: " + String(datalayer_extended.tesla.battery_moduleType) + "

"; + //content += "

reserveConfig: " + String(datalayer_extended.tesla.battery_reservedConfig) + "

"; + content += "

Battery Pack Mass: " + String(packMass) + " KG

"; + content += "

Platform Max Bus Voltage: " + String(platformMaxBusVoltage) + " V

"; + //0x2D2 722 BMSVAlimits + content += "

BMS Min Voltage: " + String(bms_min_voltage) + " V

"; + content += "

BMS Max Voltage: " + String(bms_max_voltage) + " V

"; + content += "

Max Charge Current: " + String(max_charge_current) + " A

"; + content += "

Max Discharge Current: " + String(max_discharge_current) + " A

"; + //0x332 818 BMS_bmbMinMax + content += "

Brick Voltage Max: " + String(BrickVoltageMax) + " V

"; + content += "

Brick Voltage Min: " + String(BrickVoltageMin) + " V

"; + content += "

Brick Temp Max Num: " + String(datalayer_extended.tesla.battery_BrickTempMaxNum) + "

"; + content += "

Brick Temp Min Num: " + String(datalayer_extended.tesla.battery_BrickTempMinNum) + "

"; + content += "

Brick Model Temp Max: " + String(BrickModelTMax) + " C

"; + content += "

Brick Model Temp Min: " + String(BrickModelTMin) + " C

"; + //0x252 594 BMS_powerAvailable + content += "

Max Regen Power: " + String(BMS_maxRegenPower) + " KW

"; + content += "

Max Discharge Power: " + String(BMS_maxDischargePower) + " KW

"; + content += "

Max Stationary Heat Power: " + String(BMS_maxStationaryHeatPower) + " KWh

"; + content += "

HVAC Power Budget: " + String(BMS_hvacPowerBudget) + " KW

"; + content += "

Not Enough Power For Heat Pump: " + + String(falseTrue[datalayer_extended.tesla.BMS_notEnoughPowerForHeatPump]) + "

"; //bool + content += + "

Power Limit State: " + String(BMS_powerLimitState[datalayer_extended.tesla.BMS_powerLimitState]) + "

"; + content += "

Inverter TQF: " + String(datalayer_extended.tesla.BMS_inverterTQF) + "

"; + //0x312 786 BMS_thermalStatus + content += "

Power Dissipation: " + String(BMS_powerDissipation) + " kW

"; + content += "

Flow Request: " + String(BMS_flowRequest) + " LPM

"; + content += "

Inlet Active Cool Target Temp: " + String(BMS_inletActiveCoolTargetT) + " DegC

"; + content += "

Inlet Passive Target Temp: " + String(BMS_inletPassiveTargetT) + " DegC

"; + content += "

Inlet Active Heat Target Temp: " + String(BMS_inletActiveHeatTargetT) + " DegC

"; + content += "

Pack Temp Min: " + String(BMS_packTMin) + " DegC

"; + content += "

Pack Temp Max: " + String(BMS_packTMax) + " DegC

"; + content += + "

PCS No Flow Request: " + String(Fault[datalayer_extended.tesla.BMS_pcsNoFlowRequest]) + "

"; //bool + content += + "

BMS No Flow Request: " + String(Fault[datalayer_extended.tesla.BMS_noFlowRequest]) + "

"; //bool + //0x7AA 1962 HVP_debugMessage + content += "

HVP_gpioPassivePyroDepl: " + String(Fault[datalayer_extended.tesla.HVP_gpioPassivePyroDepl]) + + "

"; //bool + content += "

HVP_gpioPyroIsoEn: " + String(Fault[datalayer_extended.tesla.HVP_gpioPyroIsoEn]) + "

"; //bool + content += "

HVP_gpioCpFaultIn: " + String(Fault[datalayer_extended.tesla.HVP_gpioCpFaultIn]) + "

"; //bool + content += "

HVP_gpioPackContPowerEn: " + String(Fault[datalayer_extended.tesla.HVP_gpioPackContPowerEn]) + + "

"; //bool + content += + "

HVP_gpioHvCablesOk: " + String(Fault[datalayer_extended.tesla.HVP_gpioHvCablesOk]) + "

"; //bool + content += + "

HVP_gpioHvpSelfEnable: " + String(Fault[datalayer_extended.tesla.HVP_gpioHvpSelfEnable]) + "

"; //bool + content += "

HVP_gpioLed: " + String(Fault[datalayer_extended.tesla.HVP_gpioLed]) + "

"; //bool + content += + "

HVP_gpioCrashSignal: " + String(Fault[datalayer_extended.tesla.HVP_gpioCrashSignal]) + "

"; //bool + content += "

HVP_gpioShuntDataReady: " + String(Fault[datalayer_extended.tesla.HVP_gpioShuntDataReady]) + + "

"; //bool + content += + "

HVP_gpioFcContPosAux: " + String(Fault[datalayer_extended.tesla.HVP_gpioFcContPosAux]) + "

"; //bool + content += + "

HVP_gpioFcContNegAux: " + String(Fault[datalayer_extended.tesla.HVP_gpioFcContNegAux]) + "

"; //bool + content += "

HVP_gpioBmsEout: " + String(Fault[datalayer_extended.tesla.HVP_gpioBmsEout]) + "

"; //bool + content += + "

HVP_gpioCpFaultOut: " + String(Fault[datalayer_extended.tesla.HVP_gpioCpFaultOut]) + "

"; //bool + content += "

HVP_gpioPyroPor: " + String(Fault[datalayer_extended.tesla.HVP_gpioPyroPor]) + "

"; //bool + content += "

HVP_gpioShuntEn: " + String(Fault[datalayer_extended.tesla.HVP_gpioShuntEn]) + "

"; //bool + content += "

HVP_gpioHvpVerEn: " + String(Fault[datalayer_extended.tesla.HVP_gpioHvpVerEn]) + "

"; //bool + content += + "

HVP_gpioPackCoontPosFlywheel: " + String(Fault[datalayer_extended.tesla.HVP_gpioPackCoontPosFlywheel]) + + "

"; //bool + content += + "

HVP_gpioCpLatchEnable: " + String(Fault[datalayer_extended.tesla.HVP_gpioCpLatchEnable]) + "

"; //bool + content += "

HVP_gpioPcsEnable: " + String(Fault[datalayer_extended.tesla.HVP_gpioPcsEnable]) + "

"; //bool + content += "

HVP_gpioPcsDcdcPwmEnable: " + String(Fault[datalayer_extended.tesla.HVP_gpioPcsDcdcPwmEnable]) + + "

"; //bool + content += "

HVP_gpioPcsChargePwmEnable: " + String(Fault[datalayer_extended.tesla.HVP_gpioPcsChargePwmEnable]) + + "

"; //bool + content += "

HVP_gpioFcContPowerEnable: " + String(Fault[datalayer_extended.tesla.HVP_gpioFcContPowerEnable]) + + "

"; //bool + content += + "

HVP_gpioHvilEnable: " + String(Fault[datalayer_extended.tesla.HVP_gpioHvilEnable]) + "

"; //bool + content += "

HVP_gpioSecDrdy: " + String(Fault[datalayer_extended.tesla.HVP_gpioSecDrdy]) + "

"; //bool + content += "

HVP_hvp1v5Ref: " + String(HVP_hvp1v5Ref) + " V

"; + content += "

HVP_shuntCurrentDebug: " + String(HVP_shuntCurrentDebug) + " A

"; + content += + "

HVP_packCurrentMia: " + String(noYes[datalayer_extended.tesla.HVP_packCurrentMia]) + "

"; //bool + content += "

HVP_auxCurrentMia: " + String(noYes[datalayer_extended.tesla.HVP_auxCurrentMia]) + "

"; //bool + content += + "

HVP_currentSenseMia: " + String(noYes[datalayer_extended.tesla.HVP_currentSenseMia]) + "

"; //bool + content += + "

HVP_shuntRefVoltageMismatch: " + String(noYes[datalayer_extended.tesla.HVP_shuntRefVoltageMismatch]) + + "

"; //bool + content += "

HVP_shuntThermistorMia: " + String(noYes[datalayer_extended.tesla.HVP_shuntThermistorMia]) + + "

"; //bool + content += "

HVP_shuntHwMia: " + String(noYes[datalayer_extended.tesla.HVP_shuntHwMia]) + "

"; //bool + content += "

HVP_dcLinkVoltage: " + String(HVP_dcLinkVoltage) + " V

"; + content += "

HVP_packVoltage: " + String(HVP_packVoltage) + " V

"; + content += "

HVP_fcLinkVoltage: " + String(HVP_fcLinkVoltage) + " V

"; + content += "

HVP_packContVoltage: " + String(HVP_packContVoltage) + " V

"; + content += "

HVP_packNegativeV: " + String(HVP_packNegativeV) + " V

"; + content += "

HVP_packPositiveV: " + String(HVP_packPositiveV) + " V

"; + content += "

HVP_pyroAnalog: " + String(HVP_pyroAnalog) + " V

"; + content += "

HVP_dcLinkNegativeV: " + String(HVP_dcLinkNegativeV) + " V

"; + content += "

HVP_dcLinkPositiveV: " + String(HVP_dcLinkPositiveV) + " V

"; + content += "

HVP_fcLinkNegativeV: " + String(HVP_fcLinkNegativeV) + " V

"; + content += "

HVP_fcContCoilCurrent: " + String(HVP_fcContCoilCurrent) + " A

"; + content += "

HVP_fcContVoltage: " + String(HVP_fcContVoltage) + " V

"; + content += "

HVP_hvilInVoltage: " + String(HVP_hvilInVoltage) + " V

"; + content += "

HVP_hvilOutVoltage: " + String(HVP_hvilOutVoltage) + " V

"; + content += "

HVP_fcLinkPositiveV: " + String(HVP_fcLinkPositiveV) + " V

"; + content += "

HVP_packContCoilCurrent: " + String(HVP_packContCoilCurrent) + " A

"; + content += "

HVP_battery12V: " + String(HVP_battery12V) + " V

"; + content += "

HVP_shuntRefVoltageDbg: " + String(HVP_shuntRefVoltageDbg) + " V

"; + content += "

HVP_shuntAuxCurrentDbg: " + String(HVP_shuntAuxCurrentDbg) + " A

"; + content += "

HVP_shuntBarTempDbg: " + String(HVP_shuntBarTempDbg) + " DegC

"; + content += "

HVP_shuntAsicTempDbg: " + String(HVP_shuntAsicTempDbg) + " DegC

"; + content += + "

HVP_shuntAuxCurrentStatus: " + String(HVP_status[datalayer_extended.tesla.HVP_shuntAuxCurrentStatus]) + + "

"; + content += + "

HVP_shuntBarTempStatus: " + String(HVP_status[datalayer_extended.tesla.HVP_shuntBarTempStatus]) + "

"; + content += "

HVP_shuntAsicTempStatus: " + String(HVP_status[datalayer_extended.tesla.HVP_shuntAsicTempStatus]) + + "

"; + #endif #ifdef NISSAN_LEAF_BATTERY diff --git a/Software/src/devboard/webserver/webserver.h b/Software/src/devboard/webserver/webserver.h index 86b5a763..a75ef8fb 100644 --- a/Software/src/devboard/webserver/webserver.h +++ b/Software/src/devboard/webserver/webserver.h @@ -6,7 +6,7 @@ #include "../../include.h" #include "../../lib/YiannisBourkelis-Uptime-Library/src/uptime_formatter.h" #include "../../lib/ayushsharma82-ElegantOTA/src/ElegantOTA.h" -#include "../../lib/mathieucarbou-AsyncTCP/src/AsyncTCP.h" +#include "../../lib/me-no-dev-AsyncTCP/src/AsyncTCP.h" #include "../../lib/me-no-dev-ESPAsyncWebServer/src/ESPAsyncWebServer.h" #include "../../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h" diff --git a/Software/src/devboard/wifi/wifi.cpp b/Software/src/devboard/wifi/wifi.cpp index 3dba4b72..7ebcc9c3 100644 --- a/Software/src/devboard/wifi/wifi.cpp +++ b/Software/src/devboard/wifi/wifi.cpp @@ -29,12 +29,8 @@ static bool connected_once = false; void init_WiFi() { #ifdef WIFIAP - if (AccessPointEnabled) { - WiFi.mode(WIFI_AP_STA); // Simultaneous WiFi AP and Router connection - init_WiFi_AP(); - } else { - WiFi.mode(WIFI_STA); // Only Router connection - } + WiFi.mode(WIFI_AP_STA); // Simultaneous WiFi AP and Router connection + init_WiFi_AP(); #else WiFi.mode(WIFI_STA); // Only Router connection #endif // WIFIAP diff --git a/Software/src/inverter/BYD-SMA.cpp b/Software/src/inverter/BYD-SMA.cpp index 34e33063..4892eacf 100644 --- a/Software/src/inverter/BYD-SMA.cpp +++ b/Software/src/inverter/BYD-SMA.cpp @@ -130,10 +130,18 @@ void update_values_can_inverter() { //This function maps all the values fetched } //Error bits - if (!datalayer.system.status.inverter_allows_contactor_closing) { - SMA_158.data.u8[2] = 0x6A; - } else { + if (datalayer.system.status.inverter_allows_contactor_closing) { SMA_158.data.u8[2] = 0xAA; +#ifdef INVERTER_CONTACTOR_ENABLE_LED_PIN + digitalWrite(INVERTER_CONTACTOR_ENABLE_LED_PIN, + HIGH); // Turn on LED to indicate that SMA inverter allows contactor closing +#endif // INVERTER_CONTACTOR_ENABLE_LED_PIN + } else { + SMA_158.data.u8[2] = 0x6A; +#ifdef INVERTER_CONTACTOR_ENABLE_LED_PIN + digitalWrite(INVERTER_CONTACTOR_ENABLE_LED_PIN, + LOW); // Turn off LED to indicate that SMA inverter allows contactor closing +#endif // INVERTER_CONTACTOR_ENABLE_LED_PIN } /* @@ -251,10 +259,15 @@ void send_can_inverter() { } } } + void setup_inverter(void) { // Performs one time setup at startup over CAN bus strncpy(datalayer.system.info.inverter_protocol, "BYD Battery-Box HVS over SMA CAN", 63); datalayer.system.info.inverter_protocol[63] = '\0'; datalayer.system.status.inverter_allows_contactor_closing = false; // The inverter needs to allow first pinMode(INVERTER_CONTACTOR_ENABLE_PIN, INPUT); +#ifdef INVERTER_CONTACTOR_ENABLE_LED_PIN + pinMode(INVERTER_CONTACTOR_ENABLE_LED_PIN, OUTPUT); + digitalWrite(INVERTER_CONTACTOR_ENABLE_LED_PIN, LOW); // Turn LED off, until inverter allows contactor closing +#endif // INVERTER_CONTACTOR_ENABLE_LED_PIN } #endif diff --git a/Software/src/inverter/SMA-CAN.cpp b/Software/src/inverter/SMA-CAN.cpp index 5831406d..43ccad0d 100644 --- a/Software/src/inverter/SMA-CAN.cpp +++ b/Software/src/inverter/SMA-CAN.cpp @@ -127,10 +127,18 @@ void update_values_can_inverter() { //This function maps all the values fetched } //Error bits - if (!datalayer.system.status.inverter_allows_contactor_closing) { - SMA_158.data.u8[2] = 0x6A; - } else { + if (datalayer.system.status.inverter_allows_contactor_closing) { SMA_158.data.u8[2] = 0xAA; +#ifdef INVERTER_CONTACTOR_ENABLE_LED_PIN + digitalWrite(INVERTER_CONTACTOR_ENABLE_LED_PIN, + HIGH); // Turn on LED to indicate that SMA inverter allows contactor closing +#endif // INVERTER_CONTACTOR_ENABLE_LED_PIN + } else { + SMA_158.data.u8[2] = 0x6A; +#ifdef INVERTER_CONTACTOR_ENABLE_LED_PIN + digitalWrite(INVERTER_CONTACTOR_ENABLE_LED_PIN, + LOW); // Turn off LED to indicate that SMA inverter allows contactor closing +#endif // INVERTER_CONTACTOR_ENABLE_LED_PIN } /* @@ -253,5 +261,9 @@ void send_can_inverter() { void setup_inverter(void) { // Performs one time setup at startup over CAN bus strncpy(datalayer.system.info.inverter_protocol, "SMA CAN", 63); datalayer.system.info.inverter_protocol[63] = '\0'; +#ifdef INVERTER_CONTACTOR_ENABLE_LED_PIN + pinMode(INVERTER_CONTACTOR_ENABLE_LED_PIN, OUTPUT); + digitalWrite(INVERTER_CONTACTOR_ENABLE_LED_PIN, LOW); // Turn LED off, until inverter allows contactor closing +#endif // INVERTER_CONTACTOR_ENABLE_LED_PIN } #endif diff --git a/Software/src/inverter/SMA-TRIPOWER-CAN.cpp b/Software/src/inverter/SMA-TRIPOWER-CAN.cpp index 7a242dae..dac1af9c 100644 --- a/Software/src/inverter/SMA-TRIPOWER-CAN.cpp +++ b/Software/src/inverter/SMA-TRIPOWER-CAN.cpp @@ -12,317 +12,248 @@ */ /* Do not change code below unless you are sure what you are doing */ -static unsigned long previousMillis500ms = 0; // will store last time a 100ms CAN Message was send +static unsigned long previousMillis250ms = 0; // will store last time a 250ms CAN Message was send +static unsigned long previousMillis500ms = 0; // will store last time a 500ms CAN Message was send +static unsigned long previousMillis2s = 0; // will store last time a 2s CAN Message was send +static unsigned long previousMillis10s = 0; // will store last time a 10s CAN Message was send +static unsigned long previousMillis60s = 0; // will store last time a 60s CAN Message was send -//Actual content messages -CAN_frame SMA_00D = {.FD = false, - .ext_ID = false, - .DLC = 8, - .ID = 0x00D, - .data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; -CAN_frame SMA_00F = {.FD = false, - .ext_ID = false, - .DLC = 8, - .ID = 0x00F, - .data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; -CAN_frame SMA_011 = {.FD = false, - .ext_ID = false, - .DLC = 8, - .ID = 0x011, - .data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; -CAN_frame SMA_013 = {.FD = false, - .ext_ID = false, - .DLC = 8, - .ID = 0x013, - .data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; -CAN_frame SMA_014 = {.FD = false, - .ext_ID = false, - .DLC = 8, - .ID = 0x014, - .data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; -CAN_frame SMA_005 = {.FD = false, - .ext_ID = false, - .DLC = 8, - .ID = 0x005, - .data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; -CAN_frame SMA_007 = {.FD = false, - .ext_ID = false, - .DLC = 8, - .ID = 0x007, - .data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; -CAN_frame SMA_006 = {.FD = false, - .ext_ID = false, - .DLC = 8, - .ID = 0x006, - .data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; -CAN_frame SMA_008 = {.FD = false, - .ext_ID = false, - .DLC = 8, - .ID = 0x008, - .data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; -CAN_frame SMA_015 = {.FD = false, - .ext_ID = false, - .DLC = 8, - .ID = 0x015, - .data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; -CAN_frame SMA_016 = {.FD = false, - .ext_ID = false, - .DLC = 8, - .ID = 0x016, - .data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; -CAN_frame SMA_017 = {.FD = false, - .ext_ID = false, - .DLC = 8, - .ID = 0x017, - .data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; -CAN_frame SMA_018 = {.FD = false, - .ext_ID = false, - .DLC = 8, - .ID = 0x018, - .data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; +typedef struct { + CAN_frame* frame; + void (*callback)(); +} Frame; +static unsigned short listLength = 0; +static Frame framesToSend[20]; + +static uint32_t inverter_time = 0; +static uint16_t inverter_voltage = 0; +static int16_t inverter_current = 0; +static bool pairing_completed = false; static int16_t temperature_average = 0; static uint16_t ampere_hours_remaining = 0; -static uint16_t ampere_hours_max = 0; -static bool batteryAlarm = false; -static bool BMSevent = false; -enum BatteryState { NA, INIT, BAT_STANDBY, OPERATE, WARNING, FAULTED, UPDATE, BAT_UPDATE }; -BatteryState batteryState = OPERATE; -enum InverterControlFlags { - EMG_CHARGE_REQUEST, - EMG_DISCHARGE_REQUEST, - NOT_ENOUGH_ENERGY_FOR_START, - INVERTER_STAY_ON, - FORCED_BATTERY_SHUTDOWN, - RESERVED, - BATTERY_UPDATE_AVAILABLE, - NO_BATTERY_UPDATED_BY_INV -}; -InverterControlFlags inverterControlFlags = BATTERY_UPDATE_AVAILABLE; -enum Events0 { - START_SOC_CALIBRATE, - STOP_SOC_CALIBRATE, - START_POWERLIMIT, - STOP_POWERLIMIT, - PREVENTATIVE_BAT_SHUTDOWN, - THERMAL_MANAGEMENT, - START_BALANCING, - STOP_BALANCING -}; -Events0 events0 = START_BALANCING; -enum Events1 { START_BATTERY_SELFTEST, STOP_BATTERY_SELFTEST }; -Events1 events1 = START_BATTERY_SELFTEST; -enum Command2Battery { IDLE, RUN, NOT_USED1, NOT_USED2, SHUTDOWN, FIRMWARE_UPDATE, BATSELFUPDATE, NOT_USED3 }; -Command2Battery command2Battery = RUN; -enum InvInitState { SYSTEM_FREQUENCY, XPHASE_SYSTEM, BLACKSTART_OPERATION }; -InvInitState invInitState = SYSTEM_FREQUENCY; +//Actual content messages +CAN_frame SMA_558 = {.FD = false, //Pairing first message + .ext_ID = false, + .DLC = 8, + .ID = 0x558, // BYD HVS 10.2 kWh (0x66 might be kWh) + .data = {0x03, 0x24, 0x00, 0x04, 0x00, 0x66, 0x04, 0x09}}; //Amount of modules? Vendor ID? +CAN_frame SMA_598 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x598, + .data = {0x12, 0xD6, 0x43, 0xA4, 0x00, 0x00, 0x00, 0x00}}; //B0-4 Serial 301100932 +CAN_frame SMA_5D8 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x5D8, + .data = {0x00, 0x42, 0x59, 0x44, 0x00, 0x00, 0x00, 0x00}}; //B Y D +CAN_frame SMA_618_0 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x618, + .data = {0x00, 0x42, 0x61, 0x74, 0x74, 0x65, 0x72, 0x79}}; //BATTERY +CAN_frame SMA_618_1 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x618, + .data = {0x01, 0x2D, 0x42, 0x6F, 0x78, 0x20, 0x50, 0x72}}; //-Box Pr +CAN_frame SMA_618_2 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x618, + .data = {0x02, 0x65, 0x6D, 0x69, 0x75, 0x6D, 0x20, 0x48}}; //emium H +CAN_frame SMA_618_3 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x618, + .data = {0x03, 0x56, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00}}; //VS +CAN_frame SMA_358 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x358, + .data = {0x12, 0x40, 0x0C, 0x80, 0x01, 0x00, 0x01, 0x00}}; +CAN_frame SMA_3D8 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x3D8, + .data = {0x04, 0x06, 0x27, 0x10, 0x00, 0x19, 0x00, 0xFA}}; +CAN_frame SMA_458 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x458, + .data = {0x00, 0x00, 0x73, 0xAE, 0x00, 0x00, 0x64, 0x64}}; +CAN_frame SMA_4D8 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x4D8, + .data = {0x10, 0x62, 0x00, 0x00, 0x00, 0x78, 0x02, 0x08}}; +CAN_frame SMA_518 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x518, + .data = {0x00, 0x96, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00}}; void update_values_can_inverter() { //This function maps all the values fetched from battery CAN to the inverter CAN - //Calculate values - + // Update values temperature_average = ((datalayer.battery.status.temperature_max_dC + datalayer.battery.status.temperature_min_dC) / 2); - ampere_hours_remaining = - ((datalayer.battery.status.reported_remaining_capacity_Wh / datalayer.battery.status.voltage_dV) * - 100); //(WH[10000] * V+1[3600])*100 = 270 (27.0Ah) - ampere_hours_max = ((datalayer.battery.info.total_capacity_Wh / datalayer.battery.status.voltage_dV) * - 100); //(WH[10000] * V+1[3600])*100 = 270 (27.0Ah) - - batteryState = OPERATE; - inverterControlFlags = INVERTER_STAY_ON; - + if (datalayer.battery.status.voltage_dV > 10) { // Only update value when we have voltage available to avoid div0 + ampere_hours_remaining = + ((datalayer.battery.status.reported_remaining_capacity_Wh / datalayer.battery.status.voltage_dV) * + 100); //(WH[10000] * V+1[3600])*100 = 270 (27.0Ah) + } //Map values to CAN messages - // Battery Limits - //Battery Max Charge Voltage (eg 400.0V = 4000 , 16bits long) - SMA_00D.data.u8[0] = (datalayer.battery.info.max_design_voltage_dV >> 8); - SMA_00D.data.u8[1] = (datalayer.battery.info.max_design_voltage_dV & 0x00FF); - //Battery Min Discharge Voltage (eg 300.0V = 3000 , 16bits long) - SMA_00D.data.u8[2] = (datalayer.battery.info.min_design_voltage_dV >> 8); - SMA_00D.data.u8[3] = (datalayer.battery.info.min_design_voltage_dV & 0x00FF); + + //Maxvoltage (eg 400.0V = 4000 , 16bits long) + SMA_358.data.u8[0] = (datalayer.battery.info.max_design_voltage_dV >> 8); + SMA_358.data.u8[1] = (datalayer.battery.info.max_design_voltage_dV & 0x00FF); + //Minvoltage (eg 300.0V = 3000 , 16bits long) + SMA_358.data.u8[2] = (datalayer.battery.info.min_design_voltage_dV >> 8); + SMA_358.data.u8[3] = (datalayer.battery.info.min_design_voltage_dV & 0x00FF); //Discharge limited current, 500 = 50A, (0.1, A) - SMA_00D.data.u8[4] = (datalayer.battery.status.max_discharge_current_dA >> 8); - SMA_00D.data.u8[5] = (datalayer.battery.status.max_discharge_current_dA & 0x00FF); + SMA_358.data.u8[4] = (datalayer.battery.status.max_discharge_current_dA >> 8); + SMA_358.data.u8[5] = (datalayer.battery.status.max_discharge_current_dA & 0x00FF); //Charge limited current, 125 =12.5A (0.1, A) - SMA_00D.data.u8[6] = (datalayer.battery.status.max_charge_current_dA >> 8); - SMA_00D.data.u8[7] = (datalayer.battery.status.max_charge_current_dA & 0x00FF); + SMA_358.data.u8[6] = (datalayer.battery.status.max_charge_current_dA >> 8); + SMA_358.data.u8[7] = (datalayer.battery.status.max_charge_current_dA & 0x00FF); - // Battery State //SOC (100.00%) - SMA_00F.data.u8[0] = (datalayer.battery.status.reported_soc >> 8); - SMA_00F.data.u8[1] = (datalayer.battery.status.reported_soc & 0x00FF); + SMA_3D8.data.u8[0] = (datalayer.battery.status.reported_soc >> 8); + SMA_3D8.data.u8[1] = (datalayer.battery.status.reported_soc & 0x00FF); //StateOfHealth (100.00%) - SMA_00F.data.u8[2] = (datalayer.battery.status.soh_pptt >> 8); - SMA_00F.data.u8[3] = (datalayer.battery.status.soh_pptt & 0x00FF); + SMA_3D8.data.u8[2] = (datalayer.battery.status.soh_pptt >> 8); + SMA_3D8.data.u8[3] = (datalayer.battery.status.soh_pptt & 0x00FF); //State of charge (AH, 0.1) - SMA_00F.data.u8[4] = (ampere_hours_remaining >> 8); - SMA_00F.data.u8[5] = (ampere_hours_remaining & 0x00FF); - //Fully charged (AH, 0.1) - SMA_00F.data.u8[6] = (ampere_hours_max >> 8); - SMA_00F.data.u8[7] = (ampere_hours_max & 0x00FF); + SMA_3D8.data.u8[4] = (ampere_hours_remaining >> 8); + SMA_3D8.data.u8[5] = (ampere_hours_remaining & 0x00FF); - // Battery Energy - //Charged Energy Counter TODO: are these needed? - //SMA_011.data.u8[0] = (X >> 8); - //SMA_011.data.u8[1] = (X & 0x00FF); - //SMA_011.data.u8[2] = (X >> 8); - //SMA_011.data.u8[3] = (X & 0x00FF); - //Discharged Energy Counter TODO: are these needed? - //SMA_011.data.u8[4] = (X >> 8); - //SMA_011.data.u8[5] = (X & 0x00FF); - //SMA_011.data.u8[6] = (X >> 8); - //SMA_011.data.u8[7] = (X & 0x00FF); - - // Battery Measurements //Voltage (370.0) - SMA_013.data.u8[0] = (datalayer.battery.status.voltage_dV >> 8); - SMA_013.data.u8[1] = (datalayer.battery.status.voltage_dV & 0x00FF); + SMA_4D8.data.u8[0] = (datalayer.battery.status.voltage_dV >> 8); + SMA_4D8.data.u8[1] = (datalayer.battery.status.voltage_dV & 0x00FF); //Current (TODO: signed OK?) - SMA_013.data.u8[2] = (datalayer.battery.status.current_dA >> 8); - SMA_013.data.u8[3] = (datalayer.battery.status.current_dA & 0x00FF); + SMA_4D8.data.u8[2] = (datalayer.battery.status.current_dA >> 8); + SMA_4D8.data.u8[3] = (datalayer.battery.status.current_dA & 0x00FF); //Temperature average - SMA_013.data.u8[4] = (temperature_average >> 8); - SMA_013.data.u8[5] = (temperature_average & 0x00FF); - //Battery state - SMA_013.data.u8[6] = batteryState; - SMA_013.data.u8[6] = inverterControlFlags; - - // Battery Temperature and Cellvoltages - // Battery max temperature - SMA_014.data.u8[0] = (datalayer.battery.status.temperature_max_dC >> 8); - SMA_014.data.u8[1] = (datalayer.battery.status.temperature_max_dC & 0x00FF); - // Battery min temperature - SMA_014.data.u8[2] = (datalayer.battery.status.temperature_min_dC >> 8); - SMA_014.data.u8[3] = (datalayer.battery.status.temperature_min_dC & 0x00FF); - // Battery Cell Voltage (sum) - //SMA_014.data.u8[4] = (??? >> 8); //TODO scaling? - //SMA_014.data.u8[5] = (??? & 0x00FF); //TODO scaling? - // Cell voltage min - //SMA_014.data.u8[6] = (??? >> 8); //TODO scaling? 0-255 - // Cell voltage max - //SMA_014.data.u8[7] = (??? >> 8); //TODO scaling? 0-255 - - //SMA_006.data.u8[0] = (ErrorCode >> 8); - //SMA_006.data.u8[1] = (ErrorCode & 0x00FF); - //SMA_006.data.u8[2] = ModuleNumber; - //SMA_006.data.u8[3] = ErrorLevel; - //SMA_008.data.u8[0] = Events0; - //SMA_008.data.u8[1] = Events1; - - //SMA_005.data.u8[0] = BMSalarms0; - //SMA_005.data.u8[1] = BMSalarms1; - //SMA_005.data.u8[2] = BMSalarms2; - //SMA_005.data.u8[3] = BMSalarms3; - //SMA_005.data.u8[4] = BMSalarms4; - //SMA_005.data.u8[5] = BMSalarms5; - //SMA_005.data.u8[6] = BMSalarms6; - //SMA_005.data.u8[7] = BMSalarms7; - - //SMA_007.data.u8[0] = DCDCalarms0; - //SMA_007.data.u8[1] = DCDCalarms1; - //SMA_007.data.u8[2] = DCDCalarms2; - //SMA_007.data.u8[3] = DCDCalarms3; - //SMA_007.data.u8[4] = DCDCwarnings0; - //SMA_007.data.u8[5] = DCDCwarnings1; - //SMA_007.data.u8[6] = DCDCwarnings2; - //SMA_007.data.u8[7] = DCDCwarnings3; - - //SMA_015.data.u8[0] = BatterySystemVersion; - //SMA_015.data.u8[1] = BatterySystemVersion; - //SMA_015.data.u8[2] = BatterySystemVersion; - //SMA_015.data.u8[3] = BatterySystemVersion; - //SMA_015.data.u8[4] = BatteryCapacity; - //SMA_015.data.u8[5] = BatteryCapacity; - //SMA_015.data.u8[6] = NumberOfModules; - //SMA_015.data.u8[7] = BatteryManufacturerID; - - //SMA_016.data.u8[0] = SerialNumber; - //SMA_016.data.u8[1] = SerialNumber; - //SMA_016.data.u8[2] = SerialNumber; - //SMA_016.data.u8[3] = SerialNumber; - //SMA_016.data.u8[4] = ManufacturingDate; - //SMA_016.data.u8[5] = ManufacturingDate; - //SMA_016.data.u8[6] = ManufacturingDate; - //SMA_016.data.u8[7] = ManufacturingDate; - - //SMA_017.data.u8[0] = Multiplex; - //SMA_017.data.u8[1] = ManufacturerName; - //SMA_017.data.u8[2] = ManufacturerName; - //SMA_017.data.u8[3] = ManufacturerName; - //SMA_017.data.u8[4] = ManufacturerName; - //SMA_017.data.u8[5] = ManufacturerName; - //SMA_017.data.u8[6] = ManufacturerName; - //SMA_017.data.u8[7] = ManufacturerName; - - //SMA_018.data.u8[0] = Multiplex; - //SMA_018.data.u8[1] = BatteryName; - //SMA_018.data.u8[2] = BatteryName; - //SMA_018.data.u8[3] = BatteryName; - //SMA_018.data.u8[4] = BatteryName; - //SMA_018.data.u8[5] = BatteryName; - //SMA_018.data.u8[6] = BatteryName; - //SMA_018.data.u8[7] = BatteryName; + SMA_4D8.data.u8[4] = (temperature_average >> 8); + SMA_4D8.data.u8[5] = (temperature_average & 0x00FF); + //Battery ready + if (datalayer.battery.status.bms_status == FAULT) { + SMA_4D8.data.u8[6] = STOP_STATE; + } else { + SMA_4D8.data.u8[6] = READY_STATE; + } } void receive_can_inverter(CAN_frame rx_frame) { switch (rx_frame.ID) { - case 0x00D: //Inverter Measurements + case 0x360: //Message originating from SMA inverter - Voltage and current + datalayer.system.status.CAN_inverter_still_alive = CAN_STILL_ALIVE; + inverter_voltage = (rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1]; + inverter_current = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3]; + break; + case 0x3E0: //Message originating from SMA inverter - ? datalayer.system.status.CAN_inverter_still_alive = CAN_STILL_ALIVE; break; - case 0x00F: //Inverter Feedback + case 0x420: //Message originating from SMA inverter - Timestamp + datalayer.system.status.CAN_inverter_still_alive = CAN_STILL_ALIVE; + inverter_time = + (rx_frame.data.u8[0] << 24) | (rx_frame.data.u8[1] << 16) | (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3]; + break; + case 0x560: //Message originating from SMA inverter - Init datalayer.system.status.CAN_inverter_still_alive = CAN_STILL_ALIVE; break; - case 0x010: //Time from inverter + case 0x5E0: //Message originating from SMA inverter - String datalayer.system.status.CAN_inverter_still_alive = CAN_STILL_ALIVE; + //Inverter brand (frame1-3 = 0x53 0x4D 0x41) = SMA break; - case 0x015: //Initialization message from inverter + case 0x660: //Message originating from SMA inverter - Pairing request datalayer.system.status.CAN_inverter_still_alive = CAN_STILL_ALIVE; send_tripower_init(); break; - case 0x017: //Initialization message from inverter 2 - datalayer.system.status.CAN_inverter_still_alive = CAN_STILL_ALIVE; - //send_tripower_init(); - break; default: break; } } +void pushFrame(CAN_frame* frame, void (*callback)() = NULL) { + if (listLength >= 20) { + return; //TODO: scream. + } + framesToSend[listLength] = { + .frame = frame, + .callback = callback, + }; + listLength++; +} + void send_can_inverter() { unsigned long currentMillis = millis(); - // Send CAN Message every 500ms - if (currentMillis - previousMillis500ms >= INTERVAL_500_MS) { - previousMillis500ms = currentMillis; - - transmit_can(&SMA_00D, can_config.inverter); //Battery limits - transmit_can(&SMA_00F, can_config.inverter); // Battery state - transmit_can(&SMA_011, can_config.inverter); // Battery Energy - transmit_can(&SMA_013, can_config.inverter); // Battery Measurements - transmit_can(&SMA_014, can_config.inverter); // Battery Temperatures and cellvoltages + // Send CAN Message only if we're enabled by inverter + if (!datalayer.system.status.inverter_allows_contactor_closing) { + return; } - if (batteryAlarm) { //Non-cyclic - transmit_can(&SMA_005, can_config.inverter); // Battery Alarms 1 - transmit_can(&SMA_007, can_config.inverter); // Battery Alarms 2 + if (listLength > 0 && currentMillis - previousMillis250ms >= INTERVAL_250_MS) { + previousMillis250ms = currentMillis; + // Send next frame. + Frame frame = framesToSend[0]; + transmit_can(frame.frame, can_config.inverter); + if (frame.callback != NULL) { + frame.callback(); + } + for (int i = 0; i < listLength - 1; i++) { + framesToSend[i] = framesToSend[i + 1]; + } + listLength--; } - if (BMSevent) { //Non-cyclic - transmit_can(&SMA_006, can_config.inverter); // Battery Errorcode - transmit_can(&SMA_008, can_config.inverter); // Battery Events + if (!pairing_completed) { + return; + } + + // Send CAN Message every 2s + if (currentMillis - previousMillis2s >= INTERVAL_2_S) { + previousMillis2s = currentMillis; + pushFrame(&SMA_358); + } + // Send CAN Message every 10s + if (currentMillis - previousMillis10s >= INTERVAL_10_S) { + previousMillis10s = currentMillis; + pushFrame(&SMA_518); + pushFrame(&SMA_4D8); + pushFrame(&SMA_3D8); } } +void completePairing() { + pairing_completed = true; +} + void send_tripower_init() { - transmit_can(&SMA_015, can_config.inverter); // Battery Data 1 - transmit_can(&SMA_016, can_config.inverter); // Battery Data 2 - transmit_can(&SMA_017, can_config.inverter); // Battery Manufacturer - transmit_can(&SMA_018, can_config.inverter); // Battery Name + listLength = 0; // clear all frames + + pushFrame(&SMA_558); //Pairing start - Vendor + pushFrame(&SMA_598); //Serial + pushFrame(&SMA_5D8); //BYD + pushFrame(&SMA_618_0); //BATTERY + pushFrame(&SMA_618_1); //-Box Pr + pushFrame(&SMA_618_2); //emium H + pushFrame(&SMA_618_3); //VS + pushFrame(&SMA_358); + pushFrame(&SMA_3D8); + pushFrame(&SMA_458); + pushFrame(&SMA_4D8); + pushFrame(&SMA_518, completePairing); } void setup_inverter(void) { // Performs one time setup at startup over CAN bus strncpy(datalayer.system.info.inverter_protocol, "SMA Tripower CAN", 63); datalayer.system.info.inverter_protocol[63] = '\0'; + datalayer.system.status.inverter_allows_contactor_closing = false; // The inverter needs to allow first + pinMode(INVERTER_CONTACTOR_ENABLE_PIN, INPUT); } #endif diff --git a/Software/src/inverter/SMA-TRIPOWER-CAN.h b/Software/src/inverter/SMA-TRIPOWER-CAN.h index 90967001..2645efce 100644 --- a/Software/src/inverter/SMA-TRIPOWER-CAN.h +++ b/Software/src/inverter/SMA-TRIPOWER-CAN.h @@ -4,6 +4,9 @@ #define CAN_INVERTER_SELECTED +#define READY_STATE 0x03 +#define STOP_STATE 0x02 + void send_tripower_init(); void transmit_can(CAN_frame* tx_frame, int interface); void setup_inverter(void); diff --git a/Software/src/inverter/SOLAX-CAN.cpp b/Software/src/inverter/SOLAX-CAN.cpp index 60f684b9..e3c5dad2 100644 --- a/Software/src/inverter/SOLAX-CAN.cpp +++ b/Software/src/inverter/SOLAX-CAN.cpp @@ -68,7 +68,7 @@ CAN_frame SOLAX_187E = {.FD = false, //Needed for Ultra .ext_ID = true, .DLC = 8, .ID = 0x187E, - .data = {0x0, 0x2D, 0x0, 0x0, 0x0, 0x5F, 0x0, 0x0}}; + .data = {0x60, 0xEA, 0x0, 0x0, 0x64, 0x0, 0x0, 0x0}}; CAN_frame SOLAX_187D = {.FD = false, //Needed for Ultra .ext_ID = true, .DLC = 8, @@ -88,7 +88,7 @@ CAN_frame SOLAX_187A = {.FD = false, //Needed for Ultra .ext_ID = true, .DLC = 8, .ID = 0x187A, - .data = {0x01, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; + .data = {0x01, 0x50, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; CAN_frame SOLAX_1881 = {.FD = false, .ext_ID = true, .DLC = 8, @@ -190,6 +190,13 @@ void update_values_can_inverter() { //This function maps all the values fetched SOLAX_1801.data.u8[0] = 2; SOLAX_1801.data.u8[2] = 1; SOLAX_1801.data.u8[4] = 1; + + //Ultra messages + SOLAX_187E.data.u8[0] = (uint8_t)capped_remaining_capacity_Wh; + SOLAX_187E.data.u8[1] = (capped_remaining_capacity_Wh >> 8); + SOLAX_187E.data.u8[2] = 0; + SOLAX_187E.data.u8[3] = 0; + SOLAX_187E.data.u8[5] = (uint8_t)(datalayer.battery.status.reported_soc / 100); } void send_can_inverter() { @@ -212,7 +219,9 @@ void receive_can_inverter(CAN_frame rx_frame) { #endif datalayer.system.status.inverter_allows_contactor_closing = false; SOLAX_1875.data.u8[4] = (0x00); // Inform Inverter: Contactor 0=off, 1=on. - for (int i = 0; i <= number_of_batteries; i++) { + for (uint8_t i = 0; i <= number_of_batteries; i++) { + transmit_can(&SOLAX_187E, can_config.inverter); + transmit_can(&SOLAX_187A, can_config.inverter); transmit_can(&SOLAX_1872, can_config.inverter); transmit_can(&SOLAX_1873, can_config.inverter); transmit_can(&SOLAX_1874, can_config.inverter); @@ -230,6 +239,8 @@ void receive_can_inverter(CAN_frame rx_frame) { case (WAITING_FOR_CONTACTOR): SOLAX_1875.data.u8[4] = (0x00); // Inform Inverter: Contactor 0=off, 1=on. + transmit_can(&SOLAX_187E, can_config.inverter); + transmit_can(&SOLAX_187A, can_config.inverter); transmit_can(&SOLAX_1872, can_config.inverter); transmit_can(&SOLAX_1873, can_config.inverter); transmit_can(&SOLAX_1874, can_config.inverter); @@ -247,6 +258,8 @@ void receive_can_inverter(CAN_frame rx_frame) { case (CONTACTOR_CLOSED): datalayer.system.status.inverter_allows_contactor_closing = true; SOLAX_1875.data.u8[4] = (0x01); // Inform Inverter: Contactor 0=off, 1=on. + transmit_can(&SOLAX_187E, can_config.inverter); + transmit_can(&SOLAX_187A, can_config.inverter); transmit_can(&SOLAX_1872, can_config.inverter); transmit_can(&SOLAX_1873, can_config.inverter); transmit_can(&SOLAX_1874, can_config.inverter); @@ -281,12 +294,5 @@ void setup_inverter(void) { // Performs one time setup at startup strncpy(datalayer.system.info.inverter_protocol, "SolaX Triple Power LFP over CAN bus", 63); datalayer.system.info.inverter_protocol[63] = '\0'; datalayer.system.status.inverter_allows_contactor_closing = false; // The inverter needs to allow first - - // Sending these messages once towards the inverter makes SOC% work on the Ultra variant - transmit_can(&SOLAX_187E, can_config.inverter); - transmit_can(&SOLAX_187D, can_config.inverter); - transmit_can(&SOLAX_187C, can_config.inverter); - transmit_can(&SOLAX_187B, can_config.inverter); - transmit_can(&SOLAX_187A, can_config.inverter); } #endif diff --git a/Software/src/lib/ayushsharma82-ElegantOTA/src/ElegantOTA.h b/Software/src/lib/ayushsharma82-ElegantOTA/src/ElegantOTA.h index 48833d99..f8770a07 100644 --- a/Software/src/lib/ayushsharma82-ElegantOTA/src/ElegantOTA.h +++ b/Software/src/lib/ayushsharma82-ElegantOTA/src/ElegantOTA.h @@ -64,7 +64,7 @@ _____ _ _ ___ _____ _ #include "Update.h" #include "StreamString.h" #if ELEGANTOTA_USE_ASYNC_WEBSERVER == 1 - #include "../../mathieucarbou-AsyncTCP/src/AsyncTCP.h" + #include "../../me-no-dev-AsyncTCP/src/AsyncTCP.h" #include "../../me-no-dev-ESPAsyncWebServer/src/ESPAsyncWebServer.h" #define ELEGANTOTA_WEBSERVER AsyncWebServer #else diff --git a/Software/src/lib/mathieucarbou-AsyncTCP/CODE_OF_CONDUCT.md b/Software/src/lib/mathieucarbou-AsyncTCP/CODE_OF_CONDUCT.md deleted file mode 100644 index 0a5f9141..00000000 --- a/Software/src/lib/mathieucarbou-AsyncTCP/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,129 +0,0 @@ - -# Contributor Covenant Code of Conduct - -## Our Pledge - -We as members, contributors, and leaders pledge to make participation in our -community a harassment-free experience for everyone, regardless of age, body -size, visible or invisible disability, ethnicity, sex characteristics, gender -identity and expression, level of experience, education, socio-economic status, -nationality, personal appearance, race, religion, or sexual identity -and orientation. - -We pledge to act and interact in ways that contribute to an open, welcoming, -diverse, inclusive, and healthy community. - -## Our Standards - -Examples of behavior that contributes to a positive environment for our -community include: - -* Demonstrating empathy and kindness toward other people -* Being respectful of differing opinions, viewpoints, and experiences -* Giving and gracefully accepting constructive feedback -* Accepting responsibility and apologizing to those affected by our mistakes, - and learning from the experience -* Focusing on what is best not just for us as individuals, but for the - overall community - -Examples of unacceptable behavior include: - -* The use of sexualized language or imagery, and sexual attention or - advances of any kind -* Trolling, insulting or derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or email - address, without their explicit permission -* Other conduct which could reasonably be considered inappropriate in a - professional setting - -## Enforcement Responsibilities - -Community leaders are responsible for clarifying and enforcing our standards of -acceptable behavior and will take appropriate and fair corrective action in -response to any behavior that they deem inappropriate, threatening, offensive, -or harmful. - -Community leaders have the right and responsibility to remove, edit, or reject -comments, commits, code, wiki edits, issues, and other contributions that are -not aligned to this Code of Conduct, and will communicate reasons for moderation -decisions when appropriate. - -## Scope - -This Code of Conduct applies within all community spaces, and also applies when -an individual is officially representing the community in public spaces. -Examples of representing our community include using an official e-mail address, -posting via an official social media account, or acting as an appointed -representative at an online or offline event. - -## Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported to the community leaders responsible for enforcement at -https://sidweb.nl/cms3/en/contact. -All complaints will be reviewed and investigated promptly and fairly. - -All community leaders are obligated to respect the privacy and security of the -reporter of any incident. - -## Enforcement Guidelines - -Community leaders will follow these Community Impact Guidelines in determining -the consequences for any action they deem in violation of this Code of Conduct: - -### 1. Correction - -**Community Impact**: Use of inappropriate language or other behavior deemed -unprofessional or unwelcome in the community. - -**Consequence**: A private, written warning from community leaders, providing -clarity around the nature of the violation and an explanation of why the -behavior was inappropriate. A public apology may be requested. - -### 2. Warning - -**Community Impact**: A violation through a single incident or series -of actions. - -**Consequence**: A warning with consequences for continued behavior. No -interaction with the people involved, including unsolicited interaction with -those enforcing the Code of Conduct, for a specified period of time. This -includes avoiding interactions in community spaces as well as external channels -like social media. Violating these terms may lead to a temporary or -permanent ban. - -### 3. Temporary Ban - -**Community Impact**: A serious violation of community standards, including -sustained inappropriate behavior. - -**Consequence**: A temporary ban from any sort of interaction or public -communication with the community for a specified period of time. No public or -private interaction with the people involved, including unsolicited interaction -with those enforcing the Code of Conduct, is allowed during this period. -Violating these terms may lead to a permanent ban. - -### 4. Permanent Ban - -**Community Impact**: Demonstrating a pattern of violation of community -standards, including sustained inappropriate behavior, harassment of an -individual, or aggression toward or disparagement of classes of individuals. - -**Consequence**: A permanent ban from any sort of public interaction within -the community. - -## Attribution - -This Code of Conduct is adapted from the [Contributor Covenant][homepage], -version 2.0, available at -https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. - -Community Impact Guidelines were inspired by [Mozilla's code of conduct -enforcement ladder](https://github.com/mozilla/diversity). - -[homepage]: https://www.contributor-covenant.org - -For answers to common questions about this code of conduct, see the FAQ at -https://www.contributor-covenant.org/faq. Translations are available at -https://www.contributor-covenant.org/translations. diff --git a/Software/src/lib/mathieucarbou-AsyncTCP/README.md b/Software/src/lib/mathieucarbou-AsyncTCP/README.md deleted file mode 100644 index d90814a1..00000000 --- a/Software/src/lib/mathieucarbou-AsyncTCP/README.md +++ /dev/null @@ -1,62 +0,0 @@ -# AsyncTCP - -[![License: LGPL 3.0](https://img.shields.io/badge/License-LGPL%203.0-yellow.svg)](https://opensource.org/license/lgpl-3-0/) -[![Continuous Integration](https://github.com/mathieucarbou/AsyncTCP/actions/workflows/ci.yml/badge.svg)](https://github.com/mathieucarbou/AsyncTCP/actions/workflows/ci.yml) -[![PlatformIO Registry](https://badges.registry.platformio.org/packages/mathieucarbou/library/AsyncTCP.svg)](https://registry.platformio.org/libraries/mathieucarbou/AsyncTCP) - -A fork of the [AsyncTCP](https://github.com/me-no-dev/AsyncTCP) library by [@me-no-dev](https://github.com/me-no-dev). - -### Async TCP Library for ESP32 Arduino - -This is a fully asynchronous TCP library, aimed at enabling trouble-free, multi-connection network environment for Espressif's ESP32 MCUs. - -This library is the base for [ESPAsyncWebServer](https://github.com/mathieucarbou/ESPAsyncWebServer) - -## AsyncClient and AsyncServer - -The base classes on which everything else is built. They expose all possible scenarios, but are really raw and require more skills to use. - -## Changes in this fork - -- Based on [ESPHome fork](https://github.com/esphome/AsyncTCP) - -- `library.properties` for Arduino IDE users -- Add `CONFIG_ASYNC_TCP_MAX_ACK_TIME` -- Add `CONFIG_ASYNC_TCP_PRIORITY` -- Add `CONFIG_ASYNC_TCP_QUEUE_SIZE` -- Add `setKeepAlive()` -- Arduino 3 / ESP-IDF 5 compatibility -- Better CI -- Better example -- Customizable macros -- Fix for "Required to lock TCPIP core functionality". Ref: https://github.com/mathieucarbou/AsyncTCP/issues/27 and https://github.com/espressif/arduino-esp32/issues/10526 -- Fix for "ack timeout 4" client disconnects. -- Fix from https://github.com/me-no-dev/AsyncTCP/pull/173 (partially applied) -- Fix from https://github.com/me-no-dev/AsyncTCP/pull/184 -- IPv6 -- LIBRETINY support -- LibreTuya -- Reduce logging of non critical messages -- Use IPADDR6_INIT() macro to set connecting IPv6 address -- xTaskCreateUniversal function - -## Coordinates - -``` -mathieucarbou/AsyncTCP @ ^3.3.1 -``` - -## Important recommendations - -Most of the crashes are caused by improper configuration of the library for the project. -Here are some recommendations to avoid them. - -I personally use the following configuration in my projects: - -```c++ - -D CONFIG_ASYNC_TCP_MAX_ACK_TIME=5000 // (keep default) - -D CONFIG_ASYNC_TCP_PRIORITY=10 // (keep default) - -D CONFIG_ASYNC_TCP_QUEUE_SIZE=64 // (keep default) - -D CONFIG_ASYNC_TCP_RUNNING_CORE=1 // force async_tcp task to be on same core as the app (default is core 0) - -D CONFIG_ASYNC_TCP_STACK_SIZE=4096 // reduce the stack size (default is 16K) -``` diff --git a/Software/src/lib/mathieucarbou-AsyncTCP/library.json b/Software/src/lib/mathieucarbou-AsyncTCP/library.json deleted file mode 100644 index 5d6e228b..00000000 --- a/Software/src/lib/mathieucarbou-AsyncTCP/library.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "name": "AsyncTCP", - "version": "3.3.1", - "description": "Asynchronous TCP Library for ESP32", - "keywords": "async,tcp", - "repository": { - "type": "git", - "url": "https://github.com/mathieucarbou/AsyncTCP.git" - }, - "authors": [ - { - "name": "Hristo Gochkov" - }, - { - "name": "Mathieu Carbou", - "maintainer": true - } - ], - "license": "LGPL-3.0", - "frameworks": "arduino", - "platforms": [ - "espressif32", - "libretiny" - ], - "build": { - "libCompatMode": 2 - }, - "export": { - "include": [ - "examples", - "src", - "library.json", - "library.properties", - "LICENSE", - "README.md" - ] - } -} \ No newline at end of file diff --git a/Software/src/lib/mathieucarbou-AsyncTCP/library.properties b/Software/src/lib/mathieucarbou-AsyncTCP/library.properties deleted file mode 100644 index dd945f8d..00000000 --- a/Software/src/lib/mathieucarbou-AsyncTCP/library.properties +++ /dev/null @@ -1,10 +0,0 @@ -name=Async TCP -includes=AsyncTCP.h -version=3.3.1 -author=Me-No-Dev -maintainer=Mathieu Carbou -sentence=Async TCP Library for ESP32 -paragraph=Async TCP Library for ESP32 -category=Other -url=https://github.com/mathieucarbou/AsyncTCP.git -architectures=* diff --git a/Software/src/lib/mathieucarbou-AsyncTCP/platformio.ini b/Software/src/lib/mathieucarbou-AsyncTCP/platformio.ini deleted file mode 100644 index ec65a367..00000000 --- a/Software/src/lib/mathieucarbou-AsyncTCP/platformio.ini +++ /dev/null @@ -1,43 +0,0 @@ -[platformio] -default_envs = arduino-2, arduino-3, arduino-310 -lib_dir = . -src_dir = examples/Client - -[env] -framework = arduino -build_flags = - -Wall -Wextra - -D CONFIG_ASYNC_TCP_MAX_ACK_TIME=5000 - -D CONFIG_ASYNC_TCP_PRIORITY=10 - -D CONFIG_ASYNC_TCP_QUEUE_SIZE=64 - -D CONFIG_ASYNC_TCP_RUNNING_CORE=1 - -D CONFIG_ASYNC_TCP_STACK_SIZE=4096 - -D CONFIG_ARDUHAL_LOG_COLORS - -D CORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG -upload_protocol = esptool -monitor_speed = 115200 -monitor_filters = esp32_exception_decoder, log2file -board = esp32dev - -[env:arduino-2] -platform = espressif32@6.9.0 - -[env:arduino-3] -platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.05/platform-espressif32.zip - -[env:arduino-310] -platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.10-rc3/platform-espressif32.zip - -; CI - -[env:ci-arduino-2] -platform = espressif32@6.9.0 -board = ${sysenv.PIO_BOARD} - -[env:ci-arduino-3] -platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.05/platform-espressif32.zip -board = ${sysenv.PIO_BOARD} - -[env:ci-arduino-310] -platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.10-rc3/platform-espressif32.zip -board = ${sysenv.PIO_BOARD} diff --git a/Software/src/lib/mathieucarbou-AsyncTCP/src/AsyncTCP.cpp b/Software/src/lib/mathieucarbou-AsyncTCP/src/AsyncTCP.cpp deleted file mode 100644 index 9addb135..00000000 --- a/Software/src/lib/mathieucarbou-AsyncTCP/src/AsyncTCP.cpp +++ /dev/null @@ -1,1661 +0,0 @@ -/* - Asynchronous TCP library for Espressif MCUs - - Copyright (c) 2016 Hristo Gochkov. All rights reserved. - This file is part of the esp8266 core for Arduino environment. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "Arduino.h" - -#include "AsyncTCP.h" - -extern "C" { -#include "lwip/dns.h" -#include "lwip/err.h" -#include "lwip/inet.h" -#include "lwip/opt.h" -#include "lwip/tcp.h" -} - -#if CONFIG_ASYNC_TCP_USE_WDT - #include "esp_task_wdt.h" -#endif - -// Required for: -// https://github.com/espressif/arduino-esp32/blob/3.0.3/libraries/Network/src/NetworkInterface.cpp#L37-L47 -#if ESP_IDF_VERSION_MAJOR >= 5 - #include -#endif - -#define TAG "AsyncTCP" - -// https://github.com/espressif/arduino-esp32/issues/10526 -#ifdef CONFIG_LWIP_TCPIP_CORE_LOCKING - #define TCP_MUTEX_LOCK() \ - if (!sys_thread_tcpip(LWIP_CORE_LOCK_QUERY_HOLDER)) { \ - LOCK_TCPIP_CORE(); \ - } - - #define TCP_MUTEX_UNLOCK() \ - if (sys_thread_tcpip(LWIP_CORE_LOCK_QUERY_HOLDER)) { \ - UNLOCK_TCPIP_CORE(); \ - } -#else // CONFIG_LWIP_TCPIP_CORE_LOCKING - #define TCP_MUTEX_LOCK() - #define TCP_MUTEX_UNLOCK() -#endif // CONFIG_LWIP_TCPIP_CORE_LOCKING - -#define INVALID_CLOSED_SLOT -1 - -/* - TCP poll interval is specified in terms of the TCP coarse timer interval, which is called twice a second - https://github.com/espressif/esp-lwip/blob/2acf959a2bb559313cd2bf9306c24612ba3d0e19/src/core/tcp.c#L1895 -*/ -#define CONFIG_ASYNC_TCP_POLL_TIMER 1 - -/* - * TCP/IP Event Task - * */ - -typedef enum { - LWIP_TCP_SENT, - LWIP_TCP_RECV, - LWIP_TCP_FIN, - LWIP_TCP_ERROR, - LWIP_TCP_POLL, - LWIP_TCP_CLEAR, - LWIP_TCP_ACCEPT, - LWIP_TCP_CONNECTED, - LWIP_TCP_DNS -} lwip_event_t; - -typedef struct { - lwip_event_t event; - void* arg; - union { - struct { - tcp_pcb* pcb; - int8_t err; - } connected; - struct { - int8_t err; - } error; - struct { - tcp_pcb* pcb; - uint16_t len; - } sent; - struct { - tcp_pcb* pcb; - pbuf* pb; - int8_t err; - } recv; - struct { - tcp_pcb* pcb; - int8_t err; - } fin; - struct { - tcp_pcb* pcb; - } poll; - struct { - AsyncClient* client; - } accept; - struct { - const char* name; - ip_addr_t addr; - } dns; - }; -} lwip_event_packet_t; - -static QueueHandle_t _async_queue; -static TaskHandle_t _async_service_task_handle = NULL; - -SemaphoreHandle_t _slots_lock; -const int _number_of_closed_slots = CONFIG_LWIP_MAX_ACTIVE_TCP; -static uint32_t _closed_slots[_number_of_closed_slots]; -static uint32_t _closed_index = []() { - _slots_lock = xSemaphoreCreateBinary(); - xSemaphoreGive(_slots_lock); - for (int i = 0; i < _number_of_closed_slots; ++i) { - _closed_slots[i] = 1; - } - return 1; -}(); - -static inline bool _init_async_event_queue() { - if (!_async_queue) { - _async_queue = xQueueCreate(CONFIG_ASYNC_TCP_QUEUE_SIZE, sizeof(lwip_event_packet_t*)); - if (!_async_queue) { - return false; - } - } - return true; -} - -static inline bool _send_async_event(lwip_event_packet_t** e, TickType_t wait = portMAX_DELAY) { - return _async_queue && xQueueSend(_async_queue, e, wait) == pdPASS; -} - -static inline bool _prepend_async_event(lwip_event_packet_t** e, TickType_t wait = portMAX_DELAY) { - return _async_queue && xQueueSendToFront(_async_queue, e, wait) == pdPASS; -} - -static inline bool _get_async_event(lwip_event_packet_t** e) { - if (!_async_queue) { - return false; - } - -#if CONFIG_ASYNC_TCP_USE_WDT - // need to return periodically to feed the dog - if (xQueueReceive(_async_queue, e, pdMS_TO_TICKS(1000)) != pdPASS) - return false; -#else - if (xQueueReceive(_async_queue, e, portMAX_DELAY) != pdPASS) - return false; -#endif - - if ((*e)->event != LWIP_TCP_POLL) - return true; - - /* - Let's try to coalesce two (or more) consecutive poll events into one - this usually happens with poor implemented user-callbacks that are runs too long and makes poll events to stack in the queue - if consecutive user callback for a same connection runs longer that poll time then it will fill the queue with events until it deadlocks. - This is a workaround to mitigate such poor designs and won't let other events/connections to starve the task time. - It won't be effective if user would run multiple simultaneous long running callbacks due to message interleaving. - todo: implement some kind of fair dequeing or (better) simply punish user for a bad designed callbacks by resetting hog connections - */ - lwip_event_packet_t* next_pkt = NULL; - while (xQueuePeek(_async_queue, &next_pkt, 0) == pdPASS) { - if (next_pkt->arg == (*e)->arg && next_pkt->event == LWIP_TCP_POLL) { - if (xQueueReceive(_async_queue, &next_pkt, 0) == pdPASS) { - free(next_pkt); - next_pkt = NULL; - log_d("coalescing polls, network congestion or async callbacks might be too slow!"); - continue; - } - } - - // quit while loop if next event can't be discarded - break; - } - - /* - now we have to decide if to proceed with poll callback handler or discard it? - poor designed apps using asynctcp without proper dataflow control could flood the queue with interleaved pool/ack events. - I.e. on each poll app would try to generate more data to send, which in turn results in additional ack event triggering chain effect - for long connections. Or poll callback could take long time starving other connections. Anyway our goal is to keep the queue length - grows under control (if possible) and poll events are the safest to discard. - Let's discard poll events processing using linear-increasing probability curve when queue size grows over 3/4 - Poll events are periodic and connection could get another chance next time - */ - if (uxQueueMessagesWaiting(_async_queue) > (rand() % CONFIG_ASYNC_TCP_QUEUE_SIZE / 4 + CONFIG_ASYNC_TCP_QUEUE_SIZE * 3 / 4)) { - free(*e); - *e = NULL; - log_d("discarding poll due to queue congestion"); - // evict next event from a queue - return _get_async_event(e); - } - - // last resort return - return true; -} - -static bool _remove_events_with_arg(void* arg) { - if (!_async_queue) { - return false; - } - - lwip_event_packet_t* first_packet = NULL; - lwip_event_packet_t* packet = NULL; - - // figure out which is the first non-matching packet so we can keep the order - while (!first_packet) { - if (xQueueReceive(_async_queue, &first_packet, 0) != pdPASS) { - return false; - } - // discard packet if matching - if ((int)first_packet->arg == (int)arg) { - free(first_packet); - first_packet = NULL; - } else if (xQueueSend(_async_queue, &first_packet, 0) != pdPASS) { - // try to return first packet to the back of the queue - // we can't wait here if queue is full, because this call has been done from the only consumer task of this queue - // otherwise it would deadlock, we have to discard the event - free(first_packet); - first_packet = NULL; - return false; - } - } - - while (xQueuePeek(_async_queue, &packet, 0) == pdPASS && packet != first_packet) { - if (xQueueReceive(_async_queue, &packet, 0) != pdPASS) { - return false; - } - if ((int)packet->arg == (int)arg) { - // remove matching event - free(packet); - packet = NULL; - // otherwise try to requeue it - } else if (xQueueSend(_async_queue, &packet, 0) != pdPASS) { - // we can't wait here if queue is full, because this call has been done from the only consumer task of this queue - // otherwise it would deadlock, we have to discard the event - free(packet); - packet = NULL; - return false; - } - } - return true; -} - -static void _handle_async_event(lwip_event_packet_t* e) { - if (e->arg == NULL) { - // do nothing when arg is NULL - // ets_printf("event arg == NULL: 0x%08x\n", e->recv.pcb); - } else if (e->event == LWIP_TCP_CLEAR) { - _remove_events_with_arg(e->arg); - } else if (e->event == LWIP_TCP_RECV) { - // ets_printf("-R: 0x%08x\n", e->recv.pcb); - AsyncClient::_s_recv(e->arg, e->recv.pcb, e->recv.pb, e->recv.err); - } else if (e->event == LWIP_TCP_FIN) { - // ets_printf("-F: 0x%08x\n", e->fin.pcb); - AsyncClient::_s_fin(e->arg, e->fin.pcb, e->fin.err); - } else if (e->event == LWIP_TCP_SENT) { - // ets_printf("-S: 0x%08x\n", e->sent.pcb); - AsyncClient::_s_sent(e->arg, e->sent.pcb, e->sent.len); - } else if (e->event == LWIP_TCP_POLL) { - // ets_printf("-P: 0x%08x\n", e->poll.pcb); - AsyncClient::_s_poll(e->arg, e->poll.pcb); - } else if (e->event == LWIP_TCP_ERROR) { - // ets_printf("-E: 0x%08x %d\n", e->arg, e->error.err); - AsyncClient::_s_error(e->arg, e->error.err); - } else if (e->event == LWIP_TCP_CONNECTED) { - // ets_printf("C: 0x%08x 0x%08x %d\n", e->arg, e->connected.pcb, e->connected.err); - AsyncClient::_s_connected(e->arg, e->connected.pcb, e->connected.err); - } else if (e->event == LWIP_TCP_ACCEPT) { - // ets_printf("A: 0x%08x 0x%08x\n", e->arg, e->accept.client); - AsyncServer::_s_accepted(e->arg, e->accept.client); - } else if (e->event == LWIP_TCP_DNS) { - // ets_printf("D: 0x%08x %s = %s\n", e->arg, e->dns.name, ipaddr_ntoa(&e->dns.addr)); - AsyncClient::_s_dns_found(e->dns.name, &e->dns.addr, e->arg); - } - free((void*)(e)); -} - -static void _async_service_task(void* pvParameters) { -#if CONFIG_ASYNC_TCP_USE_WDT - if (esp_task_wdt_add(NULL) != ESP_OK) { - log_w("Failed to add async task to WDT"); - } -#endif - lwip_event_packet_t* packet = NULL; - for (;;) { - if (_get_async_event(&packet)) { - _handle_async_event(packet); - } -#if CONFIG_ASYNC_TCP_USE_WDT - esp_task_wdt_reset(); -#endif - } -#if CONFIG_ASYNC_TCP_USE_WDT - esp_task_wdt_delete(NULL); -#endif - vTaskDelete(NULL); - _async_service_task_handle = NULL; -} -/* -static void _stop_async_task(){ - if(_async_service_task_handle){ - vTaskDelete(_async_service_task_handle); - _async_service_task_handle = NULL; - } -} -*/ - -static bool customTaskCreateUniversal( - TaskFunction_t pxTaskCode, - const char* const pcName, - const uint32_t usStackDepth, - void* const pvParameters, - UBaseType_t uxPriority, - TaskHandle_t* const pxCreatedTask, - const BaseType_t xCoreID) { -#ifndef CONFIG_FREERTOS_UNICORE - if (xCoreID >= 0 && xCoreID < 2) { - return xTaskCreatePinnedToCore(pxTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask, xCoreID); - } else { -#endif - return xTaskCreate(pxTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask); -#ifndef CONFIG_FREERTOS_UNICORE - } -#endif -} - -static bool _start_async_task() { - if (!_init_async_event_queue()) { - return false; - } - if (!_async_service_task_handle) { - customTaskCreateUniversal(_async_service_task, "async_tcp", CONFIG_ASYNC_TCP_STACK_SIZE, NULL, TASK_CONNECTIVITY_PRIO, &_async_service_task_handle, CONFIG_ASYNC_TCP_RUNNING_CORE); - if (!_async_service_task_handle) { - return false; - } - } - return true; -} - -/* - * LwIP Callbacks - * */ - -static int8_t _tcp_clear_events(void* arg) { - lwip_event_packet_t* e = (lwip_event_packet_t*)malloc(sizeof(lwip_event_packet_t)); - e->event = LWIP_TCP_CLEAR; - e->arg = arg; - if (!_prepend_async_event(&e)) { - free((void*)(e)); - } - return ERR_OK; -} - -static int8_t _tcp_connected(void* arg, tcp_pcb* pcb, int8_t err) { - // ets_printf("+C: 0x%08x\n", pcb); - lwip_event_packet_t* e = (lwip_event_packet_t*)malloc(sizeof(lwip_event_packet_t)); - e->event = LWIP_TCP_CONNECTED; - e->arg = arg; - e->connected.pcb = pcb; - e->connected.err = err; - if (!_prepend_async_event(&e)) { - free((void*)(e)); - } - return ERR_OK; -} - -static int8_t _tcp_poll(void* arg, struct tcp_pcb* pcb) { - // throttle polling events queing when event queue is getting filled up, let it handle _onack's - // log_d("qs:%u", uxQueueMessagesWaiting(_async_queue)); - if (uxQueueMessagesWaiting(_async_queue) > (rand() % CONFIG_ASYNC_TCP_QUEUE_SIZE / 2 + CONFIG_ASYNC_TCP_QUEUE_SIZE / 4)) { - log_d("throttling"); - return ERR_OK; - } - - // ets_printf("+P: 0x%08x\n", pcb); - lwip_event_packet_t* e = (lwip_event_packet_t*)malloc(sizeof(lwip_event_packet_t)); - e->event = LWIP_TCP_POLL; - e->arg = arg; - e->poll.pcb = pcb; - // poll events are not critical 'cause those are repetitive, so we may not wait the queue in any case - if (!_send_async_event(&e, 0)) { - free((void*)(e)); - } - return ERR_OK; -} - -static int8_t _tcp_recv(void* arg, struct tcp_pcb* pcb, struct pbuf* pb, int8_t err) { - lwip_event_packet_t* e = (lwip_event_packet_t*)malloc(sizeof(lwip_event_packet_t)); - e->arg = arg; - if (pb) { - // ets_printf("+R: 0x%08x\n", pcb); - e->event = LWIP_TCP_RECV; - e->recv.pcb = pcb; - e->recv.pb = pb; - e->recv.err = err; - } else { - // ets_printf("+F: 0x%08x\n", pcb); - e->event = LWIP_TCP_FIN; - e->fin.pcb = pcb; - e->fin.err = err; - // close the PCB in LwIP thread - AsyncClient::_s_lwip_fin(e->arg, e->fin.pcb, e->fin.err); - } - if (!_send_async_event(&e)) { - free((void*)(e)); - } - return ERR_OK; -} - -static int8_t _tcp_sent(void* arg, struct tcp_pcb* pcb, uint16_t len) { - // ets_printf("+S: 0x%08x\n", pcb); - lwip_event_packet_t* e = (lwip_event_packet_t*)malloc(sizeof(lwip_event_packet_t)); - e->event = LWIP_TCP_SENT; - e->arg = arg; - e->sent.pcb = pcb; - e->sent.len = len; - if (!_send_async_event(&e)) { - free((void*)(e)); - } - return ERR_OK; -} - -static void _tcp_error(void* arg, int8_t err) { - // ets_printf("+E: 0x%08x\n", arg); - lwip_event_packet_t* e = (lwip_event_packet_t*)malloc(sizeof(lwip_event_packet_t)); - e->event = LWIP_TCP_ERROR; - e->arg = arg; - e->error.err = err; - if (!_send_async_event(&e)) { - free((void*)(e)); - } -} - -static void _tcp_dns_found(const char* name, struct ip_addr* ipaddr, void* arg) { - lwip_event_packet_t* e = (lwip_event_packet_t*)malloc(sizeof(lwip_event_packet_t)); - // ets_printf("+DNS: name=%s ipaddr=0x%08x arg=%x\n", name, ipaddr, arg); - e->event = LWIP_TCP_DNS; - e->arg = arg; - e->dns.name = name; - if (ipaddr) { - memcpy(&e->dns.addr, ipaddr, sizeof(struct ip_addr)); - } else { - memset(&e->dns.addr, 0, sizeof(e->dns.addr)); - } - if (!_send_async_event(&e)) { - free((void*)(e)); - } -} - -// Used to switch out from LwIP thread -static int8_t _tcp_accept(void* arg, AsyncClient* client) { - lwip_event_packet_t* e = (lwip_event_packet_t*)malloc(sizeof(lwip_event_packet_t)); - e->event = LWIP_TCP_ACCEPT; - e->arg = arg; - e->accept.client = client; - if (!_prepend_async_event(&e)) { - free((void*)(e)); - } - return ERR_OK; -} - -/* - * TCP/IP API Calls - * */ - -#include "lwip/priv/tcpip_priv.h" - -typedef struct { - struct tcpip_api_call_data call; - tcp_pcb* pcb; - int8_t closed_slot; - int8_t err; - union { - struct { - const char* data; - size_t size; - uint8_t apiflags; - } write; - size_t received; - struct { - ip_addr_t* addr; - uint16_t port; - tcp_connected_fn cb; - } connect; - struct { - ip_addr_t* addr; - uint16_t port; - } bind; - uint8_t backlog; - }; -} tcp_api_call_t; - -static err_t _tcp_output_api(struct tcpip_api_call_data* api_call_msg) { - tcp_api_call_t* msg = (tcp_api_call_t*)api_call_msg; - msg->err = ERR_CONN; - if (msg->closed_slot == INVALID_CLOSED_SLOT || !_closed_slots[msg->closed_slot]) { - msg->err = tcp_output(msg->pcb); - } - return msg->err; -} - -static esp_err_t _tcp_output(tcp_pcb* pcb, int8_t closed_slot) { - if (!pcb) { - return ERR_CONN; - } - tcp_api_call_t msg; - msg.pcb = pcb; - msg.closed_slot = closed_slot; - tcpip_api_call(_tcp_output_api, (struct tcpip_api_call_data*)&msg); - return msg.err; -} - -static err_t _tcp_write_api(struct tcpip_api_call_data* api_call_msg) { - tcp_api_call_t* msg = (tcp_api_call_t*)api_call_msg; - msg->err = ERR_CONN; - if (msg->closed_slot == INVALID_CLOSED_SLOT || !_closed_slots[msg->closed_slot]) { - msg->err = tcp_write(msg->pcb, msg->write.data, msg->write.size, msg->write.apiflags); - } - return msg->err; -} - -static esp_err_t _tcp_write(tcp_pcb* pcb, int8_t closed_slot, const char* data, size_t size, uint8_t apiflags) { - if (!pcb) { - return ERR_CONN; - } - tcp_api_call_t msg; - msg.pcb = pcb; - msg.closed_slot = closed_slot; - msg.write.data = data; - msg.write.size = size; - msg.write.apiflags = apiflags; - tcpip_api_call(_tcp_write_api, (struct tcpip_api_call_data*)&msg); - return msg.err; -} - -static err_t _tcp_recved_api(struct tcpip_api_call_data* api_call_msg) { - tcp_api_call_t* msg = (tcp_api_call_t*)api_call_msg; - msg->err = ERR_CONN; - if (msg->closed_slot == INVALID_CLOSED_SLOT || !_closed_slots[msg->closed_slot]) { - // if(msg->closed_slot != INVALID_CLOSED_SLOT && !_closed_slots[msg->closed_slot]) { - // if(msg->closed_slot != INVALID_CLOSED_SLOT) { - msg->err = 0; - tcp_recved(msg->pcb, msg->received); - } - return msg->err; -} - -static esp_err_t _tcp_recved(tcp_pcb* pcb, int8_t closed_slot, size_t len) { - if (!pcb) { - return ERR_CONN; - } - tcp_api_call_t msg; - msg.pcb = pcb; - msg.closed_slot = closed_slot; - msg.received = len; - tcpip_api_call(_tcp_recved_api, (struct tcpip_api_call_data*)&msg); - return msg.err; -} - -static err_t _tcp_close_api(struct tcpip_api_call_data* api_call_msg) { - tcp_api_call_t* msg = (tcp_api_call_t*)api_call_msg; - msg->err = ERR_CONN; - if (msg->closed_slot == INVALID_CLOSED_SLOT || !_closed_slots[msg->closed_slot]) { - msg->err = tcp_close(msg->pcb); - } - return msg->err; -} - -static esp_err_t _tcp_close(tcp_pcb* pcb, int8_t closed_slot) { - if (!pcb) { - return ERR_CONN; - } - tcp_api_call_t msg; - msg.pcb = pcb; - msg.closed_slot = closed_slot; - tcpip_api_call(_tcp_close_api, (struct tcpip_api_call_data*)&msg); - return msg.err; -} - -static err_t _tcp_abort_api(struct tcpip_api_call_data* api_call_msg) { - tcp_api_call_t* msg = (tcp_api_call_t*)api_call_msg; - msg->err = ERR_CONN; - if (msg->closed_slot == INVALID_CLOSED_SLOT || !_closed_slots[msg->closed_slot]) { - tcp_abort(msg->pcb); - } - return msg->err; -} - -static esp_err_t _tcp_abort(tcp_pcb* pcb, int8_t closed_slot) { - if (!pcb) { - return ERR_CONN; - } - tcp_api_call_t msg; - msg.pcb = pcb; - msg.closed_slot = closed_slot; - tcpip_api_call(_tcp_abort_api, (struct tcpip_api_call_data*)&msg); - return msg.err; -} - -static err_t _tcp_connect_api(struct tcpip_api_call_data* api_call_msg) { - tcp_api_call_t* msg = (tcp_api_call_t*)api_call_msg; - msg->err = tcp_connect(msg->pcb, msg->connect.addr, msg->connect.port, msg->connect.cb); - return msg->err; -} - -static esp_err_t _tcp_connect(tcp_pcb* pcb, int8_t closed_slot, ip_addr_t* addr, uint16_t port, tcp_connected_fn cb) { - if (!pcb) { - return ESP_FAIL; - } - tcp_api_call_t msg; - msg.pcb = pcb; - msg.closed_slot = closed_slot; - msg.connect.addr = addr; - msg.connect.port = port; - msg.connect.cb = cb; - tcpip_api_call(_tcp_connect_api, (struct tcpip_api_call_data*)&msg); - return msg.err; -} - -static err_t _tcp_bind_api(struct tcpip_api_call_data* api_call_msg) { - tcp_api_call_t* msg = (tcp_api_call_t*)api_call_msg; - msg->err = tcp_bind(msg->pcb, msg->bind.addr, msg->bind.port); - return msg->err; -} - -static esp_err_t _tcp_bind(tcp_pcb* pcb, ip_addr_t* addr, uint16_t port) { - if (!pcb) { - return ESP_FAIL; - } - tcp_api_call_t msg; - msg.pcb = pcb; - msg.closed_slot = -1; - msg.bind.addr = addr; - msg.bind.port = port; - tcpip_api_call(_tcp_bind_api, (struct tcpip_api_call_data*)&msg); - return msg.err; -} - -static err_t _tcp_listen_api(struct tcpip_api_call_data* api_call_msg) { - tcp_api_call_t* msg = (tcp_api_call_t*)api_call_msg; - msg->err = 0; - msg->pcb = tcp_listen_with_backlog(msg->pcb, msg->backlog); - return msg->err; -} - -static tcp_pcb* _tcp_listen_with_backlog(tcp_pcb* pcb, uint8_t backlog) { - if (!pcb) { - return NULL; - } - tcp_api_call_t msg; - msg.pcb = pcb; - msg.closed_slot = -1; - msg.backlog = backlog ? backlog : 0xFF; - tcpip_api_call(_tcp_listen_api, (struct tcpip_api_call_data*)&msg); - return msg.pcb; -} - -/* - Async TCP Client - */ - -AsyncClient::AsyncClient(tcp_pcb* pcb) - : _connect_cb(0), _connect_cb_arg(0), _discard_cb(0), _discard_cb_arg(0), _sent_cb(0), _sent_cb_arg(0), _error_cb(0), _error_cb_arg(0), _recv_cb(0), _recv_cb_arg(0), _pb_cb(0), _pb_cb_arg(0), _timeout_cb(0), _timeout_cb_arg(0), _ack_pcb(true), _tx_last_packet(0), _rx_timeout(0), _rx_last_ack(0), _ack_timeout(CONFIG_ASYNC_TCP_MAX_ACK_TIME), _connect_port(0), prev(NULL), next(NULL) { - _pcb = pcb; - _closed_slot = INVALID_CLOSED_SLOT; - if (_pcb) { - _rx_last_packet = millis(); - tcp_arg(_pcb, this); - tcp_recv(_pcb, &_tcp_recv); - tcp_sent(_pcb, &_tcp_sent); - tcp_err(_pcb, &_tcp_error); - tcp_poll(_pcb, &_tcp_poll, CONFIG_ASYNC_TCP_POLL_TIMER); - if (!_allocate_closed_slot()) { - _close(); - } - } -} - -AsyncClient::~AsyncClient() { - if (_pcb) { - _close(); - } - _free_closed_slot(); -} - -/* - * Operators - * */ - -AsyncClient& AsyncClient::operator=(const AsyncClient& other) { - if (_pcb) { - _close(); - } - - _pcb = other._pcb; - _closed_slot = other._closed_slot; - if (_pcb) { - _rx_last_packet = millis(); - tcp_arg(_pcb, this); - tcp_recv(_pcb, &_tcp_recv); - tcp_sent(_pcb, &_tcp_sent); - tcp_err(_pcb, &_tcp_error); - tcp_poll(_pcb, &_tcp_poll, CONFIG_ASYNC_TCP_POLL_TIMER); - } - return *this; -} - -bool AsyncClient::operator==(const AsyncClient& other) { - return _pcb == other._pcb; -} - -AsyncClient& AsyncClient::operator+=(const AsyncClient& other) { - if (next == NULL) { - next = (AsyncClient*)(&other); - next->prev = this; - } else { - AsyncClient* c = next; - while (c->next != NULL) { - c = c->next; - } - c->next = (AsyncClient*)(&other); - c->next->prev = c; - } - return *this; -} - -/* - * Callback Setters - * */ - -void AsyncClient::onConnect(AcConnectHandler cb, void* arg) { - _connect_cb = cb; - _connect_cb_arg = arg; -} - -void AsyncClient::onDisconnect(AcConnectHandler cb, void* arg) { - _discard_cb = cb; - _discard_cb_arg = arg; -} - -void AsyncClient::onAck(AcAckHandler cb, void* arg) { - _sent_cb = cb; - _sent_cb_arg = arg; -} - -void AsyncClient::onError(AcErrorHandler cb, void* arg) { - _error_cb = cb; - _error_cb_arg = arg; -} - -void AsyncClient::onData(AcDataHandler cb, void* arg) { - _recv_cb = cb; - _recv_cb_arg = arg; -} - -void AsyncClient::onPacket(AcPacketHandler cb, void* arg) { - _pb_cb = cb; - _pb_cb_arg = arg; -} - -void AsyncClient::onTimeout(AcTimeoutHandler cb, void* arg) { - _timeout_cb = cb; - _timeout_cb_arg = arg; -} - -void AsyncClient::onPoll(AcConnectHandler cb, void* arg) { - _poll_cb = cb; - _poll_cb_arg = arg; -} - -/* - * Main Public Methods - * */ - -bool AsyncClient::_connect(ip_addr_t addr, uint16_t port) { - if (_pcb) { - log_d("already connected, state %d", _pcb->state); - return false; - } - if (!_start_async_task()) { - log_e("failed to start task"); - return false; - } - - if (!_allocate_closed_slot()) { - log_e("failed to allocate: closed slot full"); - return false; - } - - TCP_MUTEX_LOCK(); - tcp_pcb* pcb = tcp_new_ip_type(addr.type); - if (!pcb) { - TCP_MUTEX_UNLOCK(); - log_e("pcb == NULL"); - return false; - } - tcp_arg(pcb, this); - tcp_err(pcb, &_tcp_error); - tcp_recv(pcb, &_tcp_recv); - tcp_sent(pcb, &_tcp_sent); - tcp_poll(pcb, &_tcp_poll, CONFIG_ASYNC_TCP_POLL_TIMER); - TCP_MUTEX_UNLOCK(); - - esp_err_t err = _tcp_connect(pcb, _closed_slot, &addr, port, (tcp_connected_fn)&_tcp_connected); - return err == ESP_OK; -} - -bool AsyncClient::connect(const IPAddress& ip, uint16_t port) { - ip_addr_t addr; -#if ESP_IDF_VERSION_MAJOR < 5 - addr.u_addr.ip4.addr = ip; - addr.type = IPADDR_TYPE_V4; -#else - ip.to_ip_addr_t(&addr); -#endif - - return _connect(addr, port); -} - -#if LWIP_IPV6 && ESP_IDF_VERSION_MAJOR < 5 -bool AsyncClient::connect(const IPv6Address& ip, uint16_t port) { - auto ipaddr = static_cast(ip); - ip_addr_t addr = IPADDR6_INIT(ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]); - - return _connect(addr, port); -} -#endif - -bool AsyncClient::connect(const char* host, uint16_t port) { - ip_addr_t addr; - - if (!_start_async_task()) { - log_e("failed to start task"); - return false; - } - - TCP_MUTEX_LOCK(); - err_t err = dns_gethostbyname(host, &addr, (dns_found_callback)&_tcp_dns_found, this); - TCP_MUTEX_UNLOCK(); - if (err == ERR_OK) { -#if ESP_IDF_VERSION_MAJOR < 5 - #if LWIP_IPV6 - if (addr.type == IPADDR_TYPE_V6) { - return connect(IPv6Address(addr.u_addr.ip6.addr), port); - } - return connect(IPAddress(addr.u_addr.ip4.addr), port); - #else - return connect(IPAddress(addr.addr), port); - #endif -#else - return _connect(addr, port); -#endif - } else if (err == ERR_INPROGRESS) { - _connect_port = port; - return true; - } - log_d("error: %d", err); - return false; -} - -void AsyncClient::close(bool now) { - if (_pcb) { - _tcp_recved(_pcb, _closed_slot, _rx_ack_len); - } - _close(); -} - -int8_t AsyncClient::abort() { - if (_pcb) { - _tcp_abort(_pcb, _closed_slot); - _pcb = NULL; - } - return ERR_ABRT; -} - -size_t AsyncClient::space() { - if ((_pcb != NULL) && (_pcb->state == ESTABLISHED)) { - return tcp_sndbuf(_pcb); - } - return 0; -} - -size_t AsyncClient::add(const char* data, size_t size, uint8_t apiflags) { - if (!_pcb || size == 0 || data == NULL) { - return 0; - } - size_t room = space(); - if (!room) { - return 0; - } - size_t will_send = (room < size) ? room : size; - int8_t err = ERR_OK; - err = _tcp_write(_pcb, _closed_slot, data, will_send, apiflags); - if (err != ERR_OK) { - return 0; - } - return will_send; -} - -bool AsyncClient::send() { - auto backup = _tx_last_packet; - _tx_last_packet = millis(); - if (_tcp_output(_pcb, _closed_slot) == ERR_OK) { - return true; - } - _tx_last_packet = backup; - return false; -} - -size_t AsyncClient::ack(size_t len) { - if (len > _rx_ack_len) - len = _rx_ack_len; - if (len) { - _tcp_recved(_pcb, _closed_slot, len); - } - _rx_ack_len -= len; - return len; -} - -void AsyncClient::ackPacket(struct pbuf* pb) { - if (!pb) { - return; - } - _tcp_recved(_pcb, _closed_slot, pb->len); - pbuf_free(pb); -} - -/* - * Main Private Methods - * */ - -int8_t AsyncClient::_close() { - // ets_printf("X: 0x%08x\n", (uint32_t)this); - int8_t err = ERR_OK; - if (_pcb) { - TCP_MUTEX_LOCK(); - tcp_arg(_pcb, NULL); - tcp_sent(_pcb, NULL); - tcp_recv(_pcb, NULL); - tcp_err(_pcb, NULL); - tcp_poll(_pcb, NULL, 0); - TCP_MUTEX_UNLOCK(); - _tcp_clear_events(this); - err = _tcp_close(_pcb, _closed_slot); - if (err != ERR_OK) { - err = abort(); - } - _free_closed_slot(); - _pcb = NULL; - if (_discard_cb) { - _discard_cb(_discard_cb_arg, this); - } - } - return err; -} - -bool AsyncClient::_allocate_closed_slot() { - if (_closed_slot != INVALID_CLOSED_SLOT) { - return true; - } - xSemaphoreTake(_slots_lock, portMAX_DELAY); - uint32_t closed_slot_min_index = 0; - for (int i = 0; i < _number_of_closed_slots; ++i) { - if ((_closed_slot == INVALID_CLOSED_SLOT || _closed_slots[i] <= closed_slot_min_index) && _closed_slots[i] != 0) { - closed_slot_min_index = _closed_slots[i]; - _closed_slot = i; - } - } - if (_closed_slot != INVALID_CLOSED_SLOT) { - _closed_slots[_closed_slot] = 0; - } - xSemaphoreGive(_slots_lock); - return (_closed_slot != INVALID_CLOSED_SLOT); -} - -void AsyncClient::_free_closed_slot() { - xSemaphoreTake(_slots_lock, portMAX_DELAY); - if (_closed_slot != INVALID_CLOSED_SLOT) { - _closed_slots[_closed_slot] = _closed_index; - _closed_slot = INVALID_CLOSED_SLOT; - ++_closed_index; - } - xSemaphoreGive(_slots_lock); -} - -/* - * Private Callbacks - * */ - -int8_t AsyncClient::_connected(tcp_pcb* pcb, int8_t err) { - _pcb = reinterpret_cast(pcb); - if (_pcb) { - _rx_last_packet = millis(); - } - if (_connect_cb) { - _connect_cb(_connect_cb_arg, this); - } - return ERR_OK; -} - -void AsyncClient::_error(int8_t err) { - if (_pcb) { - TCP_MUTEX_LOCK(); - tcp_arg(_pcb, NULL); - if (_pcb->state == LISTEN) { - tcp_sent(_pcb, NULL); - tcp_recv(_pcb, NULL); - tcp_err(_pcb, NULL); - tcp_poll(_pcb, NULL, 0); - } - TCP_MUTEX_UNLOCK(); - _free_closed_slot(); - _pcb = NULL; - } - if (_error_cb) { - _error_cb(_error_cb_arg, this, err); - } - if (_discard_cb) { - _discard_cb(_discard_cb_arg, this); - } -} - -// In LwIP Thread -int8_t AsyncClient::_lwip_fin(tcp_pcb* pcb, int8_t err) { - if (!_pcb || pcb != _pcb) { - log_d("0x%08x != 0x%08x", (uint32_t)pcb, (uint32_t)_pcb); - return ERR_OK; - } - tcp_arg(_pcb, NULL); - if (_pcb->state == LISTEN) { - tcp_sent(_pcb, NULL); - tcp_recv(_pcb, NULL); - tcp_err(_pcb, NULL); - tcp_poll(_pcb, NULL, 0); - } - if (tcp_close(_pcb) != ERR_OK) { - tcp_abort(_pcb); - } - _free_closed_slot(); - _pcb = NULL; - return ERR_OK; -} - -// In Async Thread -int8_t AsyncClient::_fin(tcp_pcb* pcb, int8_t err) { - _tcp_clear_events(this); - if (_discard_cb) { - _discard_cb(_discard_cb_arg, this); - } - return ERR_OK; -} - -int8_t AsyncClient::_sent(tcp_pcb* pcb, uint16_t len) { - _rx_last_ack = _rx_last_packet = millis(); - if (_sent_cb) { - _sent_cb(_sent_cb_arg, this, len, (_rx_last_packet - _tx_last_packet)); - } - return ERR_OK; -} - -int8_t AsyncClient::_recv(tcp_pcb* pcb, pbuf* pb, int8_t err) { - while (pb != NULL) { - _rx_last_packet = millis(); - // we should not ack before we assimilate the data - _ack_pcb = true; - pbuf* b = pb; - pb = b->next; - b->next = NULL; - if (_pb_cb) { - _pb_cb(_pb_cb_arg, this, b); - } else { - if (_recv_cb) { - _recv_cb(_recv_cb_arg, this, b->payload, b->len); - } - if (!_ack_pcb) { - _rx_ack_len += b->len; - } else if (_pcb) { - _tcp_recved(_pcb, _closed_slot, b->len); - } - } - pbuf_free(b); - } - return ERR_OK; -} - -int8_t AsyncClient::_poll(tcp_pcb* pcb) { - if (!_pcb) { - // log_d("pcb is NULL"); - return ERR_OK; - } - if (pcb != _pcb) { - log_d("0x%08x != 0x%08x", (uint32_t)pcb, (uint32_t)_pcb); - return ERR_OK; - } - - uint32_t now = millis(); - - // ACK Timeout - if (_ack_timeout) { - const uint32_t one_day = 86400000; - bool last_tx_is_after_last_ack = (_rx_last_ack - _tx_last_packet + one_day) < one_day; - if (last_tx_is_after_last_ack && (now - _tx_last_packet) >= _ack_timeout) { - log_d("ack timeout %d", pcb->state); - if (_timeout_cb) - _timeout_cb(_timeout_cb_arg, this, (now - _tx_last_packet)); - return ERR_OK; - } - } - // RX Timeout - if (_rx_timeout && (now - _rx_last_packet) >= (_rx_timeout * 1000)) { - log_d("rx timeout %d", pcb->state); - _close(); - return ERR_OK; - } - // Everything is fine - if (_poll_cb) { - _poll_cb(_poll_cb_arg, this); - } - return ERR_OK; -} - -void AsyncClient::_dns_found(struct ip_addr* ipaddr) { -#if ESP_IDF_VERSION_MAJOR < 5 - if (ipaddr && IP_IS_V4(ipaddr)) { - connect(IPAddress(ip_addr_get_ip4_u32(ipaddr)), _connect_port); - #if LWIP_IPV6 - } else if (ipaddr && ipaddr->u_addr.ip6.addr) { - connect(IPv6Address(ipaddr->u_addr.ip6.addr), _connect_port); - #endif -#else - if (ipaddr) { - IPAddress ip; - ip.from_ip_addr_t(ipaddr); - connect(ip, _connect_port); -#endif - } else { - if (_error_cb) { - _error_cb(_error_cb_arg, this, -55); - } - if (_discard_cb) { - _discard_cb(_discard_cb_arg, this); - } - } -} - -/* - * Public Helper Methods - * */ - -bool AsyncClient::free() { - if (!_pcb) { - return true; - } - if (_pcb->state == CLOSED || _pcb->state > ESTABLISHED) { - return true; - } - return false; -} - -size_t AsyncClient::write(const char* data, size_t size, uint8_t apiflags) { - size_t will_send = add(data, size, apiflags); - if (!will_send || !send()) { - return 0; - } - return will_send; -} - -void AsyncClient::setRxTimeout(uint32_t timeout) { - _rx_timeout = timeout; -} - -uint32_t AsyncClient::getRxTimeout() { - return _rx_timeout; -} - -uint32_t AsyncClient::getAckTimeout() { - return _ack_timeout; -} - -void AsyncClient::setAckTimeout(uint32_t timeout) { - _ack_timeout = timeout; -} - -void AsyncClient::setNoDelay(bool nodelay) { - if (!_pcb) { - return; - } - if (nodelay) { - tcp_nagle_disable(_pcb); - } else { - tcp_nagle_enable(_pcb); - } -} - -bool AsyncClient::getNoDelay() { - if (!_pcb) { - return false; - } - return tcp_nagle_disabled(_pcb); -} - -void AsyncClient::setKeepAlive(uint32_t ms, uint8_t cnt) { - if (ms != 0) { - _pcb->so_options |= SOF_KEEPALIVE; // Turn on TCP Keepalive for the given pcb - // Set the time between keepalive messages in milli-seconds - _pcb->keep_idle = ms; - _pcb->keep_intvl = ms; - _pcb->keep_cnt = cnt; // The number of unanswered probes required to force closure of the socket - } else { - _pcb->so_options &= ~SOF_KEEPALIVE; // Turn off TCP Keepalive for the given pcb - } -} - -uint16_t AsyncClient::getMss() { - if (!_pcb) { - return 0; - } - return tcp_mss(_pcb); -} - -uint32_t AsyncClient::getRemoteAddress() { - if (!_pcb) { - return 0; - } -#if LWIP_IPV4 && LWIP_IPV6 - return _pcb->remote_ip.u_addr.ip4.addr; -#else - return _pcb->remote_ip.addr; -#endif -} - -#if LWIP_IPV6 -ip6_addr_t AsyncClient::getRemoteAddress6() { - if (!_pcb) { - ip6_addr_t nulladdr; - ip6_addr_set_zero(&nulladdr); - return nulladdr; - } - return _pcb->remote_ip.u_addr.ip6; -} - -ip6_addr_t AsyncClient::getLocalAddress6() { - if (!_pcb) { - ip6_addr_t nulladdr; - ip6_addr_set_zero(&nulladdr); - return nulladdr; - } - return _pcb->local_ip.u_addr.ip6; -} - #if ESP_IDF_VERSION_MAJOR < 5 -IPv6Address AsyncClient::remoteIP6() { - return IPv6Address(getRemoteAddress6().addr); -} - -IPv6Address AsyncClient::localIP6() { - return IPv6Address(getLocalAddress6().addr); -} - #else -IPAddress AsyncClient::remoteIP6() { - if (!_pcb) { - return IPAddress(IPType::IPv6); - } - IPAddress ip; - ip.from_ip_addr_t(&(_pcb->remote_ip)); - return ip; -} - -IPAddress AsyncClient::localIP6() { - if (!_pcb) { - return IPAddress(IPType::IPv6); - } - IPAddress ip; - ip.from_ip_addr_t(&(_pcb->local_ip)); - return ip; -} - #endif -#endif - -uint16_t AsyncClient::getRemotePort() { - if (!_pcb) { - return 0; - } - return _pcb->remote_port; -} - -uint32_t AsyncClient::getLocalAddress() { - if (!_pcb) { - return 0; - } -#if LWIP_IPV4 && LWIP_IPV6 - return _pcb->local_ip.u_addr.ip4.addr; -#else - return _pcb->local_ip.addr; -#endif -} - -uint16_t AsyncClient::getLocalPort() { - if (!_pcb) { - return 0; - } - return _pcb->local_port; -} - -IPAddress AsyncClient::remoteIP() { -#if ESP_IDF_VERSION_MAJOR < 5 - return IPAddress(getRemoteAddress()); -#else - if (!_pcb) { - return IPAddress(); - } - IPAddress ip; - ip.from_ip_addr_t(&(_pcb->remote_ip)); - return ip; -#endif -} - -uint16_t AsyncClient::remotePort() { - return getRemotePort(); -} - -IPAddress AsyncClient::localIP() { -#if ESP_IDF_VERSION_MAJOR < 5 - return IPAddress(getLocalAddress()); -#else - if (!_pcb) { - return IPAddress(); - } - IPAddress ip; - ip.from_ip_addr_t(&(_pcb->local_ip)); - return ip; -#endif -} - -uint16_t AsyncClient::localPort() { - return getLocalPort(); -} - -uint8_t AsyncClient::state() { - if (!_pcb) { - return 0; - } - return _pcb->state; -} - -bool AsyncClient::connected() { - if (!_pcb) { - return false; - } - return _pcb->state == ESTABLISHED; -} - -bool AsyncClient::connecting() { - if (!_pcb) { - return false; - } - return _pcb->state > CLOSED && _pcb->state < ESTABLISHED; -} - -bool AsyncClient::disconnecting() { - if (!_pcb) { - return false; - } - return _pcb->state > ESTABLISHED && _pcb->state < TIME_WAIT; -} - -bool AsyncClient::disconnected() { - if (!_pcb) { - return true; - } - return _pcb->state == CLOSED || _pcb->state == TIME_WAIT; -} - -bool AsyncClient::freeable() { - if (!_pcb) { - return true; - } - return _pcb->state == CLOSED || _pcb->state > ESTABLISHED; -} - -bool AsyncClient::canSend() { - return space() > 0; -} - -const char* AsyncClient::errorToString(int8_t error) { - switch (error) { - case ERR_OK: - return "OK"; - case ERR_MEM: - return "Out of memory error"; - case ERR_BUF: - return "Buffer error"; - case ERR_TIMEOUT: - return "Timeout"; - case ERR_RTE: - return "Routing problem"; - case ERR_INPROGRESS: - return "Operation in progress"; - case ERR_VAL: - return "Illegal value"; - case ERR_WOULDBLOCK: - return "Operation would block"; - case ERR_USE: - return "Address in use"; - case ERR_ALREADY: - return "Already connected"; - case ERR_CONN: - return "Not connected"; - case ERR_IF: - return "Low-level netif error"; - case ERR_ABRT: - return "Connection aborted"; - case ERR_RST: - return "Connection reset"; - case ERR_CLSD: - return "Connection closed"; - case ERR_ARG: - return "Illegal argument"; - case -55: - return "DNS failed"; - default: - return "UNKNOWN"; - } -} - -const char* AsyncClient::stateToString() { - switch (state()) { - case 0: - return "Closed"; - case 1: - return "Listen"; - case 2: - return "SYN Sent"; - case 3: - return "SYN Received"; - case 4: - return "Established"; - case 5: - return "FIN Wait 1"; - case 6: - return "FIN Wait 2"; - case 7: - return "Close Wait"; - case 8: - return "Closing"; - case 9: - return "Last ACK"; - case 10: - return "Time Wait"; - default: - return "UNKNOWN"; - } -} - -/* - * Static Callbacks (LwIP C2C++ interconnect) - * */ - -void AsyncClient::_s_dns_found(const char* name, struct ip_addr* ipaddr, void* arg) { - reinterpret_cast(arg)->_dns_found(ipaddr); -} - -int8_t AsyncClient::_s_poll(void* arg, struct tcp_pcb* pcb) { - return reinterpret_cast(arg)->_poll(pcb); -} - -int8_t AsyncClient::_s_recv(void* arg, struct tcp_pcb* pcb, struct pbuf* pb, int8_t err) { - return reinterpret_cast(arg)->_recv(pcb, pb, err); -} - -int8_t AsyncClient::_s_fin(void* arg, struct tcp_pcb* pcb, int8_t err) { - return reinterpret_cast(arg)->_fin(pcb, err); -} - -int8_t AsyncClient::_s_lwip_fin(void* arg, struct tcp_pcb* pcb, int8_t err) { - return reinterpret_cast(arg)->_lwip_fin(pcb, err); -} - -int8_t AsyncClient::_s_sent(void* arg, struct tcp_pcb* pcb, uint16_t len) { - return reinterpret_cast(arg)->_sent(pcb, len); -} - -void AsyncClient::_s_error(void* arg, int8_t err) { - reinterpret_cast(arg)->_error(err); -} - -int8_t AsyncClient::_s_connected(void* arg, struct tcp_pcb* pcb, int8_t err) { - return reinterpret_cast(arg)->_connected(pcb, err); -} - -/* - Async TCP Server - */ - -AsyncServer::AsyncServer(IPAddress addr, uint16_t port) - : _port(port) -#if ESP_IDF_VERSION_MAJOR < 5 - , - _bind4(true), _bind6(false) -#else - , - _bind4(addr.type() != IPType::IPv6), _bind6(addr.type() == IPType::IPv6) -#endif - , - _addr(addr), _noDelay(false), _pcb(0), _connect_cb(0), _connect_cb_arg(0) { -} - -#if ESP_IDF_VERSION_MAJOR < 5 -AsyncServer::AsyncServer(IPv6Address addr, uint16_t port) - : _port(port), _bind4(false), _bind6(true), _addr6(addr), _noDelay(false), _pcb(0), _connect_cb(0), _connect_cb_arg(0) {} -#endif - -AsyncServer::AsyncServer(uint16_t port) - : _port(port), _bind4(true), _bind6(false), _addr((uint32_t)IPADDR_ANY) -#if ESP_IDF_VERSION_MAJOR < 5 - , - _addr6() -#endif - , - _noDelay(false), _pcb(0), _connect_cb(0), _connect_cb_arg(0) { -} - -AsyncServer::~AsyncServer() { - end(); -} - -void AsyncServer::onClient(AcConnectHandler cb, void* arg) { - _connect_cb = cb; - _connect_cb_arg = arg; -} - -void AsyncServer::begin() { - if (_pcb) { - return; - } - - if (!_start_async_task()) { - log_e("failed to start task"); - return; - } - int8_t err; - TCP_MUTEX_LOCK(); - _pcb = tcp_new_ip_type(_bind4 && _bind6 ? IPADDR_TYPE_ANY : (_bind6 ? IPADDR_TYPE_V6 : IPADDR_TYPE_V4)); - TCP_MUTEX_UNLOCK(); - if (!_pcb) { - log_e("_pcb == NULL"); - return; - } - - ip_addr_t local_addr; -#if ESP_IDF_VERSION_MAJOR < 5 - if (_bind6) { // _bind6 && _bind4 both at the same time is not supported on Arduino 2 in this lib API - local_addr.type = IPADDR_TYPE_V6; - memcpy(local_addr.u_addr.ip6.addr, static_cast(_addr6), sizeof(uint32_t) * 4); - } else { - local_addr.type = IPADDR_TYPE_V4; - local_addr.u_addr.ip4.addr = _addr; - } -#else - _addr.to_ip_addr_t(&local_addr); -#endif - err = _tcp_bind(_pcb, &local_addr, _port); - - if (err != ERR_OK) { - _tcp_close(_pcb, -1); - log_e("bind error: %d", err); - return; - } - - static uint8_t backlog = 5; - _pcb = _tcp_listen_with_backlog(_pcb, backlog); - if (!_pcb) { - log_e("listen_pcb == NULL"); - return; - } - TCP_MUTEX_LOCK(); - tcp_arg(_pcb, (void*)this); - tcp_accept(_pcb, &_s_accept); - TCP_MUTEX_UNLOCK(); -} - -void AsyncServer::end() { - if (_pcb) { - TCP_MUTEX_LOCK(); - tcp_arg(_pcb, NULL); - tcp_accept(_pcb, NULL); - if (tcp_close(_pcb) != ERR_OK) { - TCP_MUTEX_UNLOCK(); - _tcp_abort(_pcb, -1); - } else { - TCP_MUTEX_UNLOCK(); - } - _pcb = NULL; - } -} - -// runs on LwIP thread -int8_t AsyncServer::_accept(tcp_pcb* pcb, int8_t err) { - // ets_printf("+A: 0x%08x\n", pcb); - if (_connect_cb) { - AsyncClient* c = new AsyncClient(pcb); - if (c) { - c->setNoDelay(_noDelay); - return _tcp_accept(this, c); - } - } - if (tcp_close(pcb) != ERR_OK) { - tcp_abort(pcb); - } - log_d("FAIL"); - return ERR_OK; -} - -int8_t AsyncServer::_accepted(AsyncClient* client) { - if (_connect_cb) { - _connect_cb(_connect_cb_arg, client); - } - return ERR_OK; -} - -void AsyncServer::setNoDelay(bool nodelay) { - _noDelay = nodelay; -} - -bool AsyncServer::getNoDelay() { - return _noDelay; -} - -uint8_t AsyncServer::status() { - if (!_pcb) { - return 0; - } - return _pcb->state; -} - -int8_t AsyncServer::_s_accept(void* arg, tcp_pcb* pcb, int8_t err) { - return reinterpret_cast(arg)->_accept(pcb, err); -} - -int8_t AsyncServer::_s_accepted(void* arg, AsyncClient* client) { - return reinterpret_cast(arg)->_accepted(client); -} diff --git a/Software/src/lib/mathieucarbou-AsyncTCP/src/AsyncTCP.h b/Software/src/lib/mathieucarbou-AsyncTCP/src/AsyncTCP.h deleted file mode 100644 index c909d051..00000000 --- a/Software/src/lib/mathieucarbou-AsyncTCP/src/AsyncTCP.h +++ /dev/null @@ -1,347 +0,0 @@ -/* - Asynchronous TCP library for Espressif MCUs - - Copyright (c) 2016 Hristo Gochkov. All rights reserved. - This file is part of the esp8266 core for Arduino environment. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#ifndef ASYNCTCP_H_ -#define ASYNCTCP_H_ - -#define ASYNCTCP_VERSION "3.3.1" -#define ASYNCTCP_VERSION_MAJOR 3 -#define ASYNCTCP_VERSION_MINOR 3 -#define ASYNCTCP_VERSION_REVISION 1 -#define ASYNCTCP_FORK_mathieucarbou - -#include "../../../devboard/hal/hal.h" -#include "../../../system_settings.h" - -#include "IPAddress.h" -#if ESP_IDF_VERSION_MAJOR < 5 - #include "IPv6Address.h" -#endif -#include "lwip/ip6_addr.h" -#include "lwip/ip_addr.h" -#include - -#ifndef LIBRETINY - #include "sdkconfig.h" -extern "C" { - #include "freertos/semphr.h" - #include "lwip/pbuf.h" -} -#else -extern "C" { - #include - #include -} - #define CONFIG_ASYNC_TCP_RUNNING_CORE WIFI_CORE -#endif - -// If core is not defined, then we are running in Arduino or PIO -#ifndef CONFIG_ASYNC_TCP_RUNNING_CORE - #define CONFIG_ASYNC_TCP_RUNNING_CORE WIFI_CORE -#endif - -// guard AsyncTCP task with watchdog -#ifndef CONFIG_ASYNC_TCP_USE_WDT - #define CONFIG_ASYNC_TCP_USE_WDT 0 -#endif - -#ifndef CONFIG_ASYNC_TCP_STACK_SIZE - #define CONFIG_ASYNC_TCP_STACK_SIZE 8192 * 2 -#endif - -#ifndef CONFIG_ASYNC_TCP_PRIORITY - #define CONFIG_ASYNC_TCP_PRIORITY 10 -#endif - -#ifndef CONFIG_ASYNC_TCP_QUEUE_SIZE - #define CONFIG_ASYNC_TCP_QUEUE_SIZE 64 -#endif - -#ifndef CONFIG_ASYNC_TCP_MAX_ACK_TIME - #define CONFIG_ASYNC_TCP_MAX_ACK_TIME 5000 -#endif - -class AsyncClient; - -#define ASYNC_WRITE_FLAG_COPY 0x01 // will allocate new buffer to hold the data while sending (else will hold reference to the data given) -#define ASYNC_WRITE_FLAG_MORE 0x02 // will not send PSH flag, meaning that there should be more data to be sent before the application should react. - -typedef std::function AcConnectHandler; -typedef std::function AcAckHandler; -typedef std::function AcErrorHandler; -typedef std::function AcDataHandler; -typedef std::function AcPacketHandler; -typedef std::function AcTimeoutHandler; - -struct tcp_pcb; -struct ip_addr; - -class AsyncClient { - public: - AsyncClient(tcp_pcb* pcb = 0); - ~AsyncClient(); - - AsyncClient& operator=(const AsyncClient& other); - AsyncClient& operator+=(const AsyncClient& other); - - bool operator==(const AsyncClient& other); - - bool operator!=(const AsyncClient& other) { - return !(*this == other); - } - bool connect(const IPAddress& ip, uint16_t port); -#if ESP_IDF_VERSION_MAJOR < 5 - bool connect(const IPv6Address& ip, uint16_t port); -#endif - bool connect(const char* host, uint16_t port); - /** - * @brief close connection - * - * @param now - ignored - */ - void close(bool now = false); - // same as close() - void stop() { close(false); }; - int8_t abort(); - bool free(); - - // ack is not pending - bool canSend(); - // TCP buffer space available - size_t space(); - - /** - * @brief add data to be send (but do not send yet) - * @note add() would call lwip's tcp_write() - By default apiflags=ASYNC_WRITE_FLAG_COPY - You could try to use apiflags with this flag unset to pass data by reference and avoid copy to socket buffer, - but looks like it does not work for Arduino's lwip in ESP32/IDF at least - it is enforced in https://github.com/espressif/esp-lwip/blob/0606eed9d8b98a797514fdf6eabb4daf1c8c8cd9/src/core/tcp_out.c#L422C5-L422C30 - if LWIP_NETIF_TX_SINGLE_PBUF is set, and it is set indeed in IDF - https://github.com/espressif/esp-idf/blob/a0f798cfc4bbd624aab52b2c194d219e242d80c1/components/lwip/port/include/lwipopts.h#L744 - * - * @param data - * @param size - * @param apiflags - * @return size_t amount of data that has been copied - */ - size_t add(const char* data, size_t size, uint8_t apiflags = ASYNC_WRITE_FLAG_COPY); - - /** - * @brief send data previously add()'ed - * - * @return true on success - * @return false on error - */ - bool send(); - - /** - * @brief add and enqueue data for sending - * @note it is same as add() + send() - * @note only make sense when canSend() == true - * - * @param data - * @param size - * @param apiflags - * @return size_t - */ - size_t write(const char* data, size_t size, uint8_t apiflags = ASYNC_WRITE_FLAG_COPY); - - /** - * @brief add and enque data for sending - * @note treats data as null-terminated string - * - * @param data - * @return size_t - */ - size_t write(const char* data) { return data == NULL ? 0 : write(data, strlen(data)); }; - - uint8_t state(); - bool connecting(); - bool connected(); - bool disconnecting(); - bool disconnected(); - - // disconnected or disconnecting - bool freeable(); - - uint16_t getMss(); - - uint32_t getRxTimeout(); - // no RX data timeout for the connection in seconds - void setRxTimeout(uint32_t timeout); - - uint32_t getAckTimeout(); - // no ACK timeout for the last sent packet in milliseconds - void setAckTimeout(uint32_t timeout); - - void setNoDelay(bool nodelay); - bool getNoDelay(); - - void setKeepAlive(uint32_t ms, uint8_t cnt); - - uint32_t getRemoteAddress(); - uint16_t getRemotePort(); - uint32_t getLocalAddress(); - uint16_t getLocalPort(); -#if LWIP_IPV6 - ip6_addr_t getRemoteAddress6(); - ip6_addr_t getLocalAddress6(); - #if ESP_IDF_VERSION_MAJOR < 5 - IPv6Address remoteIP6(); - IPv6Address localIP6(); - #else - IPAddress remoteIP6(); - IPAddress localIP6(); - #endif -#endif - - // compatibility - IPAddress remoteIP(); - uint16_t remotePort(); - IPAddress localIP(); - uint16_t localPort(); - - // set callback - on successful connect - void onConnect(AcConnectHandler cb, void* arg = 0); - // set callback - disconnected - void onDisconnect(AcConnectHandler cb, void* arg = 0); - // set callback - ack received - void onAck(AcAckHandler cb, void* arg = 0); - // set callback - unsuccessful connect or error - void onError(AcErrorHandler cb, void* arg = 0); - // set callback - data received (called if onPacket is not used) - void onData(AcDataHandler cb, void* arg = 0); - // set callback - data received - void onPacket(AcPacketHandler cb, void* arg = 0); - // set callback - ack timeout - void onTimeout(AcTimeoutHandler cb, void* arg = 0); - // set callback - every 125ms when connected - void onPoll(AcConnectHandler cb, void* arg = 0); - - // ack pbuf from onPacket - void ackPacket(struct pbuf* pb); - // ack data that you have not acked using the method below - size_t ack(size_t len); - // will not ack the current packet. Call from onData - void ackLater() { _ack_pcb = false; } - - static const char* errorToString(int8_t error); - const char* stateToString(); - - // internal callbacks - Do NOT call any of the functions below in user code! - static int8_t _s_poll(void* arg, struct tcp_pcb* tpcb); - static int8_t _s_recv(void* arg, struct tcp_pcb* tpcb, struct pbuf* pb, int8_t err); - static int8_t _s_fin(void* arg, struct tcp_pcb* tpcb, int8_t err); - static int8_t _s_lwip_fin(void* arg, struct tcp_pcb* tpcb, int8_t err); - static void _s_error(void* arg, int8_t err); - static int8_t _s_sent(void* arg, struct tcp_pcb* tpcb, uint16_t len); - static int8_t _s_connected(void* arg, struct tcp_pcb* tpcb, int8_t err); - static void _s_dns_found(const char* name, struct ip_addr* ipaddr, void* arg); - - int8_t _recv(tcp_pcb* pcb, pbuf* pb, int8_t err); - tcp_pcb* pcb() { return _pcb; } - - protected: - bool _connect(ip_addr_t addr, uint16_t port); - - tcp_pcb* _pcb; - int8_t _closed_slot; - - AcConnectHandler _connect_cb; - void* _connect_cb_arg; - AcConnectHandler _discard_cb; - void* _discard_cb_arg; - AcAckHandler _sent_cb; - void* _sent_cb_arg; - AcErrorHandler _error_cb; - void* _error_cb_arg; - AcDataHandler _recv_cb; - void* _recv_cb_arg; - AcPacketHandler _pb_cb; - void* _pb_cb_arg; - AcTimeoutHandler _timeout_cb; - void* _timeout_cb_arg; - AcConnectHandler _poll_cb; - void* _poll_cb_arg; - - bool _ack_pcb; - uint32_t _tx_last_packet; - uint32_t _rx_ack_len; - uint32_t _rx_last_packet; - uint32_t _rx_timeout; - uint32_t _rx_last_ack; - uint32_t _ack_timeout; - uint16_t _connect_port; - - int8_t _close(); - void _free_closed_slot(); - bool _allocate_closed_slot(); - int8_t _connected(tcp_pcb* pcb, int8_t err); - void _error(int8_t err); - int8_t _poll(tcp_pcb* pcb); - int8_t _sent(tcp_pcb* pcb, uint16_t len); - int8_t _fin(tcp_pcb* pcb, int8_t err); - int8_t _lwip_fin(tcp_pcb* pcb, int8_t err); - void _dns_found(struct ip_addr* ipaddr); - - public: - AsyncClient* prev; - AsyncClient* next; -}; - -class AsyncServer { - public: - AsyncServer(IPAddress addr, uint16_t port); -#if ESP_IDF_VERSION_MAJOR < 5 - AsyncServer(IPv6Address addr, uint16_t port); -#endif - AsyncServer(uint16_t port); - ~AsyncServer(); - void onClient(AcConnectHandler cb, void* arg); - void begin(); - void end(); - void setNoDelay(bool nodelay); - bool getNoDelay(); - uint8_t status(); - - // Do not use any of the functions below! - static int8_t _s_accept(void* arg, tcp_pcb* newpcb, int8_t err); - static int8_t _s_accepted(void* arg, AsyncClient* client); - - protected: - uint16_t _port; - bool _bind4 = false; - bool _bind6 = false; - IPAddress _addr; -#if ESP_IDF_VERSION_MAJOR < 5 - IPv6Address _addr6; -#endif - bool _noDelay; - tcp_pcb* _pcb; - AcConnectHandler _connect_cb; - void* _connect_cb_arg; - - int8_t _accept(tcp_pcb* newpcb, int8_t err); - int8_t _accepted(AsyncClient* client); -}; - -#endif /* ASYNCTCP_H_ */ diff --git a/Software/src/lib/me-no-dev-AsyncTCP/.gitignore b/Software/src/lib/me-no-dev-AsyncTCP/.gitignore new file mode 100644 index 00000000..9bea4330 --- /dev/null +++ b/Software/src/lib/me-no-dev-AsyncTCP/.gitignore @@ -0,0 +1,2 @@ + +.DS_Store diff --git a/Software/src/lib/me-no-dev-AsyncTCP/.travis.yml b/Software/src/lib/me-no-dev-AsyncTCP/.travis.yml new file mode 100644 index 00000000..dbfc064a --- /dev/null +++ b/Software/src/lib/me-no-dev-AsyncTCP/.travis.yml @@ -0,0 +1,34 @@ +sudo: false +language: python +os: + - linux + +git: + depth: false + +stages: + - build + +jobs: + include: + + - name: "Arduino Build" + if: tag IS blank AND (type = pull_request OR (type = push AND branch = master)) + stage: build + script: bash $TRAVIS_BUILD_DIR/.github/scripts/on-push.sh + + - name: "PlatformIO Build" + if: tag IS blank AND (type = pull_request OR (type = push AND branch = master)) + stage: build + script: bash $TRAVIS_BUILD_DIR/.github/scripts/on-push.sh 1 1 + +notifications: + email: + on_success: change + on_failure: change + webhooks: + urls: + - https://webhooks.gitter.im/e/60e65d0c78ea0a920347 + on_success: change # options: [always|never|change] default: always + on_failure: always # options: [always|never|change] default: always + on_start: false # default: false diff --git a/Software/src/lib/mathieucarbou-AsyncTCP/CMakeLists.txt b/Software/src/lib/me-no-dev-AsyncTCP/CMakeLists.txt similarity index 100% rename from Software/src/lib/mathieucarbou-AsyncTCP/CMakeLists.txt rename to Software/src/lib/me-no-dev-AsyncTCP/CMakeLists.txt diff --git a/Software/src/lib/me-no-dev-AsyncTCP/Kconfig.projbuild b/Software/src/lib/me-no-dev-AsyncTCP/Kconfig.projbuild new file mode 100644 index 00000000..17749264 --- /dev/null +++ b/Software/src/lib/me-no-dev-AsyncTCP/Kconfig.projbuild @@ -0,0 +1,30 @@ +menu "AsyncTCP Configuration" + +choice ASYNC_TCP_RUNNING_CORE + bool "Core on which AsyncTCP's thread is running" + default ASYNC_TCP_RUN_CORE1 + help + Select on which core AsyncTCP is running + + config ASYNC_TCP_RUN_CORE0 + bool "CORE 0" + config ASYNC_TCP_RUN_CORE1 + bool "CORE 1" + config ASYNC_TCP_RUN_NO_AFFINITY + bool "BOTH" + +endchoice + +config ASYNC_TCP_RUNNING_CORE + int + default 0 if ASYNC_TCP_RUN_CORE0 + default 1 if ASYNC_TCP_RUN_CORE1 + default -1 if ASYNC_TCP_RUN_NO_AFFINITY + +config ASYNC_TCP_USE_WDT + bool "Enable WDT for the AsyncTCP task" + default "y" + help + Enable WDT for the AsyncTCP task, so it will trigger if a handler is locking the thread. + +endmenu diff --git a/Software/src/lib/mathieucarbou-AsyncTCP/LICENSE b/Software/src/lib/me-no-dev-AsyncTCP/LICENSE similarity index 100% rename from Software/src/lib/mathieucarbou-AsyncTCP/LICENSE rename to Software/src/lib/me-no-dev-AsyncTCP/LICENSE diff --git a/Software/src/lib/me-no-dev-AsyncTCP/README.md b/Software/src/lib/me-no-dev-AsyncTCP/README.md new file mode 100644 index 00000000..79ffa9ef --- /dev/null +++ b/Software/src/lib/me-no-dev-AsyncTCP/README.md @@ -0,0 +1,15 @@ +This is commit ca8ac5f from https://github.com/me-no-dev/AsyncTCP + +# AsyncTCP +[![Build Status](https://travis-ci.org/me-no-dev/AsyncTCP.svg?branch=master)](https://travis-ci.org/me-no-dev/AsyncTCP) ![](https://github.com/me-no-dev/AsyncTCP/workflows/Async%20TCP%20CI/badge.svg) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/2f7e4d1df8b446d192cbfec6dc174d2d)](https://www.codacy.com/manual/me-no-dev/AsyncTCP?utm_source=github.com&utm_medium=referral&utm_content=me-no-dev/AsyncTCP&utm_campaign=Badge_Grade) + +### Async TCP Library for ESP32 Arduino + +[![Join the chat at https://gitter.im/me-no-dev/ESPAsyncWebServer](https://badges.gitter.im/me-no-dev/ESPAsyncWebServer.svg)](https://gitter.im/me-no-dev/ESPAsyncWebServer?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + +This is a fully asynchronous TCP library, aimed at enabling trouble-free, multi-connection network environment for Espressif's ESP32 MCUs. + +This library is the base for [ESPAsyncWebServer](https://github.com/me-no-dev/ESPAsyncWebServer) + +## AsyncClient and AsyncServer +The base classes on which everything else is built. They expose all possible scenarios, but are really raw and require more skills to use. diff --git a/Software/src/lib/mathieucarbou-AsyncTCP/component.mk b/Software/src/lib/me-no-dev-AsyncTCP/component.mk similarity index 100% rename from Software/src/lib/mathieucarbou-AsyncTCP/component.mk rename to Software/src/lib/me-no-dev-AsyncTCP/component.mk diff --git a/Software/src/lib/me-no-dev-AsyncTCP/library.json b/Software/src/lib/me-no-dev-AsyncTCP/library.json new file mode 100644 index 00000000..89f90e4e --- /dev/null +++ b/Software/src/lib/me-no-dev-AsyncTCP/library.json @@ -0,0 +1,22 @@ +{ + "name":"AsyncTCP", + "description":"Asynchronous TCP Library for ESP32", + "keywords":"async,tcp", + "authors": + { + "name": "Hristo Gochkov", + "maintainer": true + }, + "repository": + { + "type": "git", + "url": "https://github.com/me-no-dev/AsyncTCP.git" + }, + "version": "1.1.1", + "license": "LGPL-3.0", + "frameworks": "arduino", + "platforms": "espressif32", + "build": { + "libCompatMode": 2 + } +} diff --git a/Software/src/lib/me-no-dev-AsyncTCP/library.properties b/Software/src/lib/me-no-dev-AsyncTCP/library.properties new file mode 100644 index 00000000..eb4e26e9 --- /dev/null +++ b/Software/src/lib/me-no-dev-AsyncTCP/library.properties @@ -0,0 +1,9 @@ +name=AsyncTCP +version=1.1.1 +author=Me-No-Dev +maintainer=Me-No-Dev +sentence=Async TCP Library for ESP32 +paragraph=Async TCP Library for ESP32 +category=Other +url=https://github.com/me-no-dev/AsyncTCP +architectures=* diff --git a/Software/src/lib/me-no-dev-AsyncTCP/src/AsyncTCP.cpp b/Software/src/lib/me-no-dev-AsyncTCP/src/AsyncTCP.cpp new file mode 100644 index 00000000..acd89639 --- /dev/null +++ b/Software/src/lib/me-no-dev-AsyncTCP/src/AsyncTCP.cpp @@ -0,0 +1,1387 @@ +/* + Asynchronous TCP library for Espressif MCUs + + Copyright (c) 2016 Hristo Gochkov. All rights reserved. + This file is part of the esp8266 core for Arduino environment. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "Arduino.h" + +#include "AsyncTCP.h" +extern "C"{ +#include "lwip/opt.h" +#include "lwip/tcp.h" +#include "lwip/inet.h" +#include "lwip/dns.h" +#include "lwip/err.h" +} +#include "esp_task_wdt.h" + +/* + * TCP/IP Event Task + * */ + +#define TAG "AsyncTCP" + +// https://github.com/espressif/arduino-esp32/issues/10526 +#ifdef CONFIG_LWIP_TCPIP_CORE_LOCKING +#define TCP_MUTEX_LOCK() \ + if (!sys_thread_tcpip(LWIP_CORE_LOCK_QUERY_HOLDER)) { \ + LOCK_TCPIP_CORE(); \ + } + +#define TCP_MUTEX_UNLOCK() \ + if (sys_thread_tcpip(LWIP_CORE_LOCK_QUERY_HOLDER)) { \ + UNLOCK_TCPIP_CORE(); \ + } +#else // CONFIG_LWIP_TCPIP_CORE_LOCKING +#define TCP_MUTEX_LOCK() +#define TCP_MUTEX_UNLOCK() +#endif // CONFIG_LWIP_TCPIP_CORE_LOCKING + +typedef enum { + LWIP_TCP_SENT, LWIP_TCP_RECV, LWIP_TCP_FIN, LWIP_TCP_ERROR, LWIP_TCP_POLL, LWIP_TCP_CLEAR, LWIP_TCP_ACCEPT, LWIP_TCP_CONNECTED, LWIP_TCP_DNS +} lwip_event_t; + +typedef struct { + lwip_event_t event; + void *arg; + union { + struct { + void * pcb; + int8_t err; + } connected; + struct { + int8_t err; + } error; + struct { + tcp_pcb * pcb; + uint16_t len; + } sent; + struct { + tcp_pcb * pcb; + pbuf * pb; + int8_t err; + } recv; + struct { + tcp_pcb * pcb; + int8_t err; + } fin; + struct { + tcp_pcb * pcb; + } poll; + struct { + AsyncClient * client; + } accept; + struct { + const char * name; + ip_addr_t addr; + } dns; + }; +} lwip_event_packet_t; + +static xQueueHandle _async_queue; +static TaskHandle_t _async_service_task_handle = NULL; + + +SemaphoreHandle_t _slots_lock; +const int _number_of_closed_slots = CONFIG_LWIP_MAX_ACTIVE_TCP; +static uint32_t _closed_slots[_number_of_closed_slots]; +static uint32_t _closed_index = []() { + _slots_lock = xSemaphoreCreateBinary(); + xSemaphoreGive(_slots_lock); + for (int i = 0; i < _number_of_closed_slots; ++ i) { + _closed_slots[i] = 1; + } + return 1; +}(); + + +static inline bool _init_async_event_queue(){ + if(!_async_queue){ + _async_queue = xQueueCreate(32, sizeof(lwip_event_packet_t *)); + if(!_async_queue){ + return false; + } + } + return true; +} + +static inline bool _send_async_event(lwip_event_packet_t ** e){ + return _async_queue && xQueueSend(_async_queue, e, portMAX_DELAY) == pdPASS; +} + +static inline bool _prepend_async_event(lwip_event_packet_t ** e){ + return _async_queue && xQueueSendToFront(_async_queue, e, portMAX_DELAY) == pdPASS; +} + +static inline bool _get_async_event(lwip_event_packet_t ** e){ + return _async_queue && xQueueReceive(_async_queue, e, portMAX_DELAY) == pdPASS; +} + +static bool _remove_events_with_arg(void * arg){ + lwip_event_packet_t * first_packet = NULL; + lwip_event_packet_t * packet = NULL; + + if(!_async_queue){ + return false; + } + //figure out which is the first packet so we can keep the order + while(!first_packet){ + if(xQueueReceive(_async_queue, &first_packet, 0) != pdPASS){ + return false; + } + //discard packet if matching + if((int)first_packet->arg == (int)arg){ + free(first_packet); + first_packet = NULL; + //return first packet to the back of the queue + } else if(xQueueSend(_async_queue, &first_packet, portMAX_DELAY) != pdPASS){ + return false; + } + } + + while(xQueuePeek(_async_queue, &packet, 0) == pdPASS && packet != first_packet){ + if(xQueueReceive(_async_queue, &packet, 0) != pdPASS){ + return false; + } + if((int)packet->arg == (int)arg){ + free(packet); + packet = NULL; + } else if(xQueueSend(_async_queue, &packet, portMAX_DELAY) != pdPASS){ + return false; + } + } + return true; +} + +static void _handle_async_event(lwip_event_packet_t * e){ + if(e->arg == NULL){ + // do nothing when arg is NULL + //ets_printf("event arg == NULL: 0x%08x\n", e->recv.pcb); + } else if(e->event == LWIP_TCP_CLEAR){ + _remove_events_with_arg(e->arg); + } else if(e->event == LWIP_TCP_RECV){ + //ets_printf("-R: 0x%08x\n", e->recv.pcb); + AsyncClient::_s_recv(e->arg, e->recv.pcb, e->recv.pb, e->recv.err); + } else if(e->event == LWIP_TCP_FIN){ + //ets_printf("-F: 0x%08x\n", e->fin.pcb); + AsyncClient::_s_fin(e->arg, e->fin.pcb, e->fin.err); + } else if(e->event == LWIP_TCP_SENT){ + //ets_printf("-S: 0x%08x\n", e->sent.pcb); + AsyncClient::_s_sent(e->arg, e->sent.pcb, e->sent.len); + } else if(e->event == LWIP_TCP_POLL){ + //ets_printf("-P: 0x%08x\n", e->poll.pcb); + AsyncClient::_s_poll(e->arg, e->poll.pcb); + } else if(e->event == LWIP_TCP_ERROR){ + //ets_printf("-E: 0x%08x %d\n", e->arg, e->error.err); + AsyncClient::_s_error(e->arg, e->error.err); + } else if(e->event == LWIP_TCP_CONNECTED){ + //ets_printf("C: 0x%08x 0x%08x %d\n", e->arg, e->connected.pcb, e->connected.err); + AsyncClient::_s_connected(e->arg, e->connected.pcb, e->connected.err); + } else if(e->event == LWIP_TCP_ACCEPT){ + //ets_printf("A: 0x%08x 0x%08x\n", e->arg, e->accept.client); + AsyncServer::_s_accepted(e->arg, e->accept.client); + } else if(e->event == LWIP_TCP_DNS){ + //ets_printf("D: 0x%08x %s = %s\n", e->arg, e->dns.name, ipaddr_ntoa(&e->dns.addr)); + AsyncClient::_s_dns_found(e->dns.name, &e->dns.addr, e->arg); + } + free((void*)(e)); +} + +static void _async_service_task(void *pvParameters){ + lwip_event_packet_t * packet = NULL; + for (;;) { + if(_get_async_event(&packet)){ +#if CONFIG_ASYNC_TCP_USE_WDT + if(esp_task_wdt_add(NULL) != ESP_OK){ + log_e("Failed to add async task to WDT"); + } +#endif + _handle_async_event(packet); +#if CONFIG_ASYNC_TCP_USE_WDT + if(esp_task_wdt_delete(NULL) != ESP_OK){ + log_e("Failed to remove loop task from WDT"); + } +#endif + } + } + vTaskDelete(NULL); + _async_service_task_handle = NULL; +} +/* +static void _stop_async_task(){ + if(_async_service_task_handle){ + vTaskDelete(_async_service_task_handle); + _async_service_task_handle = NULL; + } +} +*/ +static bool _start_async_task(){ + if(!_init_async_event_queue()){ + return false; + } + if(!_async_service_task_handle){ + xTaskCreateUniversal(_async_service_task, "async_tcp", 8192 * 2, NULL, TASK_CONNECTIVITY_PRIO, &_async_service_task_handle, CONFIG_ASYNC_TCP_RUNNING_CORE); + if(!_async_service_task_handle){ + return false; + } + } + return true; +} + +/* + * LwIP Callbacks + * */ + +static int8_t _tcp_clear_events(void * arg) { + lwip_event_packet_t * e = (lwip_event_packet_t *)malloc(sizeof(lwip_event_packet_t)); + e->event = LWIP_TCP_CLEAR; + e->arg = arg; + if (!_prepend_async_event(&e)) { + free((void*)(e)); + } + return ERR_OK; +} + +static int8_t _tcp_connected(void * arg, tcp_pcb * pcb, int8_t err) { + //ets_printf("+C: 0x%08x\n", pcb); + lwip_event_packet_t * e = (lwip_event_packet_t *)malloc(sizeof(lwip_event_packet_t)); + e->event = LWIP_TCP_CONNECTED; + e->arg = arg; + e->connected.pcb = pcb; + e->connected.err = err; + if (!_prepend_async_event(&e)) { + free((void*)(e)); + } + return ERR_OK; +} + +static int8_t _tcp_poll(void * arg, struct tcp_pcb * pcb) { + //ets_printf("+P: 0x%08x\n", pcb); + lwip_event_packet_t * e = (lwip_event_packet_t *)malloc(sizeof(lwip_event_packet_t)); + e->event = LWIP_TCP_POLL; + e->arg = arg; + e->poll.pcb = pcb; + if (!_send_async_event(&e)) { + free((void*)(e)); + } + return ERR_OK; +} + +static int8_t _tcp_recv(void * arg, struct tcp_pcb * pcb, struct pbuf *pb, int8_t err) { + lwip_event_packet_t * e = (lwip_event_packet_t *)malloc(sizeof(lwip_event_packet_t)); + e->arg = arg; + if(pb){ + //ets_printf("+R: 0x%08x\n", pcb); + e->event = LWIP_TCP_RECV; + e->recv.pcb = pcb; + e->recv.pb = pb; + e->recv.err = err; + } else { + //ets_printf("+F: 0x%08x\n", pcb); + e->event = LWIP_TCP_FIN; + e->fin.pcb = pcb; + e->fin.err = err; + //close the PCB in LwIP thread + AsyncClient::_s_lwip_fin(e->arg, e->fin.pcb, e->fin.err); + } + if (!_send_async_event(&e)) { + free((void*)(e)); + } + return ERR_OK; +} + +static int8_t _tcp_sent(void * arg, struct tcp_pcb * pcb, uint16_t len) { + //ets_printf("+S: 0x%08x\n", pcb); + lwip_event_packet_t * e = (lwip_event_packet_t *)malloc(sizeof(lwip_event_packet_t)); + e->event = LWIP_TCP_SENT; + e->arg = arg; + e->sent.pcb = pcb; + e->sent.len = len; + if (!_send_async_event(&e)) { + free((void*)(e)); + } + return ERR_OK; +} + +static void _tcp_error(void * arg, int8_t err) { + //ets_printf("+E: 0x%08x\n", arg); + lwip_event_packet_t * e = (lwip_event_packet_t *)malloc(sizeof(lwip_event_packet_t)); + e->event = LWIP_TCP_ERROR; + e->arg = arg; + e->error.err = err; + if (!_send_async_event(&e)) { + free((void*)(e)); + } +} + +static void _tcp_dns_found(const char * name, struct ip_addr * ipaddr, void * arg) { + lwip_event_packet_t * e = (lwip_event_packet_t *)malloc(sizeof(lwip_event_packet_t)); + //ets_printf("+DNS: name=%s ipaddr=0x%08x arg=%x\n", name, ipaddr, arg); + e->event = LWIP_TCP_DNS; + e->arg = arg; + e->dns.name = name; + if (ipaddr) { + memcpy(&e->dns.addr, ipaddr, sizeof(struct ip_addr)); + } else { + memset(&e->dns.addr, 0, sizeof(e->dns.addr)); + } + if (!_send_async_event(&e)) { + free((void*)(e)); + } +} + +//Used to switch out from LwIP thread +static int8_t _tcp_accept(void * arg, AsyncClient * client) { + lwip_event_packet_t * e = (lwip_event_packet_t *)malloc(sizeof(lwip_event_packet_t)); + e->event = LWIP_TCP_ACCEPT; + e->arg = arg; + e->accept.client = client; + if (!_prepend_async_event(&e)) { + free((void*)(e)); + } + return ERR_OK; +} + +/* + * TCP/IP API Calls + * */ + +#include "lwip/priv/tcpip_priv.h" + +typedef struct { + struct tcpip_api_call_data call; + tcp_pcb * pcb; + int8_t closed_slot; + int8_t err; + union { + struct { + const char* data; + size_t size; + uint8_t apiflags; + } write; + size_t received; + struct { + ip_addr_t * addr; + uint16_t port; + tcp_connected_fn cb; + } connect; + struct { + ip_addr_t * addr; + uint16_t port; + } bind; + uint8_t backlog; + }; +} tcp_api_call_t; + +static err_t _tcp_output_api(struct tcpip_api_call_data *api_call_msg){ + tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg; + msg->err = ERR_CONN; + if(msg->closed_slot == -1 || !_closed_slots[msg->closed_slot]) { + msg->err = tcp_output(msg->pcb); + } + return msg->err; +} + +static esp_err_t _tcp_output(tcp_pcb * pcb, int8_t closed_slot) { + if(!pcb){ + return ERR_CONN; + } + tcp_api_call_t msg; + msg.pcb = pcb; + msg.closed_slot = closed_slot; + tcpip_api_call(_tcp_output_api, (struct tcpip_api_call_data*)&msg); + return msg.err; +} + +static err_t _tcp_write_api(struct tcpip_api_call_data *api_call_msg){ + tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg; + msg->err = ERR_CONN; + if(msg->closed_slot == -1 || !_closed_slots[msg->closed_slot]) { + msg->err = tcp_write(msg->pcb, msg->write.data, msg->write.size, msg->write.apiflags); + } + return msg->err; +} + +static esp_err_t _tcp_write(tcp_pcb * pcb, int8_t closed_slot, const char* data, size_t size, uint8_t apiflags) { + if(!pcb){ + return ERR_CONN; + } + tcp_api_call_t msg; + msg.pcb = pcb; + msg.closed_slot = closed_slot; + msg.write.data = data; + msg.write.size = size; + msg.write.apiflags = apiflags; + tcpip_api_call(_tcp_write_api, (struct tcpip_api_call_data*)&msg); + return msg.err; +} + +static err_t _tcp_recved_api(struct tcpip_api_call_data *api_call_msg){ + tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg; + msg->err = ERR_CONN; + if(msg->closed_slot == -1 || !_closed_slots[msg->closed_slot]) { + msg->err = 0; + tcp_recved(msg->pcb, msg->received); + } + return msg->err; +} + +static esp_err_t _tcp_recved(tcp_pcb * pcb, int8_t closed_slot, size_t len) { + if(!pcb){ + return ERR_CONN; + } + tcp_api_call_t msg; + msg.pcb = pcb; + msg.closed_slot = closed_slot; + msg.received = len; + tcpip_api_call(_tcp_recved_api, (struct tcpip_api_call_data*)&msg); + return msg.err; +} + +static err_t _tcp_close_api(struct tcpip_api_call_data *api_call_msg){ + tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg; + msg->err = ERR_CONN; + if(msg->closed_slot == -1 || !_closed_slots[msg->closed_slot]) { + msg->err = tcp_close(msg->pcb); + } + return msg->err; +} + +static esp_err_t _tcp_close(tcp_pcb * pcb, int8_t closed_slot) { + if(!pcb){ + return ERR_CONN; + } + tcp_api_call_t msg; + msg.pcb = pcb; + msg.closed_slot = closed_slot; + tcpip_api_call(_tcp_close_api, (struct tcpip_api_call_data*)&msg); + return msg.err; +} + +static err_t _tcp_abort_api(struct tcpip_api_call_data *api_call_msg){ + tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg; + msg->err = ERR_CONN; + if(msg->closed_slot == -1 || !_closed_slots[msg->closed_slot]) { + tcp_abort(msg->pcb); + } + return msg->err; +} + +static esp_err_t _tcp_abort(tcp_pcb * pcb, int8_t closed_slot) { + if(!pcb){ + return ERR_CONN; + } + tcp_api_call_t msg; + msg.pcb = pcb; + msg.closed_slot = closed_slot; + tcpip_api_call(_tcp_abort_api, (struct tcpip_api_call_data*)&msg); + return msg.err; +} + +static err_t _tcp_connect_api(struct tcpip_api_call_data *api_call_msg){ + tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg; + msg->err = tcp_connect(msg->pcb, msg->connect.addr, msg->connect.port, msg->connect.cb); + return msg->err; +} + +static esp_err_t _tcp_connect(tcp_pcb * pcb, int8_t closed_slot, ip_addr_t * addr, uint16_t port, tcp_connected_fn cb) { + if(!pcb){ + return ESP_FAIL; + } + tcp_api_call_t msg; + msg.pcb = pcb; + msg.closed_slot = closed_slot; + msg.connect.addr = addr; + msg.connect.port = port; + msg.connect.cb = cb; + tcpip_api_call(_tcp_connect_api, (struct tcpip_api_call_data*)&msg); + return msg.err; +} + +static err_t _tcp_bind_api(struct tcpip_api_call_data *api_call_msg){ + tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg; + msg->err = tcp_bind(msg->pcb, msg->bind.addr, msg->bind.port); + return msg->err; +} + +static esp_err_t _tcp_bind(tcp_pcb * pcb, ip_addr_t * addr, uint16_t port) { + if(!pcb){ + return ESP_FAIL; + } + tcp_api_call_t msg; + msg.pcb = pcb; + msg.closed_slot = -1; + msg.bind.addr = addr; + msg.bind.port = port; + tcpip_api_call(_tcp_bind_api, (struct tcpip_api_call_data*)&msg); + return msg.err; +} + +static err_t _tcp_listen_api(struct tcpip_api_call_data *api_call_msg){ + tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg; + msg->err = 0; + msg->pcb = tcp_listen_with_backlog(msg->pcb, msg->backlog); + return msg->err; +} + +static tcp_pcb * _tcp_listen_with_backlog(tcp_pcb * pcb, uint8_t backlog) { + if(!pcb){ + return NULL; + } + tcp_api_call_t msg; + msg.pcb = pcb; + msg.closed_slot = -1; + msg.backlog = backlog?backlog:0xFF; + tcpip_api_call(_tcp_listen_api, (struct tcpip_api_call_data*)&msg); + return msg.pcb; +} + + + +/* + Async TCP Client + */ + +AsyncClient::AsyncClient(tcp_pcb* pcb) +: _connect_cb(0) +, _connect_cb_arg(0) +, _discard_cb(0) +, _discard_cb_arg(0) +, _sent_cb(0) +, _sent_cb_arg(0) +, _error_cb(0) +, _error_cb_arg(0) +, _recv_cb(0) +, _recv_cb_arg(0) +, _pb_cb(0) +, _pb_cb_arg(0) +, _timeout_cb(0) +, _timeout_cb_arg(0) +, _pcb_busy(false) +, _pcb_sent_at(0) +, _ack_pcb(true) +, _rx_last_packet(0) +, _rx_since_timeout(0) +, _ack_timeout(ASYNC_MAX_ACK_TIME) +, _connect_port(0) +, prev(NULL) +, next(NULL) +{ + _pcb = pcb; + _closed_slot = -1; + if(_pcb){ + _allocate_closed_slot(); + _rx_last_packet = millis(); + tcp_arg(_pcb, this); + tcp_recv(_pcb, &_tcp_recv); + tcp_sent(_pcb, &_tcp_sent); + tcp_err(_pcb, &_tcp_error); + tcp_poll(_pcb, &_tcp_poll, 1); + } +} + +AsyncClient::~AsyncClient(){ + if(_pcb) { + _close(); + } + _free_closed_slot(); +} + +/* + * Operators + * */ + +AsyncClient& AsyncClient::operator=(const AsyncClient& other){ + if (_pcb) { + _close(); + } + + _pcb = other._pcb; + _closed_slot = other._closed_slot; + if (_pcb) { + _rx_last_packet = millis(); + tcp_arg(_pcb, this); + tcp_recv(_pcb, &_tcp_recv); + tcp_sent(_pcb, &_tcp_sent); + tcp_err(_pcb, &_tcp_error); + tcp_poll(_pcb, &_tcp_poll, 1); + } + return *this; +} + +bool AsyncClient::operator==(const AsyncClient &other) { + return _pcb == other._pcb; +} + +AsyncClient & AsyncClient::operator+=(const AsyncClient &other) { + if(next == NULL){ + next = (AsyncClient*)(&other); + next->prev = this; + } else { + AsyncClient *c = next; + while(c->next != NULL) { + c = c->next; + } + c->next =(AsyncClient*)(&other); + c->next->prev = c; + } + return *this; +} + +/* + * Callback Setters + * */ + +void AsyncClient::onConnect(AcConnectHandler cb, void* arg){ + _connect_cb = cb; + _connect_cb_arg = arg; +} + +void AsyncClient::onDisconnect(AcConnectHandler cb, void* arg){ + _discard_cb = cb; + _discard_cb_arg = arg; +} + +void AsyncClient::onAck(AcAckHandler cb, void* arg){ + _sent_cb = cb; + _sent_cb_arg = arg; +} + +void AsyncClient::onError(AcErrorHandler cb, void* arg){ + _error_cb = cb; + _error_cb_arg = arg; +} + +void AsyncClient::onData(AcDataHandler cb, void* arg){ + _recv_cb = cb; + _recv_cb_arg = arg; +} + +void AsyncClient::onPacket(AcPacketHandler cb, void* arg){ + _pb_cb = cb; + _pb_cb_arg = arg; +} + +void AsyncClient::onTimeout(AcTimeoutHandler cb, void* arg){ + _timeout_cb = cb; + _timeout_cb_arg = arg; +} + +void AsyncClient::onPoll(AcConnectHandler cb, void* arg){ + _poll_cb = cb; + _poll_cb_arg = arg; +} + +/* + * Main Public Methods + * */ + +bool AsyncClient::connect(IPAddress ip, uint16_t port){ + if (_pcb){ + log_w("already connected, state %d", _pcb->state); + return false; + } + if(!_start_async_task()){ + log_e("failed to start task"); + return false; + } + + ip_addr_t addr; + addr.type = IPADDR_TYPE_V4; + addr.u_addr.ip4.addr = ip; + + TCP_MUTEX_LOCK(); + tcp_pcb* pcb = tcp_new_ip_type(IPADDR_TYPE_V4); + if (!pcb){ + TCP_MUTEX_UNLOCK(); + log_e("pcb == NULL"); + return false; + } + + tcp_arg(pcb, this); + tcp_err(pcb, &_tcp_error); + tcp_recv(pcb, &_tcp_recv); + tcp_sent(pcb, &_tcp_sent); + tcp_poll(pcb, &_tcp_poll, 1); + TCP_MUTEX_UNLOCK(); + //_tcp_connect(pcb, &addr, port,(tcp_connected_fn)&_s_connected); + _tcp_connect(pcb, _closed_slot, &addr, port,(tcp_connected_fn)&_tcp_connected); + return true; +} + +bool AsyncClient::connect(const char* host, uint16_t port){ + ip_addr_t addr; + + if(!_start_async_task()){ + log_e("failed to start task"); + return false; + } + TCP_MUTEX_LOCK(); + err_t err = dns_gethostbyname(host, &addr, (dns_found_callback)&_tcp_dns_found, this); + TCP_MUTEX_UNLOCK(); + if(err == ERR_OK) { + return connect(IPAddress(addr.u_addr.ip4.addr), port); + } else if(err == ERR_INPROGRESS) { + _connect_port = port; + return true; + } + log_e("error: %d", err); + return false; +} + +void AsyncClient::close(bool now){ + if(_pcb){ + _tcp_recved(_pcb, _closed_slot, _rx_ack_len); + } + _close(); +} + +int8_t AsyncClient::abort(){ + if(_pcb) { + _tcp_abort(_pcb, _closed_slot ); + _pcb = NULL; + } + return ERR_ABRT; +} + +size_t AsyncClient::space(){ + if((_pcb != NULL) && (_pcb->state == 4)){ + return tcp_sndbuf(_pcb); + } + return 0; +} + +size_t AsyncClient::add(const char* data, size_t size, uint8_t apiflags) { + if(!_pcb || size == 0 || data == NULL) { + return 0; + } + size_t room = space(); + if(!room) { + return 0; + } + size_t will_send = (room < size) ? room : size; + int8_t err = ERR_OK; + err = _tcp_write(_pcb, _closed_slot, data, will_send, apiflags); + if(err != ERR_OK) { + return 0; + } + return will_send; +} + +bool AsyncClient::send(){ + int8_t err = ERR_OK; + err = _tcp_output(_pcb, _closed_slot); + if(err == ERR_OK){ + _pcb_busy = true; + _pcb_sent_at = millis(); + return true; + } + return false; +} + +size_t AsyncClient::ack(size_t len){ + if(len > _rx_ack_len) + len = _rx_ack_len; + if(len){ + _tcp_recved(_pcb, _closed_slot, len); + } + _rx_ack_len -= len; + return len; +} + +void AsyncClient::ackPacket(struct pbuf * pb){ + if(!pb){ + return; + } + _tcp_recved(_pcb, _closed_slot, pb->len); + pbuf_free(pb); +} + +/* + * Main Private Methods + * */ + +int8_t AsyncClient::_close(){ + //ets_printf("X: 0x%08x\n", (uint32_t)this); + int8_t err = ERR_OK; + if(_pcb) { + //log_i(""); + TCP_MUTEX_LOCK(); + tcp_arg(_pcb, NULL); + tcp_sent(_pcb, NULL); + tcp_recv(_pcb, NULL); + tcp_err(_pcb, NULL); + tcp_poll(_pcb, NULL, 0); + TCP_MUTEX_UNLOCK(); + _tcp_clear_events(this); + err = _tcp_close(_pcb, _closed_slot); + if(err != ERR_OK) { + err = abort(); + } + _pcb = NULL; + if(_discard_cb) { + _discard_cb(_discard_cb_arg, this); + } + } + return err; +} + +void AsyncClient::_allocate_closed_slot(){ + xSemaphoreTake(_slots_lock, portMAX_DELAY); + uint32_t closed_slot_min_index = 0; + for (int i = 0; i < _number_of_closed_slots; ++ i) { + if ((_closed_slot == -1 || _closed_slots[i] <= closed_slot_min_index) && _closed_slots[i] != 0) { + closed_slot_min_index = _closed_slots[i]; + _closed_slot = i; + } + } + if (_closed_slot != -1) { + _closed_slots[_closed_slot] = 0; + } + xSemaphoreGive(_slots_lock); +} + +void AsyncClient::_free_closed_slot(){ + if (_closed_slot != -1) { + _closed_slots[_closed_slot] = _closed_index; + _closed_slot = -1; + ++ _closed_index; + } +} + +/* + * Private Callbacks + * */ + +int8_t AsyncClient::_connected(void* pcb, int8_t err){ + _pcb = reinterpret_cast(pcb); + if(_pcb){ + _rx_last_packet = millis(); + _pcb_busy = false; +// tcp_recv(_pcb, &_tcp_recv); +// tcp_sent(_pcb, &_tcp_sent); +// tcp_poll(_pcb, &_tcp_poll, 1); + } + if(_connect_cb) { + _connect_cb(_connect_cb_arg, this); + } + return ERR_OK; +} + +void AsyncClient::_error(int8_t err) { + if(_pcb){ + tcp_arg(_pcb, NULL); + if(_pcb->state == LISTEN) { + tcp_sent(_pcb, NULL); + tcp_recv(_pcb, NULL); + tcp_err(_pcb, NULL); + tcp_poll(_pcb, NULL, 0); + } + _pcb = NULL; + } + if(_error_cb) { + _error_cb(_error_cb_arg, this, err); + } + if(_discard_cb) { + _discard_cb(_discard_cb_arg, this); + } +} + +//In LwIP Thread +int8_t AsyncClient::_lwip_fin(tcp_pcb* pcb, int8_t err) { + if(!_pcb || pcb != _pcb){ + log_e("0x%08x != 0x%08x", (uint32_t)pcb, (uint32_t)_pcb); + return ERR_OK; + } + tcp_arg(_pcb, NULL); + if(_pcb->state == LISTEN) { + tcp_sent(_pcb, NULL); + tcp_recv(_pcb, NULL); + tcp_err(_pcb, NULL); + tcp_poll(_pcb, NULL, 0); + } + if(tcp_close(_pcb) != ERR_OK) { + tcp_abort(_pcb); + } + _free_closed_slot(); + _pcb = NULL; + return ERR_OK; +} + +//In Async Thread +int8_t AsyncClient::_fin(tcp_pcb* pcb, int8_t err) { + _tcp_clear_events(this); + if(_discard_cb) { + _discard_cb(_discard_cb_arg, this); + } + return ERR_OK; +} + +int8_t AsyncClient::_sent(tcp_pcb* pcb, uint16_t len) { + _rx_last_packet = millis(); + //log_i("%u", len); + _pcb_busy = false; + if(_sent_cb) { + _sent_cb(_sent_cb_arg, this, len, (millis() - _pcb_sent_at)); + } + return ERR_OK; +} + +int8_t AsyncClient::_recv(tcp_pcb* pcb, pbuf* pb, int8_t err) { + while(pb != NULL) { + _rx_last_packet = millis(); + //we should not ack before we assimilate the data + _ack_pcb = true; + pbuf *b = pb; + pb = b->next; + b->next = NULL; + if(_pb_cb){ + _pb_cb(_pb_cb_arg, this, b); + } else { + if(_recv_cb) { + _recv_cb(_recv_cb_arg, this, b->payload, b->len); + } + if(!_ack_pcb) { + _rx_ack_len += b->len; + } else if(_pcb) { + _tcp_recved(_pcb, _closed_slot, b->len); + } + pbuf_free(b); + } + } + return ERR_OK; +} + +int8_t AsyncClient::_poll(tcp_pcb* pcb){ + if(!_pcb){ + log_w("pcb is NULL"); + return ERR_OK; + } + if(pcb != _pcb){ + log_e("0x%08x != 0x%08x", (uint32_t)pcb, (uint32_t)_pcb); + return ERR_OK; + } + + uint32_t now = millis(); + + // ACK Timeout + if(_pcb_busy && _ack_timeout && (now - _pcb_sent_at) >= _ack_timeout){ + _pcb_busy = false; + log_w("ack timeout %d", pcb->state); + if(_timeout_cb) + _timeout_cb(_timeout_cb_arg, this, (now - _pcb_sent_at)); + return ERR_OK; + } + // RX Timeout + if(_rx_since_timeout && (now - _rx_last_packet) >= (_rx_since_timeout * 1000)){ + log_w("rx timeout %d", pcb->state); + _close(); + return ERR_OK; + } + // Everything is fine + if(_poll_cb) { + _poll_cb(_poll_cb_arg, this); + } + return ERR_OK; +} + +void AsyncClient::_dns_found(struct ip_addr *ipaddr){ + if(ipaddr && ipaddr->u_addr.ip4.addr){ + connect(IPAddress(ipaddr->u_addr.ip4.addr), _connect_port); + } else { + if(_error_cb) { + _error_cb(_error_cb_arg, this, -55); + } + if(_discard_cb) { + _discard_cb(_discard_cb_arg, this); + } + } +} + +/* + * Public Helper Methods + * */ + +void AsyncClient::stop() { + close(false); +} + +bool AsyncClient::free(){ + if(!_pcb) { + return true; + } + if(_pcb->state == 0 || _pcb->state > 4) { + return true; + } + return false; +} + +size_t AsyncClient::write(const char* data) { + if(data == NULL) { + return 0; + } + return write(data, strlen(data)); +} + +size_t AsyncClient::write(const char* data, size_t size, uint8_t apiflags) { + size_t will_send = add(data, size, apiflags); + if(!will_send || !send()) { + return 0; + } + return will_send; +} + +void AsyncClient::setRxTimeout(uint32_t timeout){ + _rx_since_timeout = timeout; +} + +uint32_t AsyncClient::getRxTimeout(){ + return _rx_since_timeout; +} + +uint32_t AsyncClient::getAckTimeout(){ + return _ack_timeout; +} + +void AsyncClient::setAckTimeout(uint32_t timeout){ + _ack_timeout = timeout; +} + +void AsyncClient::setNoDelay(bool nodelay){ + if(!_pcb) { + return; + } + if(nodelay) { + tcp_nagle_disable(_pcb); + } else { + tcp_nagle_enable(_pcb); + } +} + +bool AsyncClient::getNoDelay(){ + if(!_pcb) { + return false; + } + return tcp_nagle_disabled(_pcb); +} + +uint16_t AsyncClient::getMss(){ + if(!_pcb) { + return 0; + } + return tcp_mss(_pcb); +} + +uint32_t AsyncClient::getRemoteAddress() { + if(!_pcb) { + return 0; + } + return _pcb->remote_ip.u_addr.ip4.addr; +} + +uint16_t AsyncClient::getRemotePort() { + if(!_pcb) { + return 0; + } + return _pcb->remote_port; +} + +uint32_t AsyncClient::getLocalAddress() { + if(!_pcb) { + return 0; + } + return _pcb->local_ip.u_addr.ip4.addr; +} + +uint16_t AsyncClient::getLocalPort() { + if(!_pcb) { + return 0; + } + return _pcb->local_port; +} + +IPAddress AsyncClient::remoteIP() { + return IPAddress(getRemoteAddress()); +} + +uint16_t AsyncClient::remotePort() { + return getRemotePort(); +} + +IPAddress AsyncClient::localIP() { + return IPAddress(getLocalAddress()); +} + +uint16_t AsyncClient::localPort() { + return getLocalPort(); +} + +uint8_t AsyncClient::state() { + if(!_pcb) { + return 0; + } + return _pcb->state; +} + +bool AsyncClient::connected(){ + if (!_pcb) { + return false; + } + return _pcb->state == 4; +} + +bool AsyncClient::connecting(){ + if (!_pcb) { + return false; + } + return _pcb->state > 0 && _pcb->state < 4; +} + +bool AsyncClient::disconnecting(){ + if (!_pcb) { + return false; + } + return _pcb->state > 4 && _pcb->state < 10; +} + +bool AsyncClient::disconnected(){ + if (!_pcb) { + return true; + } + return _pcb->state == 0 || _pcb->state == 10; +} + +bool AsyncClient::freeable(){ + if (!_pcb) { + return true; + } + return _pcb->state == 0 || _pcb->state > 4; +} + +bool AsyncClient::canSend(){ + return space() > 0; +} + +const char * AsyncClient::errorToString(int8_t error){ + switch(error){ + case ERR_OK: return "OK"; + case ERR_MEM: return "Out of memory error"; + case ERR_BUF: return "Buffer error"; + case ERR_TIMEOUT: return "Timeout"; + case ERR_RTE: return "Routing problem"; + case ERR_INPROGRESS: return "Operation in progress"; + case ERR_VAL: return "Illegal value"; + case ERR_WOULDBLOCK: return "Operation would block"; + case ERR_USE: return "Address in use"; + case ERR_ALREADY: return "Already connected"; + case ERR_CONN: return "Not connected"; + case ERR_IF: return "Low-level netif error"; + case ERR_ABRT: return "Connection aborted"; + case ERR_RST: return "Connection reset"; + case ERR_CLSD: return "Connection closed"; + case ERR_ARG: return "Illegal argument"; + case -55: return "DNS failed"; + default: return "UNKNOWN"; + } +} + +const char * AsyncClient::stateToString(){ + switch(state()){ + case 0: return "Closed"; + case 1: return "Listen"; + case 2: return "SYN Sent"; + case 3: return "SYN Received"; + case 4: return "Established"; + case 5: return "FIN Wait 1"; + case 6: return "FIN Wait 2"; + case 7: return "Close Wait"; + case 8: return "Closing"; + case 9: return "Last ACK"; + case 10: return "Time Wait"; + default: return "UNKNOWN"; + } +} + +/* + * Static Callbacks (LwIP C2C++ interconnect) + * */ + +void AsyncClient::_s_dns_found(const char * name, struct ip_addr * ipaddr, void * arg){ + reinterpret_cast(arg)->_dns_found(ipaddr); +} + +int8_t AsyncClient::_s_poll(void * arg, struct tcp_pcb * pcb) { + return reinterpret_cast(arg)->_poll(pcb); +} + +int8_t AsyncClient::_s_recv(void * arg, struct tcp_pcb * pcb, struct pbuf *pb, int8_t err) { + return reinterpret_cast(arg)->_recv(pcb, pb, err); +} + +int8_t AsyncClient::_s_fin(void * arg, struct tcp_pcb * pcb, int8_t err) { + return reinterpret_cast(arg)->_fin(pcb, err); +} + +int8_t AsyncClient::_s_lwip_fin(void * arg, struct tcp_pcb * pcb, int8_t err) { + return reinterpret_cast(arg)->_lwip_fin(pcb, err); +} + +int8_t AsyncClient::_s_sent(void * arg, struct tcp_pcb * pcb, uint16_t len) { + return reinterpret_cast(arg)->_sent(pcb, len); +} + +void AsyncClient::_s_error(void * arg, int8_t err) { + reinterpret_cast(arg)->_error(err); +} + +int8_t AsyncClient::_s_connected(void * arg, void * pcb, int8_t err){ + return reinterpret_cast(arg)->_connected(pcb, err); +} + +/* + Async TCP Server + */ + +AsyncServer::AsyncServer(IPAddress addr, uint16_t port) +: _port(port) +, _addr(addr) +, _noDelay(false) +, _pcb(0) +, _connect_cb(0) +, _connect_cb_arg(0) +{} + +AsyncServer::AsyncServer(uint16_t port) +: _port(port) +, _addr((uint32_t) IPADDR_ANY) +, _noDelay(false) +, _pcb(0) +, _connect_cb(0) +, _connect_cb_arg(0) +{} + +AsyncServer::~AsyncServer(){ + end(); +} + +void AsyncServer::onClient(AcConnectHandler cb, void* arg){ + _connect_cb = cb; + _connect_cb_arg = arg; +} + +void AsyncServer::begin(){ + if(_pcb) { + return; + } + + if(!_start_async_task()){ + log_e("failed to start task"); + return; + } + int8_t err; + TCP_MUTEX_LOCK(); + _pcb = tcp_new_ip_type(IPADDR_TYPE_V4); + TCP_MUTEX_UNLOCK(); + if (!_pcb){ + log_e("_pcb == NULL"); + return; + } + + ip_addr_t local_addr; + local_addr.type = IPADDR_TYPE_V4; + local_addr.u_addr.ip4.addr = (uint32_t) _addr; + err = _tcp_bind(_pcb, &local_addr, _port); + + if (err != ERR_OK) { + _tcp_close(_pcb, -1); + log_e("bind error: %d", err); + return; + } + + static uint8_t backlog = 5; + _pcb = _tcp_listen_with_backlog(_pcb, backlog); + if (!_pcb) { + log_e("listen_pcb == NULL"); + return; + } + TCP_MUTEX_LOCK(); + tcp_arg(_pcb, (void*) this); + tcp_accept(_pcb, &_s_accept); + TCP_MUTEX_UNLOCK(); +} + +void AsyncServer::end(){ + if(_pcb){ + TCP_MUTEX_LOCK(); + tcp_arg(_pcb, NULL); + tcp_accept(_pcb, NULL); + TCP_MUTEX_UNLOCK(); + if(tcp_close(_pcb) != ERR_OK){ + _tcp_abort(_pcb, -1); + } + _pcb = NULL; + } +} + +//runs on LwIP thread +int8_t AsyncServer::_accept(tcp_pcb* pcb, int8_t err){ + //ets_printf("+A: 0x%08x\n", pcb); + if(_connect_cb){ + AsyncClient *c = new AsyncClient(pcb); + if(c){ + c->setNoDelay(_noDelay); + return _tcp_accept(this, c); + } + } + if(tcp_close(pcb) != ERR_OK){ + tcp_abort(pcb); + } + log_e("FAIL"); + return ERR_OK; +} + +int8_t AsyncServer::_accepted(AsyncClient* client){ + if(_connect_cb){ + _connect_cb(_connect_cb_arg, client); + } + return ERR_OK; +} + +void AsyncServer::setNoDelay(bool nodelay){ + _noDelay = nodelay; +} + +bool AsyncServer::getNoDelay(){ + return _noDelay; +} + +uint8_t AsyncServer::status(){ + if (!_pcb) { + return 0; + } + return _pcb->state; +} + +int8_t AsyncServer::_s_accept(void * arg, tcp_pcb * pcb, int8_t err){ + return reinterpret_cast(arg)->_accept(pcb, err); +} + +int8_t AsyncServer::_s_accepted(void *arg, AsyncClient* client){ + return reinterpret_cast(arg)->_accepted(client); +} diff --git a/Software/src/lib/me-no-dev-AsyncTCP/src/AsyncTCP.h b/Software/src/lib/me-no-dev-AsyncTCP/src/AsyncTCP.h new file mode 100644 index 00000000..b89fb122 --- /dev/null +++ b/Software/src/lib/me-no-dev-AsyncTCP/src/AsyncTCP.h @@ -0,0 +1,220 @@ +/* + Asynchronous TCP library for Espressif MCUs + + Copyright (c) 2016 Hristo Gochkov. All rights reserved. + This file is part of the esp8266 core for Arduino environment. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef ASYNCTCP_H_ +#define ASYNCTCP_H_ + +#include "IPAddress.h" +#include "sdkconfig.h" +#include +extern "C" { + #include "freertos/semphr.h" + #include "lwip/pbuf.h" +} + +#include "../../../system_settings.h" +#include "../../../devboard/hal/hal.h" + +//If core is not defined, then we are running in Arduino or PIO +#ifndef CONFIG_ASYNC_TCP_RUNNING_CORE +#define CONFIG_ASYNC_TCP_RUNNING_CORE WIFI_CORE //any available core +#define CONFIG_ASYNC_TCP_USE_WDT 0 //if enabled, adds between 33us and 200us per event +#endif + +class AsyncClient; + +#define ASYNC_MAX_ACK_TIME 5000 +#define ASYNC_WRITE_FLAG_COPY 0x01 //will allocate new buffer to hold the data while sending (else will hold reference to the data given) +#define ASYNC_WRITE_FLAG_MORE 0x02 //will not send PSH flag, meaning that there should be more data to be sent before the application should react. + +typedef std::function AcConnectHandler; +typedef std::function AcAckHandler; +typedef std::function AcErrorHandler; +typedef std::function AcDataHandler; +typedef std::function AcPacketHandler; +typedef std::function AcTimeoutHandler; + +struct tcp_pcb; +struct ip_addr; + +class AsyncClient { + public: + AsyncClient(tcp_pcb* pcb = 0); + ~AsyncClient(); + + AsyncClient & operator=(const AsyncClient &other); + AsyncClient & operator+=(const AsyncClient &other); + + bool operator==(const AsyncClient &other); + + bool operator!=(const AsyncClient &other) { + return !(*this == other); + } + bool connect(IPAddress ip, uint16_t port); + bool connect(const char* host, uint16_t port); + void close(bool now = false); + void stop(); + int8_t abort(); + bool free(); + + bool canSend();//ack is not pending + size_t space();//space available in the TCP window + size_t add(const char* data, size_t size, uint8_t apiflags=ASYNC_WRITE_FLAG_COPY);//add for sending + bool send();//send all data added with the method above + + //write equals add()+send() + size_t write(const char* data); + size_t write(const char* data, size_t size, uint8_t apiflags=ASYNC_WRITE_FLAG_COPY); //only when canSend() == true + + uint8_t state(); + bool connecting(); + bool connected(); + bool disconnecting(); + bool disconnected(); + bool freeable();//disconnected or disconnecting + + uint16_t getMss(); + + uint32_t getRxTimeout(); + void setRxTimeout(uint32_t timeout);//no RX data timeout for the connection in seconds + + uint32_t getAckTimeout(); + void setAckTimeout(uint32_t timeout);//no ACK timeout for the last sent packet in milliseconds + + void setNoDelay(bool nodelay); + bool getNoDelay(); + + uint32_t getRemoteAddress(); + uint16_t getRemotePort(); + uint32_t getLocalAddress(); + uint16_t getLocalPort(); + + //compatibility + IPAddress remoteIP(); + uint16_t remotePort(); + IPAddress localIP(); + uint16_t localPort(); + + void onConnect(AcConnectHandler cb, void* arg = 0); //on successful connect + void onDisconnect(AcConnectHandler cb, void* arg = 0); //disconnected + void onAck(AcAckHandler cb, void* arg = 0); //ack received + void onError(AcErrorHandler cb, void* arg = 0); //unsuccessful connect or error + void onData(AcDataHandler cb, void* arg = 0); //data received (called if onPacket is not used) + void onPacket(AcPacketHandler cb, void* arg = 0); //data received + void onTimeout(AcTimeoutHandler cb, void* arg = 0); //ack timeout + void onPoll(AcConnectHandler cb, void* arg = 0); //every 125ms when connected + + void ackPacket(struct pbuf * pb);//ack pbuf from onPacket + size_t ack(size_t len); //ack data that you have not acked using the method below + void ackLater(){ _ack_pcb = false; } //will not ack the current packet. Call from onData + + const char * errorToString(int8_t error); + const char * stateToString(); + + //Do not use any of the functions below! + static int8_t _s_poll(void *arg, struct tcp_pcb *tpcb); + static int8_t _s_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *pb, int8_t err); + static int8_t _s_fin(void *arg, struct tcp_pcb *tpcb, int8_t err); + static int8_t _s_lwip_fin(void *arg, struct tcp_pcb *tpcb, int8_t err); + static void _s_error(void *arg, int8_t err); + static int8_t _s_sent(void *arg, struct tcp_pcb *tpcb, uint16_t len); + static int8_t _s_connected(void* arg, void* tpcb, int8_t err); + static void _s_dns_found(const char *name, struct ip_addr *ipaddr, void *arg); + + int8_t _recv(tcp_pcb* pcb, pbuf* pb, int8_t err); + tcp_pcb * pcb(){ return _pcb; } + + protected: + tcp_pcb* _pcb; + int8_t _closed_slot; + + AcConnectHandler _connect_cb; + void* _connect_cb_arg; + AcConnectHandler _discard_cb; + void* _discard_cb_arg; + AcAckHandler _sent_cb; + void* _sent_cb_arg; + AcErrorHandler _error_cb; + void* _error_cb_arg; + AcDataHandler _recv_cb; + void* _recv_cb_arg; + AcPacketHandler _pb_cb; + void* _pb_cb_arg; + AcTimeoutHandler _timeout_cb; + void* _timeout_cb_arg; + AcConnectHandler _poll_cb; + void* _poll_cb_arg; + + bool _pcb_busy; + uint32_t _pcb_sent_at; + bool _ack_pcb; + uint32_t _rx_ack_len; + uint32_t _rx_last_packet; + uint32_t _rx_since_timeout; + uint32_t _ack_timeout; + uint16_t _connect_port; + + int8_t _close(); + void _free_closed_slot(); + void _allocate_closed_slot(); + int8_t _connected(void* pcb, int8_t err); + void _error(int8_t err); + int8_t _poll(tcp_pcb* pcb); + int8_t _sent(tcp_pcb* pcb, uint16_t len); + int8_t _fin(tcp_pcb* pcb, int8_t err); + int8_t _lwip_fin(tcp_pcb* pcb, int8_t err); + void _dns_found(struct ip_addr *ipaddr); + + public: + AsyncClient* prev; + AsyncClient* next; +}; + +class AsyncServer { + public: + AsyncServer(IPAddress addr, uint16_t port); + AsyncServer(uint16_t port); + ~AsyncServer(); + void onClient(AcConnectHandler cb, void* arg); + void begin(); + void end(); + void setNoDelay(bool nodelay); + bool getNoDelay(); + uint8_t status(); + + //Do not use any of the functions below! + static int8_t _s_accept(void *arg, tcp_pcb* newpcb, int8_t err); + static int8_t _s_accepted(void *arg, AsyncClient* client); + + protected: + uint16_t _port; + IPAddress _addr; + bool _noDelay; + tcp_pcb* _pcb; + AcConnectHandler _connect_cb; + void* _connect_cb_arg; + + int8_t _accept(tcp_pcb* newpcb, int8_t err); + int8_t _accepted(AsyncClient* client); +}; + + +#endif /* ASYNCTCP_H_ */ diff --git a/Software/src/lib/me-no-dev-ESPAsyncWebServer/src/AsyncEventSource.h b/Software/src/lib/me-no-dev-ESPAsyncWebServer/src/AsyncEventSource.h index 94a0c51e..d3d1b1d4 100644 --- a/Software/src/lib/me-no-dev-ESPAsyncWebServer/src/AsyncEventSource.h +++ b/Software/src/lib/me-no-dev-ESPAsyncWebServer/src/AsyncEventSource.h @@ -22,7 +22,7 @@ #include #ifdef ESP32 -#include "../../mathieucarbou-AsyncTCP/src/AsyncTCP.h" +#include "../../me-no-dev-AsyncTCP/src/AsyncTCP.h" #define SSE_MAX_QUEUED_MESSAGES 32 #else #include diff --git a/Software/src/lib/me-no-dev-ESPAsyncWebServer/src/AsyncWebSocket.h b/Software/src/lib/me-no-dev-ESPAsyncWebServer/src/AsyncWebSocket.h index 2ef8f9ec..747399b8 100644 --- a/Software/src/lib/me-no-dev-ESPAsyncWebServer/src/AsyncWebSocket.h +++ b/Software/src/lib/me-no-dev-ESPAsyncWebServer/src/AsyncWebSocket.h @@ -23,7 +23,7 @@ #include #ifdef ESP32 -#include "../../mathieucarbou-AsyncTCP/src/AsyncTCP.h" +#include "../../me-no-dev-AsyncTCP/src/AsyncTCP.h" #define WS_MAX_QUEUED_MESSAGES 32 #else #include diff --git a/Software/src/lib/me-no-dev-ESPAsyncWebServer/src/ESPAsyncWebServer.h b/Software/src/lib/me-no-dev-ESPAsyncWebServer/src/ESPAsyncWebServer.h index 7731a14c..664c0a5c 100644 --- a/Software/src/lib/me-no-dev-ESPAsyncWebServer/src/ESPAsyncWebServer.h +++ b/Software/src/lib/me-no-dev-ESPAsyncWebServer/src/ESPAsyncWebServer.h @@ -30,10 +30,10 @@ #ifdef ESP32 #include -#include "../../mathieucarbou-AsyncTCP/src/AsyncTCP.h" +#include "../../me-no-dev-AsyncTCP/src/AsyncTCP.h" #elif defined(ESP8266) #include -#include "../../mathieucarbou-AsyncTCP/src/AsyncTCP.h" +#include "../../me-no-dev-AsyncTCP/src/AsyncTCP.h" #else #error Platform not supported #endif