Add more commands and error handling to pipsolar driver. (#23659)

Co-authored-by: Peter Rustler <peter@rustlerit.de>
This commit is contained in:
chefpro 2025-07-09 22:41:53 +02:00 committed by GitHub
parent bb53b42790
commit a052ee00a2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 311 additions and 50 deletions

View File

@ -852,6 +852,12 @@
#define D_CMND_PIP_QED "QED" #define D_CMND_PIP_QED "QED"
#define D_CMND_PIP_QEH "QEH" #define D_CMND_PIP_QEH "QEH"
#define D_CMND_PIP_DAT "DAT" #define D_CMND_PIP_DAT "DAT"
#define D_CMND_PIP_QMOD "QMOD"
#define D_CMND_PIP_QPIWS "QPIWS"
#define D_CMND_PIP_QPIRI "QPIRI"
#define D_CMND_PIP_QPIGS "QPIGS"
#define D_CMND_PIP_QFLAG "QFLAG"
#define D_CMND_PIP_CUSTOM "CUSTOM"
#define D_CMND_PIP_POLLVALUES "PollValues" #define D_CMND_PIP_POLLVALUES "PollValues"
#define D_CMND_PIP_BAUDRATE "BaudRate" #define D_CMND_PIP_BAUDRATE "BaudRate"
#define D_CMND_PIP_SERIALCONFIG "SerialConfig" #define D_CMND_PIP_SERIALCONFIG "SerialConfig"

View File

@ -40,7 +40,6 @@ struct PipSolar
{ {
NONE, NONE,
QPIGS, // get analog values QPIGS, // get analog values
//QPIRI, // Device Rating Information (settings)
QMOD, // get mode QMOD, // get mode
QPIWS, // get status/error information QPIWS, // get status/error information
QT, // get inverter time QT, // get inverter time
@ -50,6 +49,9 @@ struct PipSolar
QED, // energy day QED, // energy day
QEH, // energy hour QEH, // energy hour
DAT, // set date time DAT, // set date time
QPIRI, // Device Rating Information (settings)
QFLAG, // Device flag status
CUSTOM,// Custom command
} commandType; } commandType;
enum class CommandState { enum class CommandState {
@ -75,6 +77,18 @@ struct PipSolar
char charValue; char charValue;
}; };
enum class BoolFlag : int8_t {
False,
True,
Unknown,
};
struct QFlagValueSetting {
BoolFlag value;
const char identifier;
const char name[30];
};
struct ValueSetting struct ValueSetting
{ {
Value value; Value value;
@ -95,6 +109,7 @@ struct PipSolar
const char unit[4]; const char unit[4];
const bool publish; const bool publish;
}; };
struct QueryCommand { struct QueryCommand {
PipSolar::CommandType commandType; PipSolar::CommandType commandType;
bool send; bool send;
@ -109,6 +124,7 @@ struct PIPSOLARPollingValue {
const uint16_t waitAfterResponse; // *2ms const uint16_t waitAfterResponse; // *2ms
bool poll; bool poll;
}; };
struct PIPSOLARPollingValue PIPSOLARpollingList[] = { struct PIPSOLARPollingValue PIPSOLARpollingList[] = {
{3, PipSolar::CommandType::QPIWS, 600, 200, false}, {3, PipSolar::CommandType::QPIWS, 600, 200, false},
{3, PipSolar::CommandType::QPIGS, 600, 200, false}, {3, PipSolar::CommandType::QPIGS, 600, 200, false},
@ -120,6 +136,9 @@ struct PIPSOLARPollingValue PIPSOLARpollingList[] = {
{0, PipSolar::CommandType::QED, 200, 200, false}, {0, PipSolar::CommandType::QED, 200, 200, false},
{0, PipSolar::CommandType::QEH, 200, 200, false}, {0, PipSolar::CommandType::QEH, 200, 200, false},
{0, PipSolar::CommandType::DAT, 200, 200, false}, {0, PipSolar::CommandType::DAT, 200, 200, false},
{0, PipSolar::CommandType::QPIRI, 600, 200, false},
{0, PipSolar::CommandType::QFLAG, 600, 200, false},
{0, PipSolar::CommandType::CUSTOM, 600, 200, false},
}; };
constexpr uint8_t PIPSOLARpollingListCount = sizeof(PIPSOLARpollingList) / sizeof(PIPSOLARPollingValue); constexpr uint8_t PIPSOLARpollingListCount = sizeof(PIPSOLARpollingList) / sizeof(PIPSOLARPollingValue);
uint8_t PIPSOLARpollingValuePosition = PIPSOLARpollingListCount; uint8_t PIPSOLARpollingValuePosition = PIPSOLARpollingListCount;
@ -164,6 +183,37 @@ struct PipSolar::ValueSetting PIPSOLARqpigsValueSettings[] = {
}; };
constexpr uint8_t PIPSOLARqpigsValueSettingsCount = sizeof(PIPSOLARqpigsValueSettings) / sizeof(PipSolar::ValueSetting); constexpr uint8_t PIPSOLARqpigsValueSettingsCount = sizeof(PIPSOLARqpigsValueSettings) / sizeof(PipSolar::ValueSetting);
// (230.0 24.3 230.0 50.0 24.3 5600 5600 48.0 49.0 48.0 55.6 55.6 2 002 060 1 2 3 9 00 0 2 49.0 0 1 000
struct PipSolar::ValueSetting PIPSOLARqpiriValueSettings[] = {
//{{}, PipSolar::ValueSetting::Type::floatType, 1, 5, "Output_voltage", "V", true},
//{{}, PipSolar::ValueSetting::Type::floatType, 7, 4, "Output_current", "Hz", true},
{{}, PipSolar::ValueSetting::Type::floatType, 12, 5, "AC_out_voltage_setting", "V", true},
{{}, PipSolar::ValueSetting::Type::floatType, 18, 4, "AC_out_frequency_setting", "Hz", true},
{{}, PipSolar::ValueSetting::Type::floatType, 23, 4, "AC_out_current_setting", "A", true},
{{}, PipSolar::ValueSetting::Type::intType, 28, 4, "AC_out_apparent_power_setting", "W", true},
{{}, PipSolar::ValueSetting::Type::intType, 33, 4, "AC_out_active_power_setting", "W", true},
{{}, PipSolar::ValueSetting::Type::floatType, 38, 4, "Bat_rating_voltage_setting", "V", true},
{{}, PipSolar::ValueSetting::Type::floatType, 43, 4, "Bat_recharge_voltage_setting", "V", true},
{{}, PipSolar::ValueSetting::Type::floatType, 48, 4, "Bat_under_voltage_setting", "V", true},
{{}, PipSolar::ValueSetting::Type::floatType, 53, 4, "Bat_bulk_voltage_setting", "V", true},
{{}, PipSolar::ValueSetting::Type::floatType, 58, 4, "Bat_float_voltage_setting", "V", true},
{{}, PipSolar::ValueSetting::Type::intType, 63, 1, "Bat_type_setting", "", true},
{{}, PipSolar::ValueSetting::Type::intType, 65, 3, "Current_max_ac_charge_setting", "A", true},
{{}, PipSolar::ValueSetting::Type::intType, 69, 3, "Current_max_charge_setting", "A", true},
{{}, PipSolar::ValueSetting::Type::intType, 73, 1, "Input_voltage_range_setting", "", true},
{{}, PipSolar::ValueSetting::Type::intType, 75, 1, "Out_source_prio_setting", "", true},
{{}, PipSolar::ValueSetting::Type::intType, 77, 1, "Charge_source_prio_setting", "", true},
{{}, PipSolar::ValueSetting::Type::intType, 79, 1, "Parallel_max_number_setting", "", true},
{{}, PipSolar::ValueSetting::Type::intType, 81, 2, "Maschine_type_setting", "", true},
{{}, PipSolar::ValueSetting::Type::intType, 84, 1, "Topology_setting", "", true},
{{}, PipSolar::ValueSetting::Type::intType, 86, 1, "Output_mode_setting", "", true},
{{}, PipSolar::ValueSetting::Type::floatType, 88, 4, "Redischarge_voltage_setting", "V", true},
{{}, PipSolar::ValueSetting::Type::intType, 93, 1, "PV_parallel_ok_cond_setting", "", true},
{{}, PipSolar::ValueSetting::Type::intType, 95, 1, "PV_power_balance_setting", "", true},
{{}, PipSolar::ValueSetting::Type::intType, 97, 3, "Max_time_cv_stage_setting", "Min", true},
};
constexpr uint8_t PIPSOLARqpiriValueSettingsCount = sizeof(PIPSOLARqpiriValueSettings) / sizeof(PipSolar::ValueSetting);
// (B // (B
struct PipSolar::ValueSetting PIPSOLARqmodValueSettings[] = { struct PipSolar::ValueSetting PIPSOLARqmodValueSettings[] = {
{{}, PipSolar::ValueSetting::Type::charType, 1, 1, "Mode", "", true}, {{}, PipSolar::ValueSetting::Type::charType, 1, 1, "Mode", "", true},
@ -186,6 +236,20 @@ struct PipSolar::ValueSetting PIPSOLARqexValueSettings[] = {
}; };
constexpr uint8_t PIPSOLARqexValueSettingsCount = sizeof(PIPSOLARqexValueSettings) / sizeof(PipSolar::ValueSetting); constexpr uint8_t PIPSOLARqexValueSettingsCount = sizeof(PIPSOLARqexValueSettings) / sizeof(PipSolar::ValueSetting);
// (EakxyDbjuvz
struct PipSolar::QFlagValueSetting PIPSOLARqflagValueSettings[] = {
// deviceflags 8x
{PipSolar::BoolFlag::Unknown, 'a', "Buzzer"},
{PipSolar::BoolFlag::Unknown, 'b', "OverloadBypass"},
{PipSolar::BoolFlag::Unknown, 'k', "DisplayTimeout"},
{PipSolar::BoolFlag::Unknown, 'u', "OverloadRestart"},
{PipSolar::BoolFlag::Unknown, 'v', "TemperatureRestart"},
{PipSolar::BoolFlag::Unknown, 'x', "Backlight"},
{PipSolar::BoolFlag::Unknown, 'y', "SourceInterruptAlarm"},
{PipSolar::BoolFlag::Unknown, 'z', "FaultCodeRecord"},
};
constexpr uint8_t PIPSOLARqflagValueSettingsCount = sizeof(PIPSOLARqflagValueSettings) / sizeof(PipSolar::QFlagValueSetting);
/********************************************************************************************/ /********************************************************************************************/
bool PIPSOLARSendCommand(PipSolar::CommandType cmd, const char *parameter = nullptr, bool checksum = false); bool PIPSOLARSendCommand(PipSolar::CommandType cmd, const char *parameter = nullptr, bool checksum = false);
@ -310,6 +374,24 @@ void CmndPipSolarDAT(void) {
//AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: command DAT")); //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: command DAT"));
CmndPipSolarParameter(PipSolar::CommandType::DAT); CmndPipSolarParameter(PipSolar::CommandType::DAT);
} }
void CmndPipSolarQPIRI(void) {
//AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: command QPIRI"));
CmndPipSolarNoParameter(PipSolar::CommandType::QPIRI);
}
void CmndPipSolarQFLAG(void) {
//AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: command QFLAG"));
CmndPipSolarNoParameter(PipSolar::CommandType::QFLAG);
}
void CmndPipSolarCUSTOM(void) {
if (XdrvMailbox.data_len == 0) {
ResponseCmndChar_P(PSTR("Error\", \"Error\": \"Parameter count"));
return;
}
//AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: command DAT"));
CmndPipSolarParameter(PipSolar::CommandType::CUSTOM);
}
void CmndPipSolarPollValues(void) { void CmndPipSolarPollValues(void) {
//AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: command PollValues")); //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: command PollValues"));
@ -373,6 +455,9 @@ const char kPipSolarCommands[] PROGMEM = D_CMND_PIP_PREFIX "|"
D_CMND_PIP_QED "|" D_CMND_PIP_QED "|"
D_CMND_PIP_QEH "|" D_CMND_PIP_QEH "|"
D_CMND_PIP_DAT "|" D_CMND_PIP_DAT "|"
D_CMND_PIP_QPIRI "|"
D_CMND_PIP_QFLAG "|"
D_CMND_PIP_CUSTOM "|"
D_CMND_PIP_POLLVALUES "|" D_CMND_PIP_POLLVALUES "|"
D_CMND_PIP_BAUDRATE "|" D_CMND_PIP_BAUDRATE "|"
D_CMND_PIP_SERIALCONFIG; D_CMND_PIP_SERIALCONFIG;
@ -385,6 +470,9 @@ void (* const PipSolarCommand[])(void) PROGMEM = {
&CmndPipSolarQED, &CmndPipSolarQED,
&CmndPipSolarQEH, &CmndPipSolarQEH,
&CmndPipSolarDAT, &CmndPipSolarDAT,
&CmndPipSolarQPIRI,
&CmndPipSolarQFLAG,
&CmndPipSolarCUSTOM,
&CmndPipSolarPollValues, &CmndPipSolarPollValues,
&CmndPipSolarBaudRate, &CmndPipSolarBaudRate,
&CmndPipSolarSerialConfig &CmndPipSolarSerialConfig
@ -427,49 +515,116 @@ void PIPSOLARPublishResult(const char *subtopic, int payload)
XdrvRulesProcess(0, buffer); XdrvRulesProcess(0, buffer);
} }
void PIPSOLARPublish(const char *subtopic, const char *payload) void PIPSOLARPublishRaw(const char *subtopic, const char *payload, bool usebracket = false)
{ {
MqttPublishPayloadPrefixTopic_P(STAT, subtopic, payload); MqttPublishPayloadPrefixTopic_P(STAT, subtopic, payload);
char buffer[150]; char buffer[300];
snprintf_P(buffer, sizeof(buffer), PSTR("{\"%s\": \"%s\"}"), subtopic, payload); if(usebracket)
snprintf_P(buffer, sizeof(buffer), PSTR("{\"%s\":\"%s\"}"), subtopic, payload);
else
snprintf_P(buffer, sizeof(buffer), PSTR("{\"%s\":%s}"), subtopic, payload);
//AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: PUBLISH %s"), (const char*)buffer); //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: PUBLISH %s"), (const char*)buffer);
XdrvRulesProcess(0, buffer); XdrvRulesProcess(0, buffer);
} }
void PIPSOLARPublishRaw(const char *subtopic, const char *payload) void PIPSOLARPublish(const char *subtopic, const char *value, bool json = false, const char *name = nullptr, const char *unit = nullptr)
{ {
MqttPublishPayloadPrefixTopic_P(STAT, subtopic, payload); if (json) {
char buffer[150]; char buffer[150];
snprintf_P(buffer, sizeof(buffer), PSTR("{\"%s\": %s}"), subtopic, payload); snprintf_P(buffer, sizeof(buffer), PSTR("{\"%s\":{\"value\":\"%s\",\"unit\":\"%s\"}}"), name, value, unit);
PIPSOLARPublishRaw(subtopic, buffer);
} else {
PIPSOLARPublishRaw(subtopic, value, true);
}
//AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: PUBLISH %s"), (const char*)buffer); //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: PUBLISH %s"), (const char*)buffer);
XdrvRulesProcess(0, buffer);
} }
void PIPSOLARPublish(const char *subtopic, int value) void PIPSOLARPublish(const char *subtopic, int value, bool json = false, const char *name = nullptr, const char *unit = nullptr)
{ {
char buffer[15]; char buffer[150];
snprintf(buffer, sizeof(buffer), "%d", value); if (json) {
snprintf_P(buffer, sizeof(buffer), PSTR("{\"%s\": {\"value\":%d,\"unit\":\"%s\"}}"), name, value, unit);
} else {
snprintf_P(buffer, sizeof(buffer), PSTR("%d"), value);
}
PIPSOLARPublishRaw(subtopic, buffer);
}
void PIPSOLARPublish(const char *subtopic, uint32_t value, bool json = false, const char *name = nullptr, const char *unit = nullptr)
{
char buffer[150];
if (json) {
snprintf_P(buffer, sizeof(buffer), PSTR("{\"%s\": {\"value\":%u,\"unit\":\"%s\"}}"), name, value, unit);
} else {
snprintf_P(buffer, sizeof(buffer), PSTR("%u"), value);
}
PIPSOLARPublishRaw(subtopic, buffer); PIPSOLARPublishRaw(subtopic, buffer);
} }
void PIPSOLARPublish(const char *subtopic, float value) void PIPSOLARPublish(const char *subtopic, float value, bool json = false, const char *name = nullptr, const char *unit = nullptr)
{ {
char buffer[15]; char buffer[150];
snprintf(buffer, sizeof(buffer), "%f", value); if (json) {
snprintf_P(buffer, sizeof(buffer), PSTR("{\"%s\": {\"value\":%.1f,\"unit\":\"%s\"}}"), name, value, unit);
} else {
snprintf_P(buffer, sizeof(buffer), PSTR("%.1f"), value);
}
PIPSOLARPublishRaw(subtopic, buffer); PIPSOLARPublishRaw(subtopic, buffer);
} }
void PIPSOLARPublish(const char *subtopic, char value) void PIPSOLARPublish(const char *subtopic, char value, bool json = false, const char *name = nullptr, const char *unit = nullptr)
{ {
char buffer[2]; char buffer[150];
snprintf(buffer, sizeof(buffer), "%c", value); if (json) {
snprintf_P(buffer, sizeof(buffer), PSTR("{\"%s\": {\"value\":\"%c\",\"unit\":\"%s\"}}"), name, value, unit);
} else {
snprintf_P(buffer, sizeof(buffer), PSTR("%c"), value);
}
PIPSOLARPublish(subtopic, buffer); PIPSOLARPublish(subtopic, buffer);
} }
void PIPSOLARPublish(const char *subtopic, bool value) void PIPSOLARPublish(const char *subtopic, bool value, bool json = false, const char *name = nullptr, const char *unit = nullptr)
{ {
char buffer[2]; char buffer[150];
snprintf(buffer, sizeof(buffer), "%d", value); if (json) {
snprintf_P(buffer, sizeof(buffer), PSTR("{\"%s\": {\"value\":%s,\"unit\":\"%s\"}}"), name, (value ? PSTR("true") : PSTR("false")), unit);
} else {
snprintf_P(buffer, sizeof(buffer), PSTR("%s"), (value ? PSTR("true") : PSTR("false")));
}
PIPSOLARPublishRaw(subtopic, buffer);
}
void PIPSOLARQFlagPublish(const char *subtopic)
{
char buffer[150] = "{";
uint8_t position = 1;
for(int i = 0; i < PIPSOLARqflagValueSettingsCount; ++i) {
int8_t addition = 0;
if (PIPSOLARqflagValueSettings[i].value == PipSolar::BoolFlag::True) {
addition = snprintf_P(buffer+position, sizeof(buffer)-position, PSTR("\"%s\":true,"), PIPSOLARqflagValueSettings[i].name);
} else if (PIPSOLARqflagValueSettings[i].value == PipSolar::BoolFlag::False) {
addition = snprintf_P(buffer+position, sizeof(buffer)-position, PSTR("\"%s\":false,"), PIPSOLARqflagValueSettings[i].name);
}
//AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("qflag: buffer:\"%s\" position:%d"), buffer, position);
if (position+addition > sizeof(buffer)-1) {
buffer[position-1] = '}';
buffer[position] = '\0';
PIPSOLARPublishRaw(subtopic, buffer);
// process the last one again
--i;
// make room for the missing messages
buffer[1] = 0;
}
position = strlen(buffer);
}
if (position == 1) {
buffer[1] = '}';
buffer[2] = '\0';
} else {
buffer[position-1] = '}';
}
PIPSOLARPublishRaw(subtopic, buffer); PIPSOLARPublishRaw(subtopic, buffer);
} }
@ -522,34 +677,44 @@ bool PIPSOLARSendCommand(PipSolar::CommandType cmd, const char *parameter, bool
case PipSolar::CommandType::NONE: case PipSolar::CommandType::NONE:
return false; return false;
case PipSolar::CommandType::QPIGS: case PipSolar::CommandType::QPIGS:
command = PSTR("QPIGS"); command = PSTR(D_CMND_PIP_QPIGS);
break; break;
case PipSolar::CommandType::QMOD: case PipSolar::CommandType::QMOD:
command = PSTR("QMOD"); command = PSTR(D_CMND_PIP_QMOD);
break; break;
case PipSolar::CommandType::QPIWS: case PipSolar::CommandType::QPIWS:
command = PSTR("QPIWS"); command = PSTR(D_CMND_PIP_QPIWS);
break; break;
case PipSolar::CommandType::QT: case PipSolar::CommandType::QT:
command = PSTR("QT"); command = PSTR(D_CMND_PIP_QT);
break; break;
case PipSolar::CommandType::QET: case PipSolar::CommandType::QET:
command = PSTR("QET"); command = PSTR(D_CMND_PIP_QET);
break; break;
case PipSolar::CommandType::QEY: case PipSolar::CommandType::QEY:
command = PSTR("QEY"); command = PSTR(D_CMND_PIP_QEY);
break; break;
case PipSolar::CommandType::QEM: case PipSolar::CommandType::QEM:
command = PSTR("QEM"); command = PSTR(D_CMND_PIP_QEM);
break; break;
case PipSolar::CommandType::QED: case PipSolar::CommandType::QED:
command = PSTR("QED"); command = PSTR(D_CMND_PIP_QED);
break; break;
case PipSolar::CommandType::QEH: case PipSolar::CommandType::QEH:
command = PSTR("QEH"); command = PSTR(D_CMND_PIP_QEH);
break; break;
case PipSolar::CommandType::DAT: case PipSolar::CommandType::DAT:
command = PSTR("DAT"); command = PSTR(D_CMND_PIP_DAT);
break;
case PipSolar::CommandType::QPIRI:
command = PSTR(D_CMND_PIP_QPIRI);
break;
case PipSolar::CommandType::QFLAG:
command = PSTR(D_CMND_PIP_QFLAG);
break;
case PipSolar::CommandType::CUSTOM:
command = parameter;
parameter = nullptr;
break; break;
} }
PIPSOLAR.commandType = cmd; PIPSOLAR.commandType = cmd;
@ -604,7 +769,35 @@ const char* PIPSOLARGetValueStringCopy(char *data, int8_t position, uint8_t cou
return PIPSOLARGetValueStringCopyString; return PIPSOLARGetValueStringCopyString;
} }
void PIPSOLARInterpret(struct PipSolar::ValueSetting *settings, uint8_t count) void PIPSOLARQFlagInterpret(const char *flag)
{
bool currentValue = true;
while(*flag != '\0') {
switch(*flag) {
case 'E':
currentValue = true;
break;
case 'D':
currentValue = false;
break;
default:
for(int i = 0; i < PIPSOLARqflagValueSettingsCount; ++i) {
if(PIPSOLARqflagValueSettings[i].identifier == *flag) {
if(currentValue == true) {
PIPSOLARqflagValueSettings[i].value = PipSolar::BoolFlag::True;
} else {
PIPSOLARqflagValueSettings[i].value = PipSolar::BoolFlag::False;
}
break;
}
}
break;
}
flag++;
}
}
void PIPSOLARInterpret(struct PipSolar::ValueSetting *settings, uint8_t count, bool json = false, const char *command = nullptr)
{ {
//(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: line %d"), __LINE__); //(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: line %d"), __LINE__);
for (uint8_t i = 0; i < count; ++i) for (uint8_t i = 0; i < count; ++i)
@ -618,7 +811,11 @@ void PIPSOLARInterpret(struct PipSolar::ValueSetting *settings, uint8_t count)
//AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: line %d %s %s"), __LINE__, setting.name, temp); //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: line %d %s %s"), __LINE__, setting.name, temp);
setting.value.intValue = atoi(temp); setting.value.intValue = atoi(temp);
if (setting.publish) if (setting.publish)
if (json) {
PIPSOLARPublish(command, setting.value.intValue, true, setting.name, setting.unit);
} else {
PIPSOLARPublish(setting.name, setting.value.intValue); PIPSOLARPublish(setting.name, setting.value.intValue);
}
break; break;
} }
case PipSolar::ValueSetting::Type::intTypeCopy: { case PipSolar::ValueSetting::Type::intTypeCopy: {
@ -626,7 +823,11 @@ void PIPSOLARInterpret(struct PipSolar::ValueSetting *settings, uint8_t count)
//AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: line %d %s %s"), __LINE__, setting.name, temp); //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: line %d %s %s"), __LINE__, setting.name, temp);
setting.value.intValue = atoi(temp); setting.value.intValue = atoi(temp);
if (setting.publish) if (setting.publish)
if (json) {
PIPSOLARPublish(command, setting.value.intValue, true, setting.name, setting.unit);
} else {
PIPSOLARPublish(setting.name, setting.value.intValue); PIPSOLARPublish(setting.name, setting.value.intValue);
}
break; break;
} }
case PipSolar::ValueSetting::Type::floatType: { case PipSolar::ValueSetting::Type::floatType: {
@ -634,7 +835,11 @@ void PIPSOLARInterpret(struct PipSolar::ValueSetting *settings, uint8_t count)
//AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: line %d %s %s"), __LINE__, setting.name, temp); //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: line %d %s %s"), __LINE__, setting.name, temp);
setting.value.floatValue = atof(temp); setting.value.floatValue = atof(temp);
if (setting.publish) if (setting.publish)
if (json) {
PIPSOLARPublish(command, setting.value.floatValue, true, setting.name, setting.unit);
} else {
PIPSOLARPublish(setting.name, setting.value.floatValue); PIPSOLARPublish(setting.name, setting.value.floatValue);
}
break; break;
} }
case PipSolar::ValueSetting::Type::floatTypeCopy: { case PipSolar::ValueSetting::Type::floatTypeCopy: {
@ -642,26 +847,42 @@ void PIPSOLARInterpret(struct PipSolar::ValueSetting *settings, uint8_t count)
//AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: line %d %s %s"), __LINE__, setting.name, temp); //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: line %d %s %s"), __LINE__, setting.name, temp);
setting.value.floatValue = atof(temp); setting.value.floatValue = atof(temp);
if (setting.publish) if (setting.publish)
if (json) {
PIPSOLARPublish(command, setting.value.floatValue, true, setting.name, setting.unit);
} else {
PIPSOLARPublish(setting.name, setting.value.floatValue); PIPSOLARPublish(setting.name, setting.value.floatValue);
}
break; break;
} }
case PipSolar::ValueSetting::Type::boolType: case PipSolar::ValueSetting::Type::boolType:
//AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: line %d"), __LINE__); //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: line %d"), __LINE__);
setting.value.boolValue = PIPSOLAR.receiveBuffer[setting.position] == '1'; setting.value.boolValue = PIPSOLAR.receiveBuffer[setting.position] == '1';
if (setting.publish) if (setting.publish)
if (json) {
PIPSOLARPublish(command, setting.value.boolValue, true, setting.name, setting.unit);
} else {
PIPSOLARPublish(setting.name, setting.value.boolValue); PIPSOLARPublish(setting.name, setting.value.boolValue);
}
break; break;
case PipSolar::ValueSetting::Type::charType: case PipSolar::ValueSetting::Type::charType:
//AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: line %d"), __LINE__); //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: line %d"), __LINE__);
setting.value.charValue = PIPSOLAR.receiveBuffer[setting.position]; setting.value.charValue = PIPSOLAR.receiveBuffer[setting.position];
if (setting.publish) if (setting.publish)
if (json) {
PIPSOLARPublish(command, setting.value.charValue, true, setting.name, setting.unit);
} else {
PIPSOLARPublish(setting.name, setting.value.charValue); PIPSOLARPublish(setting.name, setting.value.charValue);
}
break; break;
case PipSolar::ValueSetting::Type::stringType: case PipSolar::ValueSetting::Type::stringType:
const char* temp = PIPSOLARGetValueString((char*)PIPSOLAR.receiveBuffer, setting.position, setting.count); const char* temp = PIPSOLARGetValueString((char*)PIPSOLAR.receiveBuffer, setting.position, setting.count);
//AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: line %d"), __LINE__); //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: line %d"), __LINE__);
if (setting.publish) if (setting.publish)
if (json) {
PIPSOLARPublish(command, temp, true, setting.name, setting.unit);
} else {
PIPSOLARPublish(setting.name, temp); PIPSOLARPublish(setting.name, temp);
}
break; break;
} }
} }
@ -690,7 +911,7 @@ void PIPSOLARInterpret(void)
char buffer[8+3+1]; char buffer[8+3+1];
auto &deviceState1 = PIPSOLARqpigsValueSettings[16]; auto &deviceState1 = PIPSOLARqpigsValueSettings[16];
auto &deviceState2 = PIPSOLARqpigsValueSettings[20]; auto &deviceState2 = PIPSOLARqpigsValueSettings[20];
snprintf(buffer, sizeof(buffer), "%3s%8s" snprintf_P(buffer, sizeof(buffer), PSTR("%3s%8s")
, PIPSOLARGetValueString((char*)PIPSOLAR.receiveBuffer, deviceState2.position, deviceState2.count) , PIPSOLARGetValueString((char*)PIPSOLAR.receiveBuffer, deviceState2.position, deviceState2.count)
, PIPSOLARGetValueString((char*)PIPSOLAR.receiveBuffer, deviceState1.position, deviceState1.count)); , PIPSOLARGetValueString((char*)PIPSOLAR.receiveBuffer, deviceState1.position, deviceState1.count));
PIPSOLARPublish(PSTR("Device_state"), buffer); PIPSOLARPublish(PSTR("Device_state"), buffer);
@ -708,43 +929,62 @@ void PIPSOLARInterpret(void)
break; break;
case PipSolar::CommandType::QT: case PipSolar::CommandType::QT:
if (wasQuery) if (wasQuery)
PIPSOLARPublishResult(PSTR("QT"), PIPSOLARGetValueString((char*)PIPSOLAR.receiveBuffer, 1, 14)); PIPSOLARPublishResult(PSTR(D_CMND_PIP_QT), PIPSOLARGetValueString((char*)PIPSOLAR.receiveBuffer, 1, 14));
//AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: line %d"), __LINE__); //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: line %d"), __LINE__);
PIPSOLARInterpret(PIPSOLARqtValueSettings, PIPSOLARqtValueSettingsCount); PIPSOLARInterpret(PIPSOLARqtValueSettings, PIPSOLARqtValueSettingsCount);
PIPSOLARPublish(PSTR("Inverter_date_time"), PIPSOLARGetValueString((char*)PIPSOLAR.receiveBuffer, 1, 14)); PIPSOLARPublish(PSTR("Inverter_date_time"), PIPSOLARGetValueString((char*)PIPSOLAR.receiveBuffer, 1, 14));
break; break;
case PipSolar::CommandType::QET: case PipSolar::CommandType::QET:
if (wasQuery) if (wasQuery)
PIPSOLARPublishResult(PSTR("QET"), atoi(PIPSOLARGetValueString((char*)PIPSOLAR.receiveBuffer, 1, 8))); PIPSOLARPublishResult(PSTR(D_CMND_PIP_QET), atoi(PIPSOLARGetValueString((char*)PIPSOLAR.receiveBuffer, 1, 8)));
PIPSOLARInterpret(PIPSOLARqexValueSettings, PIPSOLARqexValueSettingsCount); PIPSOLARInterpret(PIPSOLARqexValueSettings, PIPSOLARqexValueSettingsCount);
break; break;
case PipSolar::CommandType::QEY: case PipSolar::CommandType::QEY:
if (wasQuery) if (wasQuery)
PIPSOLARPublishResult(PSTR("QEY"), atoi(PIPSOLARGetValueString((char*)PIPSOLAR.receiveBuffer, 1, 8)), PIPSOLAR.queryCommand.parameter); PIPSOLARPublishResult(PSTR(D_CMND_PIP_QEY), atoi(PIPSOLARGetValueString((char*)PIPSOLAR.receiveBuffer, 1, 8)), PIPSOLAR.queryCommand.parameter);
else else
PIPSOLARInterpret(PIPSOLARqexValueSettings, PIPSOLARqexValueSettingsCount); PIPSOLARInterpret(PIPSOLARqexValueSettings, PIPSOLARqexValueSettingsCount);
break; break;
case PipSolar::CommandType::QEM: case PipSolar::CommandType::QEM:
if (wasQuery) if (wasQuery)
PIPSOLARPublishResult(PSTR("QEM"), atoi(PIPSOLARGetValueString((char*)PIPSOLAR.receiveBuffer, 1, 8)), PIPSOLAR.queryCommand.parameter); PIPSOLARPublishResult(PSTR(D_CMND_PIP_QEM), atoi(PIPSOLARGetValueString((char*)PIPSOLAR.receiveBuffer, 1, 8)), PIPSOLAR.queryCommand.parameter);
else else
PIPSOLARInterpret(PIPSOLARqexValueSettings, PIPSOLARqexValueSettingsCount); PIPSOLARInterpret(PIPSOLARqexValueSettings, PIPSOLARqexValueSettingsCount);
break; break;
case PipSolar::CommandType::QED: case PipSolar::CommandType::QED:
if (wasQuery) if (wasQuery)
PIPSOLARPublishResult(PSTR("QED"), atoi(PIPSOLARGetValueString((char*)PIPSOLAR.receiveBuffer, 1, 8)), PIPSOLAR.queryCommand.parameter); PIPSOLARPublishResult(PSTR(D_CMND_PIP_QED), atoi(PIPSOLARGetValueString((char*)PIPSOLAR.receiveBuffer, 1, 8)), PIPSOLAR.queryCommand.parameter);
else else
PIPSOLARInterpret(PIPSOLARqexValueSettings, PIPSOLARqexValueSettingsCount); PIPSOLARInterpret(PIPSOLARqexValueSettings, PIPSOLARqexValueSettingsCount);
break; break;
case PipSolar::CommandType::QEH: case PipSolar::CommandType::QEH:
if (wasQuery) if (wasQuery)
PIPSOLARPublishResult(PSTR("QEH"), atoi(PIPSOLARGetValueString((char*)PIPSOLAR.receiveBuffer, 1, 8)), PIPSOLAR.queryCommand.parameter); PIPSOLARPublishResult(PSTR(D_CMND_PIP_QEH), atoi(PIPSOLARGetValueString((char*)PIPSOLAR.receiveBuffer, 1, 8)), PIPSOLAR.queryCommand.parameter);
else else
PIPSOLARInterpret(PIPSOLARqexValueSettings, PIPSOLARqexValueSettingsCount); PIPSOLARInterpret(PIPSOLARqexValueSettings, PIPSOLARqexValueSettingsCount);
break; break;
case PipSolar::CommandType::DAT: case PipSolar::CommandType::DAT:
if (wasQuery) if (wasQuery)
PIPSOLARPublishResult(PSTR("DAT"), PIPSOLARGetValueString((char*)PIPSOLAR.receiveBuffer, 1, 3), PIPSOLAR.queryCommand.parameter); PIPSOLARPublishResult(PSTR(D_CMND_PIP_DAT), PIPSOLARGetValueString((char*)PIPSOLAR.receiveBuffer, 1, 3), PIPSOLAR.queryCommand.parameter);
break;
case PipSolar::CommandType::QPIRI:
{
//AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: %s %d %d"), __FUNCTION__, __LINE__, PIPSOLAR.receiveBufferPosition);
if (PIPSOLAR.receiveBufferPosition != 100)
return;
//AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: %s %d"), __FUNCTION__, __LINE__);
const char qpiri[] = PSTR(D_CMND_PIP_QPIRI);
PIPSOLARInterpret(PIPSOLARqpiriValueSettings, PIPSOLARqpiriValueSettingsCount, true, qpiri);
break;
}
case PipSolar::CommandType::QFLAG:
//if (wasQuery)
PIPSOLARQFlagInterpret((char*)PIPSOLAR.receiveBuffer);
PIPSOLARQFlagPublish(PSTR(D_CMND_PIP_QFLAG));
break;
case PipSolar::CommandType::CUSTOM:
//if (wasQuery)
PIPSOLARPublishResult(PSTR(D_CMND_PIP_CUSTOM), (char*)PIPSOLAR.receiveBuffer, PIPSOLAR.queryCommand.parameter);
break; break;
} }
@ -772,6 +1012,8 @@ void PIPSOLARInput(void)
PIPSOLAR.maxCurrentErrorPoll = std::max(PIPSOLAR.maxCurrentErrorPoll, PIPSOLAR.currentErrorPoll); PIPSOLAR.maxCurrentErrorPoll = std::max(PIPSOLAR.maxCurrentErrorPoll, PIPSOLAR.currentErrorPoll);
++PIPSOLAR.errorPoll; ++PIPSOLAR.errorPoll;
PIPSOLAR.receiveBufferPosition = 0; // we are in trouble, but keep it going PIPSOLAR.receiveBufferPosition = 0; // we are in trouble, but keep it going
PIPSOLARPublish(PSTR("errortext"),PSTR("Buffer overflow"));
PIPSOLARPublish(PSTR("currentError"),PIPSOLAR.currentErrorPoll);
} }
} }
if (PIPSOLAR.receiveBufferPosition > 2 && PIPSOLAR.receiveBuffer[PIPSOLAR.receiveBufferPosition - 1] == '\r') if (PIPSOLAR.receiveBufferPosition > 2 && PIPSOLAR.receiveBuffer[PIPSOLAR.receiveBufferPosition - 1] == '\r')
@ -787,8 +1029,14 @@ void PIPSOLARInput(void)
PIPSOLAR.receiveBuffer[PIPSOLAR.receiveBufferPosition] = 0; // terminate string PIPSOLAR.receiveBuffer[PIPSOLAR.receiveBufferPosition] = 0; // terminate string
if (valid) if (valid)
{ {
PIPSOLAR.currentErrorPoll = 0;
++PIPSOLAR.successPoll; ++PIPSOLAR.successPoll;
if (PIPSOLAR.currentErrorPoll != 0 || (PIPSOLAR.successPoll % 100) == 0) {
PIPSOLAR.currentErrorPoll = 0;
PIPSOLARPublish(PSTR("errortext"),PSTR("Success"));
PIPSOLARPublish(PSTR("currentError"),PIPSOLAR.currentErrorPoll);
}
//AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: Received valid data \"%s\" timeout %d"), PIPSOLAR.receiveBuffer, PIPSOLAR.commandTimeoutCounter); //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: Received valid data \"%s\" timeout %d"), PIPSOLAR.receiveBuffer, PIPSOLAR.commandTimeoutCounter);
PIPSOLARInterpret(); PIPSOLARInterpret();
PIPSOLAR.commandState = PipSolar::CommandState::GotResponse; PIPSOLAR.commandState = PipSolar::CommandState::GotResponse;
@ -800,6 +1048,8 @@ void PIPSOLARInput(void)
PIPSOLAR.receiveBufferPosition = 0; PIPSOLAR.receiveBufferPosition = 0;
PIPSOLAR.commandState = PipSolar::CommandState::None; PIPSOLAR.commandState = PipSolar::CommandState::None;
PIPSOLAR.commandType = PipSolar::CommandType::NONE; PIPSOLAR.commandType = PipSolar::CommandType::NONE;
PIPSOLARPublish(PSTR("errortext"),PSTR("Crc error"));
PIPSOLARPublish(PSTR("currentError"),PIPSOLAR.currentErrorPoll);
} }
PIPSOLAR.commandTimeoutCounter = -1; PIPSOLAR.commandTimeoutCounter = -1;
} }
@ -816,6 +1066,8 @@ void PIPSOLARInput(void)
PIPSOLAR.commandType = PipSolar::CommandType::NONE; PIPSOLAR.commandType = PipSolar::CommandType::NONE;
PIPSOLAR.receiveBufferPosition = 0; PIPSOLAR.receiveBufferPosition = 0;
++PIPSOLAR.currentErrorPoll; ++PIPSOLAR.currentErrorPoll;
PIPSOLARPublish(PSTR("errortext"),PSTR("Timeout WaitForResponse"));
PIPSOLARPublish(PSTR("currentError"),PIPSOLAR.currentErrorPoll);
PIPSOLAR.maxCurrentErrorPoll = std::max(PIPSOLAR.maxCurrentErrorPoll, PIPSOLAR.currentErrorPoll); PIPSOLAR.maxCurrentErrorPoll = std::max(PIPSOLAR.maxCurrentErrorPoll, PIPSOLAR.currentErrorPoll);
++PIPSOLAR.errorPoll; ++PIPSOLAR.errorPoll;
PIPSOLARNextPolling(); PIPSOLARNextPolling();
@ -842,6 +1094,8 @@ void PIPSOLARNextPolling() {
switch(PIPSOLAR.queryCommand.commandType) { switch(PIPSOLAR.queryCommand.commandType) {
case PipSolar::CommandType::QT: case PipSolar::CommandType::QT:
case PipSolar::CommandType::QET: case PipSolar::CommandType::QET:
case PipSolar::CommandType::QPIRI:
case PipSolar::CommandType::QFLAG:
//AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: query without parameter")); //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: query without parameter"));
PIPSOLARSendCommand(PIPSOLAR.queryCommand.commandType); PIPSOLARSendCommand(PIPSOLAR.queryCommand.commandType);
PIPSOLAR.queryCommand.send = true; PIPSOLAR.queryCommand.send = true;
@ -851,6 +1105,7 @@ void PIPSOLARNextPolling() {
case PipSolar::CommandType::QED: case PipSolar::CommandType::QED:
case PipSolar::CommandType::QEH: case PipSolar::CommandType::QEH:
case PipSolar::CommandType::DAT: case PipSolar::CommandType::DAT:
case PipSolar::CommandType::CUSTOM:
//AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: query with parameter")); //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("PIPSOLAR: query with parameter"));
PIPSOLARSendCommand(PIPSOLAR.queryCommand.commandType, PIPSOLAR.queryCommand.parameter); PIPSOLARSendCommand(PIPSOLAR.queryCommand.commandType, PIPSOLAR.queryCommand.parameter);
PIPSOLAR.queryCommand.send = true; PIPSOLAR.queryCommand.send = true;
@ -953,10 +1208,10 @@ void PIPSOLARShowWeb(const PipSolar::ValueSetting &setting)
break; break;
case PipSolar::ValueSetting::Type::floatTypeCopy: case PipSolar::ValueSetting::Type::floatTypeCopy:
case PipSolar::ValueSetting::Type::floatType: case PipSolar::ValueSetting::Type::floatType:
WSContentSend_PD(PSTR("{s}%s{m}%f %s{e}"), setting.name, setting.value.floatValue, setting.unit); WSContentSend_PD(PSTR("{s}%s{m}%.1f %s{e}"), setting.name, setting.value.floatValue, setting.unit);
break; break;
case PipSolar::ValueSetting::Type::boolType: case PipSolar::ValueSetting::Type::boolType:
WSContentSend_PD(PSTR("{s}%s{m}%s %s{e}"), setting.name, (setting.value.boolValue ? "true" : "false"), setting.unit); WSContentSend_PD(PSTR("{s}%s{m}%s %s{e}"), setting.name, (setting.value.boolValue ? PSTR("true") : PSTR("false")), setting.unit);
break; break;
case PipSolar::ValueSetting::Type::charType: case PipSolar::ValueSetting::Type::charType:
WSContentSend_PD(PSTR("{s}%s{m}%c %s{e}"), setting.name, setting.value.charValue, setting.unit); WSContentSend_PD(PSTR("{s}%s{m}%c %s{e}"), setting.name, setting.value.charValue, setting.unit);