Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions SmartEVSE-3/src/esp32.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -832,6 +832,31 @@ void mqtt_receive_callback(const String topic, const String payload) {
break;
// END PLAN-09

// BEGIN PLAN-15: SoC MQTT commands
#if MODEM
case MQTT_CMD_INITIAL_SOC:
InitialSoC = cmd.initial_soc;
RecomputeSoC();
break;
case MQTT_CMD_FULL_SOC:
FullSoC = cmd.full_soc;
RecomputeSoC();
break;
case MQTT_CMD_ENERGY_CAPACITY:
EnergyCapacity = cmd.energy_capacity;
RecomputeSoC();
break;
case MQTT_CMD_ENERGY_REQUEST:
EnergyRequest = cmd.energy_request;
RecomputeSoC();
break;
case MQTT_CMD_EVCCID_SET:
strncpy(EVCCID, cmd.evccid, sizeof(EVCCID) - 1);
EVCCID[sizeof(EVCCID) - 1] = '\0';
break;
#endif
// END PLAN-15

default:
return;
}
Expand Down
56 changes: 56 additions & 0 deletions SmartEVSE-3/src/mqtt_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,62 @@ bool mqtt_parse_command(const char *prefix, const char *topic,
return false;
}

/* EV State of Charge and energy parameters */
if (match_topic(prefix, topic, "/Set/InitialSoC")) {
if (payload[0] == '\0') return false;
char *endptr;
long val = strtol(payload, &endptr, 10);
if (*endptr != '\0') return false;
if (val < -1 || val > 100) return false;
out->cmd = MQTT_CMD_INITIAL_SOC;
out->initial_soc = (int8_t)val;
return true;
}

if (match_topic(prefix, topic, "/Set/FullSoC")) {
if (payload[0] == '\0') return false;
char *endptr;
long val = strtol(payload, &endptr, 10);
if (*endptr != '\0') return false;
if (val < -1 || val > 100) return false;
out->cmd = MQTT_CMD_FULL_SOC;
out->full_soc = (int8_t)val;
return true;
}

if (match_topic(prefix, topic, "/Set/EnergyCapacity")) {
if (payload[0] == '\0') return false;
char *endptr;
long val = strtol(payload, &endptr, 10);
if (*endptr != '\0') return false;
if (val < -1 || val > 200000) return false;
out->cmd = MQTT_CMD_ENERGY_CAPACITY;
out->energy_capacity = (int32_t)val;
return true;
}

if (match_topic(prefix, topic, "/Set/EnergyRequest")) {
if (payload[0] == '\0') return false;
char *endptr;
long val = strtol(payload, &endptr, 10);
if (*endptr != '\0') return false;
if (val < -1 || val > 200000) return false;
out->cmd = MQTT_CMD_ENERGY_REQUEST;
out->energy_request = (int32_t)val;
return true;
}

/* EV CC ID for session identification */
if (match_topic(prefix, topic, "/Set/EVCCID")) {
out->cmd = MQTT_CMD_EVCCID_SET;
size_t len = strlen(payload);
if (len >= sizeof(out->evccid))
return false;
strncpy(out->evccid, payload, sizeof(out->evccid) - 1);
out->evccid[sizeof(out->evccid) - 1] = '\0';
return true;
}

