diff --git a/.gitignore b/.gitignore index e9e2ef2..c23d77e 100755 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ .DS_Store -bin/*/ +bin/* *build-* *build* *~ diff --git a/MakefileGlobal.mk b/MakefileGlobal.mk index 5de1361..64ab427 100644 --- a/MakefileGlobal.mk +++ b/MakefileGlobal.mk @@ -73,4 +73,4 @@ $(TARGET_DIR)/$(BIN): $(SRC) $(HDRS) $(BIN_DIR)/$(BIN): $(TARGET_DIR)/$(BIN) @ echo "$(BIN) $(BIN_DIR)/" - @ mv $(TARGET_DIR)/$(BIN) $(BIN_DIR)/ + @ cp $(TARGET_DIR)/$(BIN) $(BIN_DIR)/ diff --git a/bin/FermController.ino.bin b/bin/FermController.ino.bin deleted file mode 100644 index 9557f2b..0000000 Binary files a/bin/FermController.ino.bin and /dev/null differ diff --git a/lib/Device/Device.cpp b/lib/Device/Device.cpp deleted file mode 100644 index ea0008e..0000000 --- a/lib/Device/Device.cpp +++ /dev/null @@ -1,358 +0,0 @@ - -#include "Device.h" - -Device::Device(const uint8_t _pin_cool, const uint8_t _pin_heat, const uint8_t _pin_wire) { - this->_pin_cool = _pin_cool; - this->_pin_heat = _pin_heat; - this->_pin_wire = _pin_wire; -} - -void Device::CoolSet(bool set_state) { - // Set pin state - if (set_state) { - Serial.println("Starting cooling."); - strcpy(_curr_action, ACTION_COOLING); - SendState(ACTION_TPC, _curr_action); - digitalWrite(_pin_heat, LOW); // Just to be sure. - digitalWrite(_pin_cool, HIGH); - } else { - Serial.println("Stopping cooling."); - strcpy(_curr_action, ACTION_IDLE); - SendState(ACTION_TPC, _curr_action); - digitalWrite(_pin_cool, LOW); - digitalWrite(_pin_heat, LOW); - } -} - -void Device::HeatSet(bool set_state) { - if (set_state) { - Serial.println("Starting heat."); - strcpy(_curr_action, ACTION_HEATING); - SendState(ACTION_TPC, _curr_action); - digitalWrite(_pin_cool, LOW); // Just to be sure. - digitalWrite(_pin_heat, HIGH); - } else { - Serial.println("Stopping heat."); - strcpy(_curr_action, ACTION_IDLE); - SendState(ACTION_TPC, _curr_action); - digitalWrite(_pin_cool, LOW); - digitalWrite(_pin_heat, LOW); - } -} - -void Device::Hyst(float new_value){ - _hyst = new_value; -} - -float Device::Hyst(){ - return _hyst; -} - -void Device::Update(){ - float currentMillis = millis(); - - //Read temp sensor. - if (currentMillis - _lastSensor >= _sensor_period) { - //Read temperature from DS18b20 - float tempC = _sensors.getTempC(_ds_serial); - if (tempC == DEVICE_DISCONNECTED_C) { - Serial.println("Error: Could not read temperature data"); - } else { - _curr_temp = DallasTemperature::toFahrenheit(tempC); - } - } - - // Some helpful variables. - bool heating = _curr_action==ACTION_HEATING; - bool cooling = _curr_action==ACTION_COOLING; - bool running = (heating || cooling); - - // Adjust cool/heat on or off - if (_mode == "cool"){ - if (_curr_temp > _temp + _hyst && !cooling) { - CoolSet(true); - } else if (_curr_temp <= _temp && cooling) { - CoolSet(false); - } - } else if (_mode == "heat"){ - if (_curr_temp < _temp - _hyst && !heating) { - HeatSet(true); - } else if (_curr_temp >= _temp && heating) { - HeatSet(false); - } - } else if (_mode == "auto"){ - if ((_curr_temp < _temp_lo - _hyst) && !heating) { - HeatSet(true); - } else if ((_curr_temp > _temp_hi + _hyst) && !cooling) { - CoolSet(true); - } else if (running && (_curr_temp >= _temp_lo) && (_curr_temp <= _temp_hi)) { - if (heating) HeatSet(false); - if (cooling) CoolSet(false); - } - } else { - // IS OFF - if (heating) HeatSet(false); - if (cooling) CoolSet(false); - } - - //Send Data to broker - if (currentMillis - _lastSend >= _send_period) { - // Time's up, send data - char temp[7]; - dtostrf(_curr_temp, 6, 2, temp); - SendState(TEMP_CURRENT, temp); - _lastSend = currentMillis; - } - - _mqtt_client.loop(); -} - -void Device::AttachNet(WiFiClient &network) { - this->_net = network; - this->_mqtt_client.setClient(_net); - this->_mqtt_client.setBufferSize(DOC_SIZE); -} - -void Device::AttachSensor(DallasTemperature &sensors, uint8_t serial[8]){ - _sensors = sensors; - _ds_serial = serial; -} - -//void Device::topicRoot(const String &root) { _device_prefix = root; } -//byte* Device::topicRoot() { return _device_prefix; } - -void Device::SendConfig(char* broker, char* name, String &chipid, bool multimode) { - String name_slug = slugify(name); - String CMD_TPL = "{{ value }}"; - String STAT_TPL = "{{ value_json }}"; - - _topic_root = ROOT + name_slug; - - String _config_topic = CONFIG_ROOT + name_slug + "_" + chipid + "/config"; - - StaticJsonDocument payload_doc; - payload_doc["uniq_id"] = chipid + "_" + name_slug; - payload_doc["name"] = name; - payload_doc["temp_unit"] = "F"; - payload_doc["max_temp"] = _max_temp; - payload_doc["min_temp"] = _min_temp; - payload_doc["initial"] = _init_temp; - - // Action Topic - payload_doc["action_topic"] = _topic_root + ACTION_TPC; - payload_doc["action_template"] = STAT_TPL; - - // Mode setup - payload_doc["mode_cmd_t"] = _topic_root + MODE_SET; - payload_doc["mode_cmd_tpl"] = CMD_TPL; - payload_doc["mode_stat_t"] = _topic_root + MODE_STATE; - payload_doc["mode_stat_tpl"] = STAT_TPL; - - JsonArray modes = payload_doc.createNestedArray("modes"); - modes.add("off"); - modes.add("cool"); - - payload_doc["temp_cmd_t"] = _topic_root + TEMP_SET; - payload_doc["temp_cmd_tpl"] = CMD_TPL; - payload_doc["temp_stat_t"] = _topic_root + TEMP_STATE; - payload_doc["temp_stat_tpl"] = STAT_TPL; - - payload_doc["curr_temp_t"] = _topic_root + TEMP_CURRENT; - payload_doc["curr_temp_tpl"] = CMD_TPL; - - if (multimode) { - payload_doc["temp_hi_cmd_t"] = _topic_root + TEMP_HI_SET; - payload_doc["temp_hi_cmd_tpl"] = CMD_TPL; - payload_doc["temp_hi_stat_t"] = _topic_root + TEMP_HI_STATE; - payload_doc["temp_hi_stat_tpl"] = STAT_TPL; - - payload_doc["temp_lo_cmd_t"] = _topic_root + TEMP_LO_SET; - payload_doc["temp_lo_cmd_tpl"] = CMD_TPL; - payload_doc["temp_lo_stat_t"] = _topic_root + TEMP_LO_STATE; - payload_doc["temp_lo_stat_tpl"] = STAT_TPL; - - modes.add("heat"); - modes.add("auto"); - } - - // Attach Device - JsonObject dev = payload_doc.createNestedObject("dev"); - dev["name"] = DEVICE_NAME; - dev["mdl"] = DEVICE_MDL; - dev["sw"] = String(version); - dev["mf"] = DEVICE_MF; - JsonArray ids = dev.createNestedArray("ids"); - ids.add(chipid); - - String payload; - serializeJson(payload_doc, payload); - - - bool response = ConnectMQTT(broker, MQTT_NAME, MQTT_USER, MQTT_PASSWORD); - if (response) { - _mqtt_client.publish(_config_topic.c_str(), payload.c_str(), MSG_RETAIN); - _mqtt_client.loop(); - } - - _mqtt_client.subscribe((_topic_root + MODE_SET).c_str()); - _mqtt_client.subscribe((_topic_root + TEMP_SET).c_str()); - if (multimode) { - _mqtt_client.subscribe((_topic_root + TEMP_HI_SET).c_str()); - _mqtt_client.subscribe((_topic_root + TEMP_LO_SET).c_str()); - } - - _mqtt_client.loop(); -} - -void Device::_Temp(byte value){ - Serial.print("Set Temp"); - _temp = value; - SendState(TEMP_STATE, (char*)value); -} -void Device::_Mode(char* value){ - Serial.print("Set Mode"); - strcpy(_mode, value); - SendState(MODE_STATE, (char*)value); -} -void Device::_TempHi(byte value){ - Serial.print("Set High Temp"); - _temp_hi = value; - SendState(TEMP_HI_STATE, (char*)value); -} -void Device::_TempLo(byte value){ - Serial.print("Set Low Temp"); - _temp_lo = value; - SendState(TEMP_LO_STATE, (char*)value); -} - -void Device::SendState(String suffix, String payload){ - String topic = _topic_root + suffix; - - _mqtt_client.publish(topic.c_str(), payload.c_str(), MSG_RETAIN); -} - -/** Callback function for MQTT client. - Looks up a command function based on topic and executes it. - - @param topic - @param payload - @param length -*/ -void Device::_mqttCallback(char *topic, uint8_t *payload, unsigned int length) { - char data [16] = {'\0'}; - - // Remove root from the incoming topic. - char suffix[100] = topic[_topic_root.length()]; - Serial.print("Incoming topic -> "); - Serial.print(suffix); - Serial.print(": "); - int i; - - for (i; i < length; i++) - { - data[i] = ((char)payload[i]); - Serial.print(data[i]); - } - data[i] = '\0'; - - switch (suffix) { - - case MODE_SET: - _Mode(data); - break; - - case TEMP_SET: - _Temp(atoi(data)); - break; - - case TEMP_LO_SET: - _TempLo(atoi(data)); - break; - - case TEMP_HI_SET: - _TempHi(atoi(data)); - break; - - default: - Serial.println("Command function not found for " + String(topic)); - } - -} - -/** Connect to MQTT broker. - - @param server IP address string of the server. - @param name the name used for this connection - @param user MQTT broker username - @param password MQTT broker password - @return boolean indicating success or failure of connection. -*/ -bool Device::ConnectMQTT(const String &server, const String &name, const String &user, const String &password) { - - _mqtt_client.setServer((server.c_str(), 1883); - _mqtt_client.setCallback(&Device::_mqttCallback); - - byte i = 0; - - if (_mqtt_client.connected()) return true; - - while (!_mqtt_client.connected() && (i < 3)) { - Serial.println("Attempt MQTT Connection."); - boolean ret; - ret = _mqtt_client.connect(name.c_str(), user.c_str(), password.c_str()); - if (ret) { - Serial.println("Connected to MQTT"); - return true; - - } else { - int Status = _mqtt_client.state(); - - switch (Status) - { - case -4: - Serial.println(F("Connection timeout")); - break; - - case -3: - Serial.println(F("Connection lost")); - break; - - case -2: - Serial.println(F("Connect failed")); - break; - - case -1: - Serial.println(F("Disconnected")); - break; - - case 1: - Serial.println(F("Bad protocol")); - break; - - case 2: - Serial.println(F("Bad client ID")); - break; - - case 3: - Serial.println(F("Unavailable")); - break; - - case 4: - Serial.println(F("Bad credentials")); - break; - - case 5: - Serial.println(F("Unauthorized")); - break; - } - - } - - Serial.print("."); - i++; - delay(5000); - } - - return false; - -} diff --git a/lib/Device/Device.h b/lib/Device/Device.h index 6983304..7d65365 100644 --- a/lib/Device/Device.h +++ b/lib/Device/Device.h @@ -53,13 +53,13 @@ const char version[] = "0.0.1"; #define TOPIC_LIMIT 4 -//COMMAND_SIGNATURE void (*commandFunction)(uint8_t*) // https://forum.arduino.cc/t/assignment-of-function/528949/3 -//CALLBACK_SIGNATURE void (*callback)(char*, uint8_t*, unsigned int) +typedef void (*ptr)(uint8_t*); +//typedef ptr (*pm)(); const size_t DOC_SIZE = JSON_OBJECT_SIZE(29) + JSON_ARRAY_SIZE(4); struct CommandTopic { - void (*cmd)(byte*); + ptr CmdFunc; String CmdTopic; }; @@ -69,13 +69,18 @@ struct ControlDevice { CommandTopic command_topics[TOPIC_LIMIT]; }; -void (*cmd)(byte*) CmdLookup(String command_topic, ControlDevice devices[], int device_count) { +ptr CmdLookup(String lookup_topic, ControlDevice devices[], int device_count) { for (int i=0;iCmdTopic == command_topic) return this_device.command_topics[j]->cmd; + CommandTopic this_topic = this_device.command_topics[j]; + String topic = this_topic.CmdTopic; + if (topic == lookup_topic) { + return this_topic.CmdFunc; + } } } + return 0; } #endif diff --git a/lib/global/global.h b/lib/global/global.h deleted file mode 100644 index d712593..0000000 --- a/lib/global/global.h +++ /dev/null @@ -1,17 +0,0 @@ -/* This file is all the stuff I want to be -able to change without having to update the -source repository. -*/ - -#ifndef GLOBAL_H -#define GLOBAL_H - -#define DEVICE_SW "0.0.1" -auto chipid = String(ESP.getChipId(), HEX); - -#define DEVICE_NAME "Glycol Chiller" -#define DEVICE_MDL "Chillenator v0.1" -#define DEVICE_MF "Damn Yankee Brewing" -#define FERMENTER_COUNT 2 - -#endif diff --git a/src/FermController/FermController.ino b/src/FermController/FermController.ino index dd535e7..37d8141 100644 --- a/src/FermController/FermController.ino +++ b/src/FermController/FermController.ino @@ -4,8 +4,9 @@ // My Libraries #include -#include +#include #include +#include String chiller_state = "idle"; int tank_setpoint = 28; @@ -24,12 +25,6 @@ void mqttCallback(char *topic, byte *payload, unsigned int length) { Communicator hass_comm = Communicator(net, &mqttCallback); -String slugify(String input) { - input.toLowerCase(); - input.replace(" ", "_"); - return input; -} - void merge(JsonObject dest, JsonObjectConst src) { for (auto kvp : src) { dest[kvp.key()] = kvp.value(); @@ -41,8 +36,6 @@ void merge(JsonObject dest, JsonObjectConst src) { * Using climate device. */ void climateDevice(String name, boolean multimode=false) { - auto chipid = String(ESP.getChipId(), HEX); - String name_slug = slugify(name); String config_topic = "homeassistant/climate/" + name_slug + "_" + chipid + "/config"; diff --git a/src/FermController/device.h b/src/FermController/device.h deleted file mode 100644 index 621d682..0000000 --- a/src/FermController/device.h +++ /dev/null @@ -1,79 +0,0 @@ -#include - -class Device { - public: - - String device_topic; - Communicator hass_comm; - - Device(Communicator& comm, String topic) { - this->hass_comm = comm; - this->device_topic = topic; - } - - - void addParameter(String id, String value){ - _params[_paramcount] = Parameter(id, value); - _paramcount++ - } - - void attachEntity(Entity entity){ - _entities[_entitycount] = entity; - _entitycount++; - } - - void registerDevice(){ - - for (int i=0;i<_entitycount;i++){ - StaticJsonDocument<512> doc; - for (int j=0;j<_entities[i].paramcount;j++) { - doc[_entities[i].params[j].getID()] = _entities[i].params[j].getValue(); - } - } - JsonObject dev = doc.createNestedObject("dev"); - for (int i=0; i<_paramcount;i++) { - dev[_params[j].getID()] = _params[j].getValue(); - } - - //Register - hass_comm.mqtt_discovery(device_topic, doc); - } - - private: - Parameter _params[]; - int _paramcount = 0; - Entity _entities[]; - int _entitycount = 0; - -} - -class Entity { - public: - Parameter params[]; - int paramcount = 0; - void addParameter(String id, String value){ - params[paramcount] = Parameter(id, value); - paramcount++ - } - -} - -class Parameter { - public: - Parameter(String id, String value){ - this->_id = id; - this->_value = value; - } - - String getID(){ - return this->_id; - } - - String getValue(){ - return this->_value; - } - - private: - String _id; - String _value; -} \ No newline at end of file