Skip to content

Commit

Permalink
Merge pull request #194 from IgorYbema/main
Browse files Browse the repository at this point in the history
Release of version v1.0
  • Loading branch information
Egyras authored Dec 22, 2020
2 parents ca96406 + 47b6ea6 commit 2d4c58f
Show file tree
Hide file tree
Showing 25 changed files with 1,739 additions and 939 deletions.
185 changes: 96 additions & 89 deletions HeishaMon/HeishaMon.ino

Large diffs are not rendered by default.

887 changes: 673 additions & 214 deletions HeishaMon/commands.cpp

Large diffs are not rendered by default.

163 changes: 112 additions & 51 deletions HeishaMon/commands.h
Original file line number Diff line number Diff line change
@@ -1,68 +1,129 @@
#include <ESP8266WiFi.h>

#include <ArduinoJson.h>

#define PANASONICQUERYSIZE 110
extern byte panasonicQuery[PANASONICQUERYSIZE];

#define OPTIONALPCBQUERYSIZE 19
#define OPTIONALPCBSAVETIME 300 //save each 5 minutes the current optional pcb state into flash to have valid values during reboot
extern byte optionalPCBQuery[OPTIONALPCBQUERYSIZE];
#define NUMBER_OF_OPTIONALPCB_TOPICS 13

static const char * optionalPcbTopics[] = {
"Heat_Cool_Mode",
"Compressor_State",
"SmartGrid_Mode",
"External_Thermostat_1_State",
"External_Thermostat_2_State",
"Demand_Control",
"Pool_Temp",
"Buffer_Temp",
"Z1_Room_Temp",
"Z1_Water_Temp",
"Z2_Room_Temp",
"Z2_Water_Temp",
"Solar_Temp"
};

static const byte optionalPcbBytes[] = {
6,
6,
6,
6,
6,
14,
7,
8,
10,
16,
11,
15,
13
};

extern const char* mqtt_topic_values;
extern const char* mqtt_topic_commands;
extern const char* mqtt_topic_pcbvalues;
extern const char* mqtt_topic_1wire;
extern const char* mqtt_topic_s0;
extern const char* mqtt_topic_pcb;
extern const char* mqtt_logtopic;
extern const char* mqtt_willtopic;
extern const char* mqtt_iptopic;
extern const char* mqtt_set_heatpump_state_topic;
extern const char* mqtt_set_quiet_mode_topic;
extern const char* mqtt_set_z1_heat_request_temperature_topic;
extern const char* mqtt_set_z1_cool_request_temperature_topic;
extern const char* mqtt_set_z2_heat_request_temperature_topic;
extern const char* mqtt_set_z2_cool_request_temperature_topic;
extern const char* mqtt_set_operationmode_topic;
extern const char* mqtt_set_force_DHW_topic;
extern const char* mqtt_set_force_defrost_topic;
extern const char* mqtt_set_force_sterilization_topic;
extern const char* mqtt_set_holiday_topic;
extern const char* mqtt_set_powerful_topic;
extern const char* mqtt_set_dhw_temp_topic;
extern const char* mqtt_send_raw_value_topic;
extern const char* mqtt_set_pump_topic;
extern const char* mqtt_set_pumpspeed_topic;

