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

Include support for HTTPS POST of data to HTTPS Server (e.g. emoncms.org for heatpumpmonitor.org) #2 #428

Open
wants to merge 16 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
20 changes: 19 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
![](doc/images/logo.png)


<hr/>

<p align="center">
Expand Down Expand Up @@ -27,6 +28,7 @@ _If this project has any value for you, please consider [buying me a 🍺](https
<li>Needs just an ESP32, no need for extra hardware. ESP8266 is also supported.</li>
<li>Queries the Altherma for selected values at defined interval.</li>
<li>Converts and formalizes all values in a JSON message sent over MQTT.</li>
<li>Converts and formalizes all values in a JSON message sent over HTTPS.</li>
<li>Easily integrates with Home Assistant's MQTT auto-discovery.</li>
<li>Supports update OverTheAir</li>
<li>Log messages in Serial + MQTT + Screen (m5StickC)</li>
Expand Down Expand Up @@ -64,6 +66,7 @@ If you are using an **ESP8266** select the `nodemcuv2` environement.

3. Edit the file `src/setup.h` as follows:
- enter your wifi and mqtt settings
- if you want to send via HTTPS, update the HTTPS section lower down the file
- select your RX TX GPIO pins connected to the X10A port. *The ESP32 has 3 serial ports. The first one, Serial0 is reserved for ESP<-USB->PC communication and ESP Altherma uses the Serial0 for logging (as any other project would do). So if you open the serial monitor on your PC, you'll see some debug from ESPAltherma. ESP32 can map any GPIO to the serial ports. Do NOT use the main Serial0 GPIOs RX0/TX0.* * The ESP8266 only has 1.5 Serial ports so it uses a software based serial driver. You can choose any pins, but some will stop you from being able to use the console*

For ESP32 try to stick to the RX2/TX2 of your board (probably GPIO16/GPIO17). **For M5StickC or M5StickCPlus, 26 and 36 will automatically be used if you selected the corresponding environment**. For ESP8266 pins 4 & 5 (D2 & D1 on the NodeMCUv2) are known to work well.
Expand Down Expand Up @@ -110,7 +113,9 @@ If you are using an **ESP8266** select the `nodemcuv2` environement.

A wiki page is available [here](https://github.com/raomin/ESPAltherma/wiki/Information-about-Values) where everyone can comment on the values and their definition.

5. You're ready to go! Connect your ESP32/ESP8266 and click -> Upload! Or press `F1` and select -> `PlatformIO: Upload`
5. Decide on what format of BOOLEAN data is required for the destination. The default is "ON" and "OFF", however in converters.h there is the option to change this to "1" and "0" if the destination for the data requires this, by defining (uncommenting) the #define BOOLNUM statement.

6. You're ready to go! Connect your ESP32/ESP8266 and click -> Upload! Or press `F1` and select -> `PlatformIO: Upload`

## Step 2: Connecting to the Heat pump

Expand Down Expand Up @@ -332,6 +337,19 @@ When put in terms of ESPAltherma variables, the COP can be define as a sensor li
{% else %} 0 {%endif%}"
```

# HTTPS - Emoncms / OpenEnergyMonitor / HeatPumpMonitor

## Background

As many Daikin owners and installers are keen to use this platform to send data directly to the https://heatpumpmonitor.org/ site by https://openenergymonitor.org/ the addition of the HTTPS messaging was added as a feature. This removes the need to have an instance of HomeAssistant to receive the MQTT and re-send as HTTP to emoncms, the engine behind heatpumpmonitor.

## Settings for Emoncms

- in converters.h, BOOLNUM needs to be defined - this means that rather than ON or OFF being sent, the data is 0 or 1 which is what EMONCMS is expecting
- in setup.h, HTTPS needs to be defined, as well as MQTT not being defined
- also in setup.h, ONETOPIC_ONEVAL should not be defined.
- APIKEY and NODE also need to be defined with your own values

# FAQ

## Great! I can now monitor my heat pump! Can I change the configuration values too?
Expand Down
18 changes: 18 additions & 0 deletions include/converters.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// convert read registry value to the expected format based on convID
#include <string.h>
char buff[64];
//#define BOOLNUM // If defined (not commented out), convertTable 200 and 300 return the on/off signal as "1" or "0" rather than the default "ON" or "OFF"

class Converter
{
public:
Expand Down Expand Up @@ -311,11 +313,19 @@ class Converter
b = (char)(b << tableID % 10);
if ((data[0] & b) > 0)
{
#ifdef BOOLNUM
strcat(ret, "1");
#elif
strcat(ret, "ON");
#endif
}
else
{
#ifdef BOOLNUM
strcat(ret, "0");
#elif
strcat(ret, "OFF");
#endif
}
return;
}
Expand Down Expand Up @@ -420,11 +430,19 @@ class Converter
{
if (data[0] == 0)
{
#ifdef BOOLNUM
strcat(ret, "0");
#elif
strcat(ret, "OFF");
#endif
}
else
{
#ifdef BOOLNUM
strcat(ret, "1");
#elif
strcat(ret, "ON");
#endif
}
}
// 201
Expand Down
96 changes: 96 additions & 0 deletions include/https.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#include <HttpClient.h>
#include <WiFiClientSecure.h>
#include "setup.h"
#ifdef ARDUINO_M5Stick_C_Plus2
#include <M5StickCPlus2.h>
#elif ARDUINO_M5Stick_C_Plus
#include <M5StickCPlus.h>
#elif ARDUINO_M5Stick_C
#include <M5StickC.h>
#endif

char jsonbuffhttps[MAX_MSG_SIZE] = "{\0";


void posthttps(char* httpsbuff)
{
String httpRequestData = "node=" + String(NODE) + "&data=" + String(httpsbuff) + "&apikey=" + APIKEY; //Build the Emoncms data string

static WiFiClientSecure client;
if (!client) {
client.setCACert(rootCACertificate);
}

// setup https
HTTPClient https;

if (https.begin(client, HTTP_SERVER)) {
Serial.print("[HTTPS] POST...\n");
#ifdef ARDUINO_M5Stick_C_Plus2
M5.Lcd.print("[HTTPS] POST...\n");
#endif
https.addHeader("Content-Type", "application/x-www-form-urlencoded");

// start connection and send HTTP header
int httpCode = https.POST(httpRequestData);
// httpCode will be negative on error
if (httpCode > 0) {
// HTTP header has been send and Server response header has been handled
Serial.printf("[HTTPS] POST... code: %d\n", httpCode);
#ifdef ARDUINO_M5Stick_C_Plus2
M5.Lcd.printf("[HTTPS] POST... code: %d\n", httpCode);
#endif
// file found at server
if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
// print server response payload
String payload = https.getString();
Serial.println(payload);
#ifdef ARDUINO_M5Stick_C_Plus2
M5.Lcd.println(payload);
#endif
}

}
else {
Serial.printf("[HTTPS] POST... failed, error: %s\n", https.errorToString(httpCode).c_str());
#ifdef ARDUINO_M5Stick_C_Plus2
M5.Lcd.printf("[HTTPS] POST... failed, error: %s\n", https.errorToString(httpCode).c_str());
#endif
}

https.end();
}
}


void sendValuesHTTPS()
{
Serial.printf("Sending values via HTTPS.\n");
#ifdef ARDUINO_M5Stick_C_Plus2
//Add Power values
// getBatteryVoltage returns battery voltage [mV] as an int16_t
float batteryVoltage = (float) M5.Power.getBatteryVoltage() / 1000; // convert to V as a float
snprintf(jsonbuffhttps + strlen(jsonbuffhttps),MAX_MSG_SIZE - strlen(jsonbuffhttps) , "\"%s\":\"%.3gV\",", "M5BatV", batteryVoltage);
#elif ARDUINO_M5Stick_C
//Add M5 APX values
snprintf(jsonbuffhttps + strlen(jsonbuffhttps),MAX_MSG_SIZE - strlen(jsonbuffhttps) , "\"%s\":\"%.3gV\",\"%s\":\"%gmA\",", "M5VIN", M5.Axp.GetVinVoltage(),"M5AmpIn", M5.Axp.GetVinCurrent());
snprintf(jsonbuffhttps + strlen(jsonbuffhttps),MAX_MSG_SIZE - strlen(jsonbuffhttps) , "\"%s\":\"%.3gV\",\"%s\":\"%gmA\",", "M5BatV", M5.Axp.GetBatVoltage(),"M5BatCur", M5.Axp.GetBatCurrent());
snprintf(jsonbuffhttps + strlen(jsonbuffhttps),MAX_MSG_SIZE - strlen(jsonbuffhttps) , "\"%s\":\"%.3gmW\",", "M5BatPwr", M5.Axp.GetBatPower());
#endif
snprintf(jsonbuffhttps + strlen(jsonbuffhttps),MAX_MSG_SIZE - strlen(jsonbuffhttps) , "\"%s\":\"%ddBm\",", "WifiRSSI", WiFi.RSSI());
snprintf(jsonbuffhttps + strlen(jsonbuffhttps),MAX_MSG_SIZE - strlen(jsonbuffhttps) , "\"%s\":\"%d\",", "FreeMem", ESP.getFreeHeap());
jsonbuffhttps[strlen(jsonbuffhttps) - 1] = '}';

posthttps(jsonbuffhttps);
#ifdef ARDUINO_M5Stick_C_Plus2
M5.Lcd.println(jsonbuffhttps); //Optional - prints the data to the screen if required
#endif

// wipes the jsonbuffhttps back to {null
strcpy(jsonbuffhttps, "{\0");

}




10 changes: 6 additions & 4 deletions include/mqtt.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@
#define EEPROM_CHK 1
#define EEPROM_STATE 0

#define MQTT_attr "espaltherma/ATTR"
#define MQTT_lwt "espaltherma/LWT"
// commented out duplicates
// #define MQTT_attr "espaltherma/ATTR"
// #define MQTT_lwt "espaltherma/LWT"


#ifdef JSONTABLE
char jsonbuff[MAX_MSG_SIZE] = "[{\0";
Expand All @@ -25,7 +27,7 @@ WiFiClient espClient;
#endif
PubSubClient client(espClient);

void sendValues()
void sendValuesMQTT()
{
Serial.printf("Sending values in MQTT.\n");
#ifdef ARDUINO_M5Stick_C_Plus2
Expand Down Expand Up @@ -251,4 +253,4 @@ void callback(char *topic, byte *payload, unsigned int length)
{
Serial.printf("Unknown topic: %s\n", topic);
}
}
}
2 changes: 1 addition & 1 deletion platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@


[platformio]
default_envs = esp32
default_envs = m5stickcplus2

[env:nodemcuv2]
platform = espressif8266
Expand Down
33 changes: 30 additions & 3 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@
#include "converters.h"
#include "comm.h"
#include "mqtt.h"
#ifdef HTTPS
#include "https.h"
#endif //HTTPS
#include "restart.h"

Converter converter;
Expand Down Expand Up @@ -74,11 +77,22 @@ void updateValues(char regID)

#else
if (alpha){

#ifdef MQTT
snprintf(jsonbuff + strlen(jsonbuff), MAX_MSG_SIZE - strlen(jsonbuff), "\"%s\":\"%s\",", labels[i]->label, labels[i]->asString);
#endif
#ifdef HTTPS
snprintf(jsonbuffhttps + strlen(jsonbuffhttps), MAX_MSG_SIZE - strlen(jsonbuffhttps), "\"%s\":\"%s\",", labels[i]->label, labels[i]->asString);
#endif //HTTPS

}
else{//number, no quotes
#ifdef MQTT
snprintf(jsonbuff + strlen(jsonbuff), MAX_MSG_SIZE - strlen(jsonbuff), "\"%s\":%s,", labels[i]->label, labels[i]->asString);
#endif
#ifdef HTTPS
snprintf(jsonbuffhttps + strlen(jsonbuffhttps), MAX_MSG_SIZE - strlen(jsonbuffhttps), "\"%s\":%s,", labels[i]->label, labels[i]->asString);
#endif //HTTPS

}
#endif
}
Expand Down Expand Up @@ -349,6 +363,7 @@ void setup()
espClient.setTimeout(5);
#endif

#ifdef MQTT
client.setBufferSize(MAX_MSG_SIZE); //to support large json message
client.setCallback(callback);
client.setServer(MQTT_SERVER, MQTT_PORT);
Expand All @@ -361,8 +376,10 @@ void setup()
reconnectMqtt();
mqttSerial.println("OK!");

initRegistries();
mqttSerial.print("ESPAltherma started!");
#endif //ifdef MQTT

initRegistries();
}

void waitLoop(uint ms){
Expand All @@ -380,10 +397,13 @@ void loop()
{ //restart board if needed
checkWifi();
}
#ifdef MQTT
if (!client.connected())
{ //(re)connect to MQTT if needed
reconnectMqtt();
}
#endif //ifdef MQTT

//Querying all registries
for (size_t i = 0; (i < 32) && registryIDs[i] != 0xFF; i++)
{
Expand All @@ -402,7 +422,14 @@ void loop()
//waitLoop(500);//wait .5sec between registries
}
}
sendValues();//Send the full json message
#ifdef MQTT
sendValuesMQTT();//Send the full json message
mqttSerial.printf("Done. Waiting %ld ms...", FREQUENCY - millis() + start);
#endif //MQTT
#ifdef HTTPS
sendValuesHTTPS();
Serial.print("sending values from HTTPS");
#endif // HTTPS
waitLoop(FREQUENCY - millis() + start);

}
53 changes: 53 additions & 0 deletions src/setup.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
#ifndef SETUP_H
#define SETUP_H

//Setup your credentials and mqtt info here:
//only change the value between the " " leave the rest of the line untouched.
#define WIFI_SSID "SSID"//**Your SSID here**
Expand All @@ -10,6 +13,8 @@
//#define WIFI_PRIMARY_DNS 8, 8, 8, 8 //A DNS address is needed, even if it's not used
//#define WIFI_SECONDARY_DNS 8, 8, 4, 4 //A DNS address is needed, even if it's not used

#define MQTT //We want to send MQTT messages to a MQTT Server (comment out if we don't)

#define MQTT_SERVER "192.168.1.4"//**IP address here of your MQTT server**
#define MQTT_USERNAME ""//leave empty if not set (bad!)
#define MQTT_PASSWORD ""//leave empty if not set (bad!)
Expand Down Expand Up @@ -130,3 +135,51 @@
#ifndef PROTOCOL
#define PROTOCOL 'I'
#endif

// HTTPS FUNCTIONS -------------------
// Uncomment the below 'define HTTPS' to send HTTPS Messages
//#define HTTPS
#if defined (HTTPS)
#define HTTP_SERVER "https://emoncms.org/input/post" //emoncms
#define APIKEY " " //emoncms
#define NODE "emontx" // node in emoncms

// root certificate of emoncms.org - expires 2038
#define rootCACertificate \
"-----BEGIN CERTIFICATE-----\n" \
"MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCB\n" \
"iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl\n" \
"cnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV\n" \
"BAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAw\n" \
"MjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNV\n" \
"BAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU\n" \
"aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2Vy\n" \
"dGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK\n" \
"AoICAQCAEmUXNg7D2wiz0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B\n" \
"3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2jY0K2dvKpOyuR+OJv0OwWIJAJPuLodMkY\n" \
"tJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFnRghRy4YUVD+8M/5+bJz/\n" \
"Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O+T23LLb2\n" \
"VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT\n" \
"79uq/nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6\n" \
"c0Plfg6lZrEpfDKEY1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmT\n" \
"Yo61Zs8liM2EuLE/pDkP2QKe6xJMlXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97l\n" \
"c6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8yexDJtC/QV9AqURE9JnnV4ee\n" \
"UB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+eLf8ZxXhyVeE\n" \
"Hg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd\n" \
"BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8G\n" \
"A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPF\n" \
"Up/L+M+ZBn8b2kMVn54CVVeWFPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KO\n" \
"VWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ7l8wXEskEVX/JJpuXior7gtNn3/3\n" \
"ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQEg9zKC7F4iRO/Fjs\n" \
"8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM8WcR\n" \
"iQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYze\n" \
"Sf7dNXGiFSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZ\n" \
"XHlKYC6SQK5MNyosycdiyA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/\n" \
"qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9cJ2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRB\n" \
"VXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGwsAvgnEzDHNb842m1R0aB\n" \
"L6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gxQ+6IHdfG\n" \
"jjxDah2nGN59PRbxYvnKkKj9\n" \
"-----END CERTIFICATE-----"
#endif //HTTPS

#endif //SETUP_H