// // // PlantModel // // #include "ProjGlobals.h" #include "PlantModel.h" #include "WiFiStateHandler.h" #include "Utility.h" PlantData_T plant; /// This keeps track of everything relevant to this system String OnOffText(bool isOn) { if (isOn) return String("On"); else return String("Off"); } String DrumStateText(DrumState_E state) { switch (state) { case DrumIsOpen: return String("Open"); case DrumIsClosed: return String("Closed"); case DrumIsMoving: return String("Moving"); default: return String("Error"); } } String DrumMotorText(DrumMotor_E state) { switch (state) { case DrumOff: return String("Stopped"); case DrumCW: return String("CW Rotation"); case DrumCCW: return String("CCW Rotation"); default: return String("Error"); } } String DrumOpenText(bool isOpen) { if (isOpen) return String("Open"); else return String("not open"); } String DrumClosedText(bool isClosed) { if (isClosed) return String("Closed"); else return String("not closed"); } String WaterInTankText(bool waterInTank) { if (waterInTank) return String("OK"); else return String("Empty"); } // { // "id": "5c:cf:7f:c0:52:82", // "name": "3-Way Switch", // "state": 0, // "sense": 56, // "ip": "192.168.1.23", // "rssi": "-63", // "countdown": "3:45", // "uptime": "0:11:45", // "wifimode": "station"|"ap" // } // void HandleGetState() { int day, hr, minute, sec; char _upTime[15]; // 0000.00:00:00\0 + 1 spare sec = millis() / 1000; minute = sec / 60; hr = minute / 60; day = hr / 24; if (day) snprintf(_upTime, sizeof(_upTime), "%dd %d:%02d:%02d", day, hr % 24, minute % 60, sec % 60); else if (hr) snprintf(_upTime, sizeof(_upTime), "%d:%02d:%02d", hr, minute % 60, sec % 60); else snprintf(_upTime, sizeof(_upTime), "%02d:%02d", minute % 60, sec % 60); String modeText = (WiFiStateGet() == WFC_JoinedAP) ? "Station" : "Access Point"; String message = "{\n"; message += "\t\"id\": \"" + GetMacString() + "\",\n"; message += "\t\"name\": \"" + wifiConfig.getName() + "\",\n"; message += "\t\"version\": \"" + AP_VERS + "\",\n"; //message += "\t\"state\": " + String(CurrStatus) + ",\n"; //message += "\t\"raw\": " + String(iRaw) + ",\n"; //message += "\t\"sense\": " + String(iRawSum / AVG_RATIO) + ",\n"; message += "\t\"ip\": \"" + String(WiFi.localIP()[0]) + "." + String(WiFi.localIP()[1]) + "." + String(WiFi.localIP()[2]) + "." + String(WiFi.localIP()[3]) + "\",\n"; message += "\t\"rssi\": \"" + String(WiFi.RSSI()) + "\",\n"; message += "\t\"uptime\": \"" + String(_upTime) + "\",\n"; message += "\t\"wifimode\": \"" + modeText + "\",\n"; snprintf(_upTime, sizeof(_upTime), "%02u:%02u", plant.SecondsToday/3660, (plant.SecondsToday/60)%60); message += "\t\"TimeOfDay\": \"" + String(_upTime) + "\",\n"; message += "\t\"Fahrenheit\": \"" + String(plant.Fahrenheit) + "\",\n"; message += "\t\"ChamberTemp_C\": \"" + String(plant.ChamberTemp_C) + "\",\n"; message += "\t\"ChamberHumi\": \"" + String(plant.ChamberHumi) + " % \",\n"; message += "\t\"SoilHeater\": \"" + OnOffText(plant.SoilHeater) + "\",\n"; message += "\t\"SoilTemp_C\": \"" + String(plant.SoilTemp_C) + "\",\n"; message += "\t\"AmbientTemp_C\": \"" + String(plant.AmbientTemp_C) + "\",\n"; message += "\t\"DrumDoorIcon\": \"" + DrumStateText(plant.DrumDoorIcon) + "\",\n"; message += "\t\"DrumOpenSensor\": \"" + DrumOpenText(plant.DrumOpenSensor) + "\",\n"; message += "\t\"DrumClosedSensor\": \"" + DrumClosedText(plant.DrumClosedSensor) + "\",\n"; message += "\t\"DrumMotorStatus\": \"" + DrumMotorText(plant.DrumMotorStatus) + "\",\n"; message += "\t\"DrumMotor_V\": \"" + String(plant.DrumMotor_V) + "\",\n"; message += "\t\"DrumMotor_I\": \"" + String(plant.DrumMotor_I) + "\",\n"; snprintf(_upTime, sizeof(_upTime), "%02u:%02u", plant.DrumMotorOn_sec/60, plant.DrumMotorOn_sec%60); message += "\t\"DrumMotorOn_sec\": \"" + String(_upTime) + "\",\n"; message += "\t\"WaterInTank\": \"" + String(plant.WaterInTank) + "\",\n"; message += "\t\"WaterMotor_V\": \"" + String(plant.WaterPumpStatus) + "\",\n"; message += "\t\"SoilMoisture_X\": \"" + String(plant.SoilMoisture_X) + "\",\n"; snprintf(_upTime, sizeof(_upTime), "%02u:%02u", plant.WaterCyclePeriod_sec/60, plant.WaterCyclePeriod_sec%60); message += "\t\"WaterCyclePeriod_sec\": \"" + String(_upTime) + "\",\n"; snprintf(_upTime, sizeof(_upTime), "%02u:%02u", plant.WaterCycleOn_sec/60, plant.WaterCycleOn_sec%60); message += "\t\"WaterCycleOn_sec\": \"" + String(_upTime) + "\",\n"; snprintf(_upTime, sizeof(_upTime), "%02u:%02u", plant.WaterCycle_sec/60, plant.WaterCycle_sec%60); message += "\t\"waterCycle\": \"" + String(_upTime) + "\"\n"; //message += "\t\"toggle\": " + String(!digitalRead(SW_TOGGLE)) + ",\n"; //message += "\t\"reset\": " + String(!digitalRead(SW_RESET)); message += "}\n"; server.sendHeader("Access-Control-Allow-Origin", String("*"), true); server.send(200, "application/json", message); } void simulation() { if (++plant.SecondsToday >= (24*3600)) { // Seconds are advancing really fast for the simulation plant.SecondsToday -= (24 * 3600); } static int lastMinutesToday = -1; int hoursToday = plant.SecondsToday / 3600; int minutesToday = plant.SecondsToday / 60; // Simulate Ambient temp rising and falling if (lastMinutesToday != minutesToday) { lastMinutesToday = minutesToday; //Serial.printf("%02u:%02u, Ambient %3.1f\n", hoursToday, minutesToday % 60, plant.AmbientTemp_C); if (hoursToday < 15) { // warming part of the day if (plant.AmbientTemp_C < 45.0) { plant.AmbientTemp_C += (float)(rand() % 10)/1000.0; } } else { // cooling part of the day if (plant.AmbientTemp_C > 10.0) { plant.AmbientTemp_C -= (float)(rand() % 10)/1000.0; } } if (plant.SoilTemp_C > 40.0) { plant.SoilHeater = false; } else if (plant.SoilTemp_C < 20.0) { plant.SoilHeater = true; } if (plant.SoilHeater) { if (plant.SoilTemp_C < 50.0) { plant.SoilTemp_C += (float)(rand() % 10)/1000.0; } } else { if (plant.SoilTemp_C < plant.ChamberTemp_C) { plant.SoilTemp_C += (float)(rand() % 10)/1000.0; } else { plant.SoilTemp_C -= (float)(rand() % 10)/1000.0; } } if (plant.DrumMotorStatus == DrumCW) { plant.DrumMotorOn_sec++; } else if (plant.DrumMotorStatus == DrumCCW) { plant.DrumMotorOn_sec++; } else { plant.DrumMotorOn_sec = 0; } if (plant.ChamberTemp_C > 50.0) { if (!plant.DrumOpenSensor) { plant.DrumMotorStatus = DrumCW; if (plant.DrumMotorOn_sec > 50) { plant.DrumOpenSensor = true; plant.DrumClosedSensor = false; } } } else if (plant.ChamberTemp_C < 40.0) { if (!plant.DrumClosedSensor) { plant.DrumMotorStatus = DrumCW; if (plant.DrumMotorOn_sec > 50) { plant.DrumOpenSensor = false; plant.DrumClosedSensor = true; } } } if (plant.DrumDoorIcon == DrumIsOpen) { if (plant.ChamberTemp_C > plant.AmbientTemp_C) { plant.ChamberTemp_C -= (float)(rand() % 10)/1000.0; } else if (plant.ChamberTemp_C < plant.AmbientTemp_C) { plant.ChamberTemp_C += (float)(rand() % 10)/1000.0; } } else { if (plant.ChamberTemp_C > plant.AmbientTemp_C) { plant.ChamberTemp_C -= (float)(rand() % 5)/1000.0; } else if (plant.ChamberTemp_C < plant.AmbientTemp_C) { plant.ChamberTemp_C += (float)(rand() % 20)/1000.0; } } plant.ChamberHumi = (float)(rand() % 73) + 25; if (++plant.WaterCycle_sec >= plant.WaterCyclePeriod_sec) { plant.WaterCycle_sec -= plant.WaterCyclePeriod_sec; } if (plant.WaterCycle_sec >= plant.WaterCycleOn_sec) { plant.WaterPumpStatus = false; } if (plant.SoilMoisture_X < 60.0 && plant.WaterCycle_sec < plant.WaterCycleOn_sec) { plant.WaterPumpStatus = true; } if (plant.WaterPumpStatus) { plant.SoilMoisture_X += (float)(rand() % 40)/100.0; } else { plant.SoilMoisture_X -= (float)(rand() % 5)/100.0; } } }