void send_heatpump_command(char* topic, char *msg,bool (*send_command)(byte*, int),void (*log_message)(char*));
void set_optionalpcb(char* topic, char *msg,void (*log_message)(char*));
unsigned int set_heatpump_state(char *msg, unsigned char *cmd, char *log_msg);
unsigned int set_pump(char *msg, unsigned char *cmd, char *log_msg);
unsigned int set_pump_speed(char *msg, unsigned char *cmd, char *log_msg);
unsigned int set_quiet_mode(char *msg, unsigned char *cmd, char *log_msg);
unsigned int set_z1_heat_request_temperature(char *msg, unsigned char *cmd, char *log_msg);
unsigned int set_z1_cool_request_temperature(char *msg, unsigned char *cmd, char *log_msg);
unsigned int set_z2_heat_request_temperature(char *msg, unsigned char *cmd, char *log_msg);
unsigned int set_z2_cool_request_temperature(char *msg, unsigned char *cmd, char *log_msg);
unsigned int set_force_DHW(char *msg, unsigned char *cmd, char *log_msg);
unsigned int set_force_defrost(char *msg, unsigned char *cmd, char *log_msg);
unsigned int set_force_sterilization(char *msg, unsigned char *cmd, char *log_msg);
unsigned int set_holiday_mode(char *msg, unsigned char *cmd, char *log_msg);
unsigned int set_powerful_mode(char *msg, unsigned char *cmd, char *log_msg);
unsigned int set_operation_mode(char *msg, unsigned char *cmd, char *log_msg);
unsigned int set_DHW_temp(char *msg, unsigned char *cmd, char *log_msg);
unsigned int set_curves(char *msg, unsigned char *cmd,char *log_msg);
unsigned int set_zones(char *msg, unsigned char *cmd,char *log_msg);
unsigned int set_floor_heat_delta(char *msg, unsigned char *cmd,char *log_msg);
unsigned int set_floor_cool_delta(char *msg, unsigned char *cmd,char *log_msg);
unsigned int set_dhw_heat_delta(char *msg, unsigned char *cmd,char *log_msg);


//optional pcb commands
unsigned int set_heat_cool_mode(char *msg, char *log_msg);
unsigned int set_compressor_state(char *msg, char *log_msg);
unsigned int set_smart_grid_mode(char *msg, char *log_msg);
unsigned int set_external_thermostat_1_state(char *msg, char *log_msg);
unsigned int set_external_thermostat_2_state(char *msg, char *log_msg);
unsigned int set_demand_control(char *msg, char *log_msg);
unsigned int set_pool_temp(char *msg, char *log_msg);
unsigned int set_buffer_temp(char *msg, char *log_msg);
unsigned int set_z1_room_temp(char *msg, char *log_msg);
unsigned int set_z1_water_temp(char *msg, char *log_msg);
unsigned int set_z2_room_temp(char *msg, char *log_msg);
unsigned int set_z2_water_temp(char *msg, char *log_msg);
unsigned int set_solar_temp(char *msg, char *log_msg);
unsigned int set_byte_9(char *msg, char *log_msg);




struct {
const char *name;
unsigned int (*func)(char *msg, unsigned char *cmd, char *log_msg);
} commands[] = {
// set heatpump state to on by sending 1
{ "SetHeatpump", set_heatpump_state },
// set pump state to on by sending 1
{ "SetPump", set_pump },
// set pump speed
{ "SetPumpSpeed", set_pump_speed },
// set 0 for Off mode, set 1 for Quiet mode 1, set 2 for Quiet mode 2, set 3 for Quiet mode 3
{ "SetQuietMode", set_quiet_mode },
// z1 heat request temp - set from -5 to 5 to get same temperature shift point or set direct temp
{ "SetZ1HeatRequestTemperature", set_z1_heat_request_temperature },
// z1 cool request temp - set from -5 to 5 to get same temperature shift point or set direct temp
{ "SetZ1CoolRequestTemperature", set_z1_cool_request_temperature },
// z2 heat request temp - set from -5 to 5 to get same temperature shift point or set direct temp
{ "SetZ2HeatRequestTemperature", set_z2_heat_request_temperature },
// z2 cool request temp - set from -5 to 5 to get same temperature shift point or set direct temp
{ "SetZ2CoolRequestTemperature", set_z2_cool_request_temperature },
// set mode to force DHW by sending 1
{ "SetForceDHW", set_force_DHW },
// set mode to force defrost by sending 1
{ "SetForceDefrost", set_force_defrost },
// set mode to force sterilization by sending 1
{ "SetForceSterilization", set_force_sterilization },
// set Holiday mode by sending 1, off will be 0
{ "SetHolidayMode", set_holiday_mode },
// set Powerful mode by sending 0 = off, 1 for 30min, 2 for 60min, 3 for 90 min
{ "SetPowerfulMode", set_powerful_mode },
// set Heat pump operation mode 3 = DHW only, 0 = heat only, 1 = cool only, 2 = Auto, 4 = Heat+DHW, 5 = Cool+DHW, 6 = Auto + DHW
{ "SetOperationMode", set_operation_mode },
// set DHW temperature by sending desired temperature between 40C-75C
{ "SetDHWTemp", set_DHW_temp },
// set heat/cool curves on z1 and z2 using a json input
{ "SetCurves", set_curves },
// set zones to active
{ "SetZones", set_zones },
{ "SetFloorHeatDelta", set_floor_heat_delta },
{ "SetFloorCoolDelta", set_floor_cool_delta },
{ "SetDHWHeatDelta", set_dhw_heat_delta },
};

