From 8750bceead8888fa6194862c7e7610754a6c6a0f Mon Sep 17 00:00:00 2001 From: Chris Giacofei Date: Wed, 19 Jan 2022 16:30:26 -0500 Subject: [PATCH 1/5] Load config to EEPROM --- boil_kettle/boil_kettle.ino | 3 ++ boil_kettle/eeprom_init.h | 66 +++++++++++++++++++++++++++++++++++++ boil_kettle/mqtt.ino | 40 +++++++++++----------- 3 files changed, 89 insertions(+), 20 deletions(-) create mode 100644 boil_kettle/eeprom_init.h diff --git a/boil_kettle/boil_kettle.ino b/boil_kettle/boil_kettle.ino index 269a964..f27729f 100644 --- a/boil_kettle/boil_kettle.ino +++ b/boil_kettle/boil_kettle.ino @@ -2,6 +2,7 @@ #include #include #include +#include // Additoinal Libraries #include @@ -13,6 +14,7 @@ // My Includes #include "config.h" +#include "eeprom_init.h" #include "button.h" #include "slowPWM.h" @@ -70,6 +72,7 @@ LiquidScreen home_screen(KettleState_line, kettle_power_line); LiquidMenu menu(lcd); void setup() { + StoreEEPROM(); unsigned long lastRun = millis() - UpdateInterval; Serial.begin(9600); diff --git a/boil_kettle/eeprom_init.h b/boil_kettle/eeprom_init.h new file mode 100644 index 0000000..98aef3d --- /dev/null +++ b/boil_kettle/eeprom_init.h @@ -0,0 +1,66 @@ +#include + +const uint8_t CompileTimeP[] PROGMEM = __DATE__ " " __TIME__; +const size_t ConfAddress = sizeof(CompileTimeP); + +unsigned char b, e = -1, *p = (uint8_t*)CompileTimeP - 1; + +struct Vessel { + String name; + String setpoint; + String sensor; + double Rref; + double RNominal; +}; + +struct Topic { + String root; + Vessel mash; + Vessel boil; +}; + +struct Mqtt { + char broker[14]; + char user[10]; + char password[21]; + Topic topic; +}; + +struct ConfigData { + Mqtt mqtt; + int interval; + int period; + uint8_t threshold; + uint8_t hysteresis; +}; + +void StoreEEPROM() { + while( b = pgm_read_byte( ++p ) ){ + if( b != EEPROM[++e] ){ + + Vessel BoilKettle {"boil_kettle", BOIL_SETPOINT_TOPIC, BOIL_ACTUAL_TOPIC, RREF_KETTLE, RNOMINAL_KETTLE}; + Vessel MashTun {"mash_tun", MASH_SETPOINT_TOPIC, MASH_ACTUAL_TOPIC, RREF_MASH, RNOMINAL_MASH}; + Topic mqtt_topics {TOPIC_ROOT, MashTun, BoilKettle}; + Mqtt mqtt_data; + strcpy(mqtt_data.broker, MQTT_BROKER); + strcpy(mqtt_data.user, MQTT_USER); + strcpy(mqtt_data.password, MQTT_PASSWORD); + mqtt_data.topic = mqtt_topics; + + + ConfigData conf { + mqtt_data, + UpdateInterval, + PeriodPWM, + ThreshPWR, + Hysteresis + }; + + EEPROM.put(ConfAddress, conf); + Serial.println(conf.mqtt.broker); + + while( b = pgm_read_byte( p++ ) ) EEPROM[e++] = b; + break; + } + } +} diff --git a/boil_kettle/mqtt.ino b/boil_kettle/mqtt.ino index f3aeafd..354470b 100644 --- a/boil_kettle/mqtt.ino +++ b/boil_kettle/mqtt.ino @@ -1,6 +1,12 @@ void ConnectMQTT() { - static const char *password = MQTT_PASSWORD; - static const char *user = MQTT_USER; + ConfigData config; + EEPROM.get(ConfAddress, config); + + static const char *user = config.mqtt.user; + static const char *password = config.mqtt.password; + //config.mqtt.topic.root + //config.mqtt.broker + Serial.println("connecting MQTT..."); while (!mqtt_client.connect("brewhouse", user, password)) { Serial.print("."); @@ -8,11 +14,14 @@ void ConnectMQTT() { } Serial.println("\nconnected!"); - mqtt_client.subscribe("brewery/setpoint/bk"); + + mqtt_client.subscribe(config.mqtt.topic.root + config.mqtt.topic.boil.setpoint); + mqtt_client.subscribe(config.mqtt.topic.root + config.mqtt.topic.mash.setpoint); } void MessageReceived(String &topic, String &payload) { - Serial.println("incoming: " + topic + " - " + payload); + ConfigData config; + EEPROM.get(ConfAddress, config); /** JSON Parser Setup */ StaticJsonDocument<200> doc; @@ -22,29 +31,20 @@ void MessageReceived(String &topic, String &payload) { // Test if parsing succeeds. if (error) { - Serial.print(F("deserializeJson() failed: ")); Serial.println(error.f_str()); return; } - char buf[30]; - strcpy(buf,TOPIC_PREFIX); - strcat(buf,BOIL_SETPOINT_TOPIC); - if (topic == buf) { + + if (topic == config.mqtt.topic.root + config.mqtt.topic.boil.setpoint) { // Update PWM setpoint. - String name = doc["entity"]; String setting = doc["setpoint"]; - KettleDuty = setting.toInt(); - String unit = doc["units"]; - - Serial.println("Updating setpoint for " + name + " to " + setting + " " + unit); } } void SetupMQTT(const char *broker) { // Note: Local domain names (e.g. "Computer.local" on OSX) are not supported // by Arduino. You need to set the IP address directly. - Serial.println("Setup MQTT client."); mqtt_client.begin(broker, net); mqtt_client.onMessage(MessageReceived); @@ -52,20 +52,20 @@ void SetupMQTT(const char *broker) { } static void SendSensorData() { - Serial.println("Sending data..."); - + ConfigData config; + EEPROM.get(ConfAddress, config); // NOTE: max message length is 250 bytes. StaticJsonDocument<200> doc; - doc["entity"] = "boil_kettle"; + doc["entity"] = config.mqtt.topic.boil.name; doc["setpoint"] = KettleDuty; doc["units"] = "%"; String jstr; serializeJson(doc, jstr); - String topic = TOPIC_PREFIX; - topic += "sensor/boil_kettle"; + String topic = config.mqtt.topic.root; + topic += config.mqtt.topic.boil.sensor; mqtt_client.publish(topic, jstr); From 421a0c6580227965a334a2a0f32861cbd23ee76b Mon Sep 17 00:00:00 2001 From: Chris Giacofei Date: Thu, 20 Jan 2022 08:40:32 -0500 Subject: [PATCH 2/5] Change libraries used for mqtt and json parsing. Not using strings for data any more. --- boil_kettle/boil_kettle.ino | 10 +++-- boil_kettle/mqtt.ino | 80 +++++++++++++++---------------------- 2 files changed, 39 insertions(+), 51 deletions(-) diff --git a/boil_kettle/boil_kettle.ino b/boil_kettle/boil_kettle.ino index 269a964..e50261a 100644 --- a/boil_kettle/boil_kettle.ino +++ b/boil_kettle/boil_kettle.ino @@ -4,8 +4,8 @@ #include // Additoinal Libraries -#include -#include +#include +#include #include #include // LiquidMenu_config.h needs to be modified to use I2C. #include @@ -26,8 +26,10 @@ slowPWM boilPWM; MD_REncoder rotary = MD_REncoder(encoderDT, encoderCLK); LiquidCrystal_I2C lcd(0x27,20,4); +void MessageReceived(char*, byte*, unsigned int); + EthernetClient net; -MQTTClient mqtt_client; +PubSubClient mqtt_client(MQTT_BROKER, 1883, MessageReceived, net); unsigned long lastRun = 0; @@ -87,7 +89,7 @@ void setup() { // if you get a connection, report back via serial: if (Ethernet.linkStatus() == LinkON) { - SetupMQTT(MQTT_BROKER); + ConnectMQTT(); } else { // if you didn't get a connection to the server: Serial.println("connection failed"); diff --git a/boil_kettle/mqtt.ino b/boil_kettle/mqtt.ino index f3aeafd..1f195a0 100644 --- a/boil_kettle/mqtt.ino +++ b/boil_kettle/mqtt.ino @@ -1,72 +1,58 @@ void ConnectMQTT() { static const char *password = MQTT_PASSWORD; static const char *user = MQTT_USER; - Serial.println("connecting MQTT..."); while (!mqtt_client.connect("brewhouse", user, password)) { Serial.print("."); delay(1000); } - Serial.println("\nconnected!"); - mqtt_client.subscribe("brewery/setpoint/bk"); + char topic[30]; + strcpy(topic,TOPIC_ROOT); + strcat(topic,BOIL_SETPOINT_TOPIC); + mqtt_client.subscribe(topic); } -void MessageReceived(String &topic, String &payload) { - Serial.println("incoming: " + topic + " - " + payload); - - /** JSON Parser Setup */ - StaticJsonDocument<200> doc; - - // Deserialize the JSON document - DeserializationError error = deserializeJson(doc, payload); - - // Test if parsing succeeds. - if (error) { - Serial.print(F("deserializeJson() failed: ")); - Serial.println(error.f_str()); - return; - } +void MessageReceived(char* topic, byte* payload, unsigned int length) { char buf[30]; - strcpy(buf,TOPIC_PREFIX); + strcpy(buf,TOPIC_ROOT); strcat(buf,BOIL_SETPOINT_TOPIC); - if (topic == buf) { - // Update PWM setpoint. - String name = doc["entity"]; - String setting = doc["setpoint"]; - KettleDuty = setting.toInt(); - String unit = doc["units"]; + char msg[length+1]; - Serial.println("Updating setpoint for " + name + " to " + setting + " " + unit); + for (int i=0;ivalueint; + } } static void SendSensorData() { - Serial.println("Sending data..."); - // NOTE: max message length is 250 bytes. - StaticJsonDocument<200> doc; + char *string = NULL; + cJSON *entity = NULL; + cJSON *setpoint = NULL; + cJSON *units = NULL; - doc["entity"] = "boil_kettle"; - doc["setpoint"] = KettleDuty; - doc["units"] = "%"; + cJSON *monitor = cJSON_CreateObject(); + cJSON_AddStringToObject(monitor, "entity", "boil_kettle"); + cJSON_AddNumberToObject(monitor, "setpoint", KettleDuty); + cJSON_AddStringToObject(monitor, "units", "%"); + char *msg = cJSON_Print(monitor); - String jstr; - serializeJson(doc, jstr); + char topic[30]; + strcpy(topic,TOPIC_ROOT); + strcat(topic,BOIL_ACTUAL_TOPIC); - String topic = TOPIC_PREFIX; - topic += "sensor/boil_kettle"; - - mqtt_client.publish(topic, jstr); + mqtt_client.publish(topic, msg); } From 2673fa7fa391fe5f4c1bf8f414c2de6b1e854241 Mon Sep 17 00:00:00 2001 From: Chris Giacofei Date: Thu, 20 Jan 2022 09:53:25 -0500 Subject: [PATCH 3/5] Use a separate sketch to load EEPROM. --- boil_kettle/boil_kettle.ino | 2 -- {boil_kettle => eeprom_setup}/eeprom_init.h | 36 ++------------------- 2 files changed, 2 insertions(+), 36 deletions(-) rename {boil_kettle => eeprom_setup}/eeprom_init.h (70%) diff --git a/boil_kettle/boil_kettle.ino b/boil_kettle/boil_kettle.ino index b26ea8b..0d39800 100644 --- a/boil_kettle/boil_kettle.ino +++ b/boil_kettle/boil_kettle.ino @@ -14,7 +14,6 @@ // My Includes #include "config.h" -#include "eeprom_init.h" #include "button.h" #include "slowPWM.h" @@ -74,7 +73,6 @@ LiquidScreen home_screen(KettleState_line, kettle_power_line); LiquidMenu menu(lcd); void setup() { - StoreEEPROM(); unsigned long lastRun = millis() - UpdateInterval; Serial.begin(9600); diff --git a/boil_kettle/eeprom_init.h b/eeprom_setup/eeprom_init.h similarity index 70% rename from boil_kettle/eeprom_init.h rename to eeprom_setup/eeprom_init.h index 75b09e5..a699228 100644 --- a/boil_kettle/eeprom_init.h +++ b/eeprom_setup/eeprom_init.h @@ -1,40 +1,8 @@ #include - -const uint8_t CompileTimeP[] PROGMEM = __DATE__ " " __TIME__; -const size_t ConfAddress = sizeof(CompileTimeP); - -unsigned char b, e = -1, *p = (uint8_t*)CompileTimeP - 1; - -struct Vessel { - char name[16]; - char setpoint[20]; - char sensor[20]; - double Rref; - double RNominal; -}; - -struct Topic { - char root[10]; - Vessel mash; - Vessel boil; -}; - -struct Mqtt { - IPAddress broker; - char user[10]; - char password[21]; - Topic topic; -}; - -struct ConfigData { - Mqtt mqtt; - int interval; - int period; - uint8_t threshold; - uint8_t hysteresis; -}; +#include "config.h" void StoreEEPROM() { + unsigned char b, e = -1, *p = (uint8_t*)CompileTimeP - 1; while( b = pgm_read_byte( ++p ) ){ if( b != EEPROM[++e] ){ From 9818e77866eb645a37ecdeef6ff10f2ba8ed8d82 Mon Sep 17 00:00:00 2001 From: Chris Giacofei Date: Thu, 20 Jan 2022 10:02:55 -0500 Subject: [PATCH 4/5] Ignore stuff. --- eeprom_setup/.gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 eeprom_setup/.gitignore diff --git a/eeprom_setup/.gitignore b/eeprom_setup/.gitignore new file mode 100644 index 0000000..299bb98 --- /dev/null +++ b/eeprom_setup/.gitignore @@ -0,0 +1 @@ +config.h \ No newline at end of file From 24b3cdae1caa35c6f586e39a9d5e6f39c724a212 Mon Sep 17 00:00:00 2001 From: Chris Giacofei Date: Thu, 20 Jan 2022 10:21:55 -0500 Subject: [PATCH 5/5] Cleanup --- boil_kettle/mqtt.ino | 2 ++ 1 file changed, 2 insertions(+) diff --git a/boil_kettle/mqtt.ino b/boil_kettle/mqtt.ino index 68a8bf1..66e94ba 100644 --- a/boil_kettle/mqtt.ino +++ b/boil_kettle/mqtt.ino @@ -46,6 +46,7 @@ void MessageReceived(char* topic, byte* payload, unsigned int length) { // Update PWM setpoint. setting = cJSON_GetObjectItemCaseSensitive(monitor_json, "setpoint"); KettleDuty = setting->valueint; + cJSON_Delete(monitor_json); } } @@ -70,5 +71,6 @@ static void SendSensorData() { mqtt_client.publish(topic, msg); + cJSON_Delete(monitor); }