if (match_topic(prefix, topic, "/Set/DiagProfile")) {
out->cmd = MQTT_CMD_DIAG_PROFILE;
if (strcmp(payload, "off") == 0 || strcmp(payload, "0") == 0) {
Expand Down
11 changes: 10 additions & 1 deletion SmartEVSE-3/src/mqtt_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ typedef enum {
MQTT_CMD_DIAG_PROFILE,
MQTT_CMD_MAINS_METER_TIMEOUT,
MQTT_CMD_HOMEWIZARD_IP,
MQTT_CMD_INITIAL_SOC,
MQTT_CMD_FULL_SOC,
MQTT_CMD_ENERGY_CAPACITY,
MQTT_CMD_ENERGY_REQUEST,
MQTT_CMD_EVCCID_SET,
} mqtt_cmd_type_t;

// Mode values matching firmware MODE_NORMAL/MODE_SOLAR/MODE_SMART
Expand Down Expand Up @@ -59,7 +64,7 @@ typedef struct {
struct { int32_t L1, L2, L3; } mains_meter;
struct { int32_t L1, L2, L3; int32_t W; int32_t Wh; } ev_meter;
int16_t home_battery_current; // MQTT_CMD_HOME_BATTERY_CURRENT
char evccid[32]; // MQTT_CMD_REQUIRED_EVCCID
char evccid[32]; // MQTT_CMD_REQUIRED_EVCCID and MQTT_CMD_EVCCID_SET
struct { uint8_t index; uint8_t r, g, b; } color; // MQTT_CMD_COLOR
uint8_t cable_lock; // MQTT_CMD_CABLE_LOCK
uint8_t enable_c2; // MQTT_CMD_ENABLE_C2
Expand All @@ -72,6 +77,10 @@ typedef struct {
uint8_t diag_profile; // MQTT_CMD_DIAG_PROFILE (0-5)
uint16_t mains_meter_timeout; // MQTT_CMD_MAINS_METER_TIMEOUT (0, 10-3600)
char homewizard_ip[16]; // MQTT_CMD_HOMEWIZARD_IP (IPv4 or empty)
int8_t initial_soc; // MQTT_CMD_INITIAL_SOC (-1 or 0-100)
int8_t full_soc; // MQTT_CMD_FULL_SOC (-1 or 0-100)
int32_t energy_capacity; // MQTT_CMD_ENERGY_CAPACITY (-1 or 0-200000 Wh)
int32_t energy_request; // MQTT_CMD_ENERGY_REQUEST (-1 or 0-200000 Wh)
};
} mqtt_command_t;

Expand Down
7 changes: 7 additions & 0 deletions SmartEVSE-3/test/native/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ SOLAR_DEBUG_JSON_SRC := $(SRC_DIR)/solar_debug_json.c
SESSION_LOG_SRC := $(SRC_DIR)/session_log.c
DIAG_TELEMETRY_SRC := $(SRC_DIR)/diag_telemetry.c
DIAG_MODBUS_SRC := $(SRC_DIR)/diag_modbus.c
CAPACITY_PEAK_SRC := $(SRC_DIR)/capacity_peak.c

# Discover all test files
TEST_SRCS := $(wildcard $(TEST_DIR)/test_*.c)
Expand All @@ -49,6 +50,9 @@ all: $(TEST_BINS)
$(BUILD)/test_mqtt_parser: $(TEST_DIR)/test_mqtt_parser.c $(MQTT_PARSER_SRC) $(SRC_DIR)/mqtt_parser.h include/*.h | $(BUILD)
$(CC) $(CFLAGS) $(INCLUDES) -o $@ $(TEST_DIR)/test_mqtt_parser.c $(MQTT_PARSER_SRC)

$(BUILD)/test_mqtt_soc: $(TEST_DIR)/test_mqtt_soc.c $(MQTT_PARSER_SRC) $(SRC_DIR)/mqtt_parser.h include/*.h | $(BUILD)
$(CC) $(CFLAGS) $(INCLUDES) -o $@ $(TEST_DIR)/test_mqtt_soc.c $(MQTT_PARSER_SRC)

$(BUILD)/test_mqtt_publish: $(TEST_DIR)/test_mqtt_publish.c $(MQTT_PUBLISH_SRC) $(SRC_DIR)/mqtt_publish.h include/*.h | $(BUILD)
$(CC) $(CFLAGS) $(INCLUDES) -o $@ $(TEST_DIR)/test_mqtt_publish.c $(MQTT_PUBLISH_SRC)

Expand Down Expand Up @@ -112,6 +116,9 @@ $(BUILD)/test_diag_modbus: $(TEST_DIR)/test_diag_modbus.c $(DIAG_MODBUS_SRC) $(S
$(BUILD)/test_diag_replay: $(TEST_DIR)/test_diag_replay.c diag_loader.c include/diag_loader.h $(DIAG_TELEMETRY_SRC) $(SRC_DIR)/diag_telemetry.h include/*.h | $(BUILD)
$(CC) $(CFLAGS) $(INCLUDES) -o $@ $(TEST_DIR)/test_diag_replay.c diag_loader.c $(DIAG_TELEMETRY_SRC)

$(BUILD)/test_capacity_peak: $(TEST_DIR)/test_capacity_peak.c $(CAPACITY_PEAK_SRC) $(SRC_DIR)/capacity_peak.h include/*.h | $(BUILD)
$(CC) $(CFLAGS) $(INCLUDES) -o $@ $(TEST_DIR)/test_capacity_peak.c $(CAPACITY_PEAK_SRC)

$(BUILD)/test_api_staleness: $(TEST_DIR)/test_api_staleness.c $(EVSE_SRC) $(MQTT_PARSER_SRC) $(SRC_DIR)/evse_ctx.h $(SRC_DIR)/mqtt_parser.h include/*.h | $(BUILD)
$(CC) $(CFLAGS) $(INCLUDES) -o $@ $(TEST_DIR)/test_api_staleness.c $(EVSE_SRC) $(MQTT_PARSER_SRC)

Expand Down
Loading
Loading