struct {
const char *name;
unsigned int (*func)(char *msg, char *log_msg);
} optionalCommands[] = {
// optional PCB
{ "SetHeatCoolMode", set_heat_cool_mode },
{ "SetCompressorState", set_compressor_state },
{ "SetSmartGridMode", set_smart_grid_mode },
{ "SetExternalThermostat1State", set_external_thermostat_1_state },
{ "SetExternalThermostat2State", set_external_thermostat_2_state },
{ "SetDemandControl", set_demand_control },
{ "SetPoolTemp", set_pool_temp },
{ "SetBufferTemp", set_buffer_temp },
{ "SetZ1RoomTemp", set_z1_room_temp },
{ "SetZ1WaterTemp", set_z1_water_temp },
{ "SetZ2RoomTemp", set_z2_room_temp },
{ "SetZ2WaterTemp", set_z2_water_temp },
{ "SetSolarTemp", set_solar_temp },
{ "SetOptPCBByte9", set_byte_9 }
};

void send_heatpump_command(char* topic, char *msg, bool (*send_command)(byte*, int), void (*log_message)(char*), bool optionalPCB);
bool saveOptionalPCB(byte* command, int length);
bool loadOptionalPCB(byte* command, int length);
122 changes: 122 additions & 0 deletions HeishaMon/dallas.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
#include <OneWire.h>
#include <DallasTemperature.h>
#include <PubSubClient.h>
#include "commands.h"
#include "dallas.h"

#define MQTT_RETAIN_VALUES 1 // do we retain 1wire values?

#define MAXTEMPDIFFPERSEC 0.5 // what is the allowed temp difference per second which is allowed (to filter bad values)

#define DALLASASYNC 0 //async dallas yes or no (default no, because async seems to break 1wire sometimes with current code)

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature DS18B20(&oneWire);

//global array for 1wire data
dallasDataStruct* actDallasData = 0;
int dallasDevicecount = 0;


unsigned long nextalldatatime_dallas = 0;

unsigned long dallasTimer = 0;
unsigned int updateAllDallasTime = 30000; // will be set using heishmonSettings
unsigned int dallasTimerWait = 30000; // will be set using heishmonSettings

void initDallasSensors(void (*log_message)(char*), unsigned int updateAllDallasTimeSettings, unsigned int dallasTimerWaitSettings) {
char log_msg[256];
updateAllDallasTime = updateAllDallasTimeSettings;
dallasTimerWait = dallasTimerWaitSettings;
DS18B20.begin();
dallasDevicecount = DS18B20.getDeviceCount();
sprintf(log_msg, "Number of 1wire sensors on bus: %d", dallasDevicecount); log_message(log_msg);
if ( dallasDevicecount > MAX_DALLAS_SENSORS) {
dallasDevicecount = MAX_DALLAS_SENSORS;
sprintf(log_msg, "Reached max 1wire sensor count. Only %d sensors will provide data.", dallasDevicecount); log_message(log_msg);
}

//init array
actDallasData = new dallasDataStruct [dallasDevicecount];
for (int j = 0 ; j < dallasDevicecount; j++) {
DS18B20.getAddress(actDallasData[j].sensor, j);
}

DS18B20.requestTemperatures();
for (int i = 0 ; i < dallasDevicecount; i++) {
actDallasData[i].address[16] = '\0';
for (int x = 0; x < 8; x++) {
// zero pad the address if necessary
sprintf(&actDallasData[i].address[x * 2], "%02x", actDallasData[i].sensor[x]);
}
sprintf(log_msg, "Found 1wire sensor: %s", actDallasData[i].address ); log_message(log_msg);
}
if (DALLASASYNC) DS18B20.setWaitForConversion(false); //async 1wire during next loops
}

