Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

first poc for power set via mqtt #109

Closed
wants to merge 3 commits into from
Closed
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ tools/esp8266/binaries
*.db
*.suo
*.ipch
tools/esp8266/.vscode/extensions.json
36 changes: 30 additions & 6 deletions tools/esp8266/app.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ void app::setup(uint32_t timeout) {
if(0ULL != invSerial) {
iv = mSys->addInverter(name, invSerial, modPwr);
if(NULL != iv) {
DPRINTLN(DBG_INFO, F("add inverter: ") + String(name) + ", SN: " + String(invSerial, HEX));

mEep->read(ADDR_INV_PWR_LIM + (i * 2),&iv->powerLimit);
DPRINTLN(DBG_INFO, F("add inverter: ") + String(name) + ", SN: " + String(invSerial, HEX) + ", Power Limit: " + String(iv->powerLimit));
for(uint8_t j = 0; j < 4; j++) {
mEep->read(ADDR_INV_CH_NAME + (i * 4 * MAX_NAME_LENGTH) + j * MAX_NAME_LENGTH, iv->chName[j], MAX_NAME_LENGTH);
}
Expand Down Expand Up @@ -148,6 +148,7 @@ void app::setup(uint32_t timeout) {
mqttPort = 1883;

mMqtt.setup(mqttAddr, mqttTopic, mqttUser, mqttPwd, mqttPort);
mMqtt.mClient->setCallback(std::bind(&app::cbMqtt, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
mMqttTicker = 0;

mSerialTicker = 0;
Expand Down Expand Up @@ -229,7 +230,7 @@ void app::loop(void) {

if(0 != len) {
Inverter<> *iv = mSys->findInverter(&p->packet[1]);
if(NULL != iv) {
if(NULL != iv && p->packet[0] == 0x95) {
uint8_t *pid = &p->packet[9];
if((*pid & 0x7F) < 5) {
memcpy(mPayload[iv->id].data[(*pid & 0x7F) - 1], &p->packet[10], len-11);
Expand Down Expand Up @@ -349,8 +350,15 @@ void app::loop(void) {
yield();
if(mSerialDebug)
DPRINTLN(DBG_INFO, F("Requesting Inverter SN ") + String(iv->serial.u64, HEX));
mSys->Radio.sendTimePacket(iv->radioId.u64, mPayload[iv->id].ts);
mRxTicker = 0;
if(iv->powerLimitChange){
if(mSerialDebug)
DPRINTLN(DBG_INFO, F("Requesting Inverter to change power limit to ") + String(iv->powerLimit));
mSys->Radio.sendControlPacket(iv->radioId.u64, uint16_t(iv->powerLimit*10));
iv->powerLimitChange = false;
} else {
mSys->Radio.sendTimePacket(iv->radioId.u64, mPayload[iv->id].ts);
mRxTicker = 0;
}
}
}
else if(mSerialDebug)
Expand Down Expand Up @@ -600,6 +608,22 @@ void app::showErase() {
showReboot();
}

//-----------------------------------------------------------------------------
void app::cbMqtt(const char* topic, byte* payload, unsigned int length) {
DPRINTLN(DBG_INFO, F("app::cbMqtt"));
// DPRINTLN(DBG_INFO, topic);
// ToDo check topic !
int inverterId = 0; // ToDo get inverter id from topic
Inverter<> *iv = this->mSys->getInverterByPos(inverterId);
if(NULL != iv) {
iv->powerLimit = std::stoi((char*)payload);
iv->powerLimitChange = true;
mEep->write(ADDR_INV_PWR_LIM + inverterId * 2,iv->powerLimit);
DPRINTLN(DBG_INFO, F("Power limit for inverter ") + String(iv->id) + F(" set to ") + String(iv->powerLimit) + F("W") );
}
}



//-----------------------------------------------------------------------------
void app::showStatistics(void) {
Expand Down Expand Up @@ -690,7 +714,7 @@ void app::showLiveData(void) {
}

modHtml += F("<div class=\"iv\">"
"<div class=\"ch-iv\"><span class=\"head\">") + String(iv->name) + F("</span>");
"<div class=\"ch-iv\"><span class=\"head\">") + String(iv->name) + F(" Limit ") + String(iv->powerLimit) + F(" W</span>");
uint8_t list[] = {FLD_UAC, FLD_IAC, FLD_PAC, FLD_F, FLD_PCT, FLD_T, FLD_YT, FLD_YD, FLD_PDC, FLD_EFF};

for(uint8_t fld = 0; fld < 10; fld++) {
Expand Down
1 change: 1 addition & 0 deletions tools/esp8266/app.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ class app : public Main {
void setup(uint32_t timeout);
void loop(void);
void handleIntr(void);
void cbMqtt(const char* topic, byte* payload, unsigned int length);

uint8_t app_loops;
uint8_t getIrqPin(void) {
Expand Down
4 changes: 3 additions & 1 deletion tools/esp8266/defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ typedef struct {
#define INV_CH_CH_NAME_LEN MAX_NUM_INVERTERS * MAX_NAME_LENGTH * 4 // (4 channels)
#define INV_INTERVAL_LEN 2 // uint16_t
#define INV_MAX_RTRY_LEN 1 // uint8_t
#define INV_PWR_LIM_LEN MAX_NUM_INVERTERS * 2 // uint16_t

#define PINOUT_LEN 3 // 3 pins: CS, CE, IRQ

Expand Down Expand Up @@ -89,8 +90,9 @@ typedef struct {
#define ADDR_INV_CH_NAME ADDR_INV_CH_PWR + INV_CH_CH_PWR_LEN
#define ADDR_INV_INTERVAL ADDR_INV_CH_NAME + INV_CH_CH_NAME_LEN
#define ADDR_INV_MAX_RTRY ADDR_INV_INTERVAL + INV_INTERVAL_LEN
#define ADDR_INV_PWR_LIM ADDR_INV_MAX_RTRY + INV_MAX_RTRY_LEN

#define ADDR_MQTT_ADDR ADDR_INV_MAX_RTRY + INV_MAX_RTRY_LEN
#define ADDR_MQTT_ADDR ADDR_INV_PWR_LIM + INV_PWR_LIM_LEN
#define ADDR_MQTT_USER ADDR_MQTT_ADDR + MQTT_ADDR_LEN
#define ADDR_MQTT_PWD ADDR_MQTT_USER + MQTT_USER_LEN
#define ADDR_MQTT_TOPIC ADDR_MQTT_PWD + MQTT_PWD_LEN
Expand Down
4 changes: 4 additions & 0 deletions tools/esp8266/hmInverter.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ class Inverter {
uint8_t type; // integer which refers to inverter type
byteAssign_t* assign; // type of inverter
uint8_t listLen; // length of assignments
uint16_t powerLimit; // limit power output
bool powerLimitChange; // true if change needed
serial_u serial; // serial number as on barcode
serial_u radioId; // id converted to modbus
uint8_t channels; // number of PV channels (1-4)
Expand All @@ -79,6 +81,8 @@ class Inverter {

Inverter() {
ts = 0;
powerLimit = -1; // 65535 W Limit -> unlimited
powerLimitChange = false;
}

~Inverter() {
Expand Down
22 changes: 22 additions & 0 deletions tools/esp8266/hmRadio.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,28 @@ class HmRadio {
return mTxChLst[mTxChIdx];
}*/

void sendControlPacket(uint64_t invId, uint16_t data) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function name is not that optimal. We will have more ControlPackages in the future (ON/OFF/RESET/RESTART). This name should be dedicated for power limiting. In my fork i implemented already a function call for these: https://github.com/a-marcel/ahoy/blob/main/tools/esp8266/hmRadio.h#L221

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@a-marcel Thanks for the input. My intention was /is to be as close to the implementation as it is done on the original DTU. There is that kind of function call but of course, extended with the parameter 'subcmd' aka: on/off/reset/activepowercontro/reactivepowercontrol/powerfactor which all use the same main cmd "devcontrol"
But as stated before this merge request is closed due to missing code quality / functionality

DPRINTLN(DBG_VERBOSE, F("hmRadio.h:sendControlPacket"));
sendCmdPacket(invId, 0x51, 0x80, false);
mTxBuf[10] = 0x0b; // control type --> 0x0b => Type_ActivePowerContr
mTxBuf[11] = 0x00;
// 4 bytes control data
// Power Limit fix point 10 eg. 30 W --> 0d300 = 0x012c
mTxBuf[12] = (data >> 8) & 0xff; // 0x01
mTxBuf[13] = (data ) & 0xff; // 0x2c
//
mTxBuf[14] = 0x00;
mTxBuf[15] = 0x00;
// crc control data
uint16_t crc = crc16(&mTxBuf[10], 6);
mTxBuf[16] = (crc >> 8) & 0xff;
mTxBuf[17] = (crc ) & 0xff;
// crc over all
mTxBuf[18] = crc8(mTxBuf, 18);

sendPacket(invId, mTxBuf, 19, true);
}

void sendTimePacket(uint64_t invId, uint32_t ts) {
//DPRINTLN(DBG_VERBOSE, F("hmRadio.h:sendTimePacket"));
sendCmdPacket(invId, 0x15, 0x80, false);
Expand Down
16 changes: 11 additions & 5 deletions tools/esp8266/mqtt.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

class mqtt {
public:
PubSubClient *mClient;

mqtt() {
mClient = new PubSubClient(mEspClient);
mAddressSet = false;
Expand All @@ -35,6 +37,10 @@ class mqtt {
snprintf(mTopic, MQTT_TOPIC_LEN, "%s", topic);
}

void setCallback(void (*func)(const char* topic, byte* payload, unsigned int length)){
mClient->setCallback(func);
}

void sendMsg(const char *topic, const char *msg) {
//DPRINTLN(DBG_VERBOSE, F("mqtt.h:sendMsg"));
char top[64];
Expand Down Expand Up @@ -79,25 +85,25 @@ class mqtt {

void loop() {
//DPRINT(F("m"));
//if(!mClient->connected())
// reconnect();
if(!mClient->connected())
reconnect();
mClient->loop();
}

private:
void reconnect(void) {
//DPRINTLN(DBG_VERBOSE, F("mqtt.h:reconnect"));
DPRINTLN(DBG_INFO, F("mqtt.h:reconnect"));
if(!mClient->connected()) {
if((strlen(mUser) > 0) && (strlen(mPwd) > 0))
mClient->connect(DEF_DEVICE_NAME, mUser, mPwd);
else
mClient->connect(DEF_DEVICE_NAME);
}
mClient->subscribe("home/huette/powerset");
}

WiFiClient mEspClient;
PubSubClient *mClient;


bool mAddressSet;
uint16_t mPort;
char mUser[MQTT_USER_LEN];
Expand Down
1 change: 0 additions & 1 deletion tools/esp8266/platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ framework = arduino
board = nodemcuv2
monitor_speed = 115200
board_build.f_cpu = 80000000L
upload_port = /dev/ttyUSB0

lib_deps =
nrf24/[email protected]
Expand Down