void readNewDallasTemp(PubSubClient &mqtt_client, void (*log_message)(char*), char* mqtt_topic_base) {
char log_msg[256];
char mqtt_topic[256];
char valueStr[20];
bool updatenow = false;

if (millis() > nextalldatatime_dallas) {
updatenow = true;
nextalldatatime_dallas = millis() + (1000 * updateAllDallasTime);
}
if (!(DALLASASYNC)) DS18B20.requestTemperatures();
for (int i = 0; i < dallasDevicecount; i++) {
float temp = DS18B20.getTempC(actDallasData[i].sensor);
if (temp < -120.0) {
sprintf(log_msg, "Error 1wire sensor offline: %s", actDallasData[i].address); log_message(log_msg);
} else {
float allowedtempdiff = (((millis() - actDallasData[i].lastgoodtime)) / 1000.0) * MAXTEMPDIFFPERSEC;
if ((actDallasData[i].temperature != -127.0) and ((temp > (actDallasData[i].temperature + allowedtempdiff)) or (temp < (actDallasData[i].temperature - allowedtempdiff)))) {
sprintf(log_msg, "Filtering 1wire sensor temperature (%s). Delta to high. Current: %.2f Last: %.2f", actDallasData[i].address, temp, actDallasData[i].temperature); log_message(log_msg);
} else {
actDallasData[i].lastgoodtime = millis();
if ((updatenow) || (actDallasData[i].temperature != temp )) { //only update mqtt topic if temp changed or after each update timer
actDallasData[i].temperature = temp;
sprintf(log_msg, "Received 1wire sensor temperature (%s): %.2f", actDallasData[i].address, actDallasData[i].temperature); log_message(log_msg);
sprintf(valueStr, "%.2f", actDallasData[i].temperature);
sprintf(mqtt_topic, "%s/%s/%s", mqtt_topic_base, mqtt_topic_1wire, actDallasData[i].address); mqtt_client.publish(mqtt_topic, valueStr, MQTT_RETAIN_VALUES);
}
}
}
}
}

void dallasLoop(PubSubClient &mqtt_client, void (*log_message)(char*), char* mqtt_topic_base) {
if ((DALLASASYNC) && (millis() > (dallasTimer - 1000))) {
DS18B20.requestTemperatures(); // get temperatures for next run 1 second before getting the temperatures (async)
}
if (millis() > dallasTimer) {
log_message((char*)"Requesting new 1wire temperatures");
dallasTimer = millis() + (1000 * dallasTimerWait);
readNewDallasTemp(mqtt_client, log_message, mqtt_topic_base);
}
}

String dallasJsonOutput() {
String output = "[";
for (int i = 0; i < dallasDevicecount; i++) {
output = output + "{";
output = output + "\"Sensor\": \"" + actDallasData[i].address + "\",";
output = output + "\"Temperature\": \"" + actDallasData[i].temperature + "\"";
output = output + "}";
if (i < dallasDevicecount - 1) output = output + ",";
}
output = output + "]";
return output;
}

String dallasTableOutput() {
String output = "";
for (int i = 0; i < dallasDevicecount; i++) {
output = output + "<tr>";
output = output + "<td>" + actDallasData[i].address + "</td>";
output = output + "<td>" + actDallasData[i].temperature + "</td>";
output = output + "</tr>";
}
return output;
}
18 changes: 18 additions & 0 deletions HeishaMon/dallas.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#include <PubSubClient.h>
#include <OneWire.h>
#include <DallasTemperature.h>

#define MAX_DALLAS_SENSORS 15
#define ONE_WIRE_BUS 4 // DS18B20 pin, for now a static config - should be in config menu later

struct dallasDataStruct {
float temperature = -127.0;
unsigned long lastgoodtime = 0;
DeviceAddress sensor;
char address[17];
};

void dallasLoop(PubSubClient &mqtt_client, void (*log_message)(char*), char* mqtt_topic_base);
void initDallasSensors(void (*log_message)(char*), unsigned int updataAllDallasTimeSettings, unsigned int dallasTimerWaitSettings);
String dallasJsonOutput(void);
String dallasTableOutput(void);
Loading

0 comments on commit 2d4c58f

Please sign in to comment.