ProcessPacket using JumpTable

This commit is contained in:
Heuideog Yi @ PC RnD1 2026-04-24 08:42:52 +09:00
parent 3eeeb8304d
commit 95cbe9f950
15 changed files with 581 additions and 526 deletions

View File

@ -24,7 +24,7 @@ void CONFIG_TYPE::init() {
bNightControl = false;
bControlTemperature = true;
bControlHumidity = true;
bEnableIO = true;
bCheckAC = true;
bAC2_OnOff = false;
nNightStartHour = 18;
@ -32,18 +32,25 @@ void CONFIG_TYPE::init() {
nNightEndHour = 6;
nNightEndMin = 0;
ac1ControlMode = PHASE_CONTROL;
ac2ControlMode = ZCD_CONTROL;
// Block 2 - Sensor and Temperature/Humidity Settings
nTempTarget = 260;
nTempTargetNight = 260;
nTemp1Offset = 0;
nTemp2Offset = 0;
nTemp3Offset = 0;
nHumidTarget = 880;
nHumidTargetNight = 880;
nHumidTarget = 800;
nHumidTargetNight = 800;
nHumid1Offset = 0;
nHumid2Offset = 0;
nTemp1SensorType = TEMP_SENSOR_TYPE::BLE_TUYA;
nTemp2SensorType = TEMP_SENSOR_TYPE::AHT20;
nTempSafety = 290;
bNTCNegativePolarity = true;
nBLEScanInterval = 143;
bBLETest = false;
Kp_Temp1 = 3.0f; // Load Kp for Temperature control
Kd_Temp1 = 750.0f; // Load Kd for Temperature control
@ -52,27 +59,43 @@ void CONFIG_TYPE::init() {
Kp_Humidity = 2.0f; // Load Kp for Humidity control
Kd_Humidity = 150.0f; // Load Kd for Humidity control
LR_Humidity = 0.08f; // Load learning rate for Humidity
Kp_Temp2 = 3.0f; // Load Kp for Temperature control
Kd_Temp2 = 750.0f; // Load Kd for Temperature control
LR_Temp2 = 0.05f; // Load learning rate for Temperature
Kp_Humid2 = 2.0f; // Load Kp for Humidity control
Kd_Humid2 = 150.0f; // Load Kd for Humidity control
LR_Humid2 = 0.08f; // Load learning rate for Humidity
Kp_Temp3 = 3.0f; // Load Kp for Temperature control
Kd_Temp3 = 750.0f; // Load Kd for Temperature control
LR_Temp3 = 0.05f; // Load learning rate for Temperature
Kp_Humid3 = 2.0f; // Load Kp for Humidity control
Kd_Humid3 = 150.0f; // Load Kd for Humidity control
LR_Humid3 = 0.08f; // Load learning rate for Humidity
// Block 3 - AC1 and AC2
// Day/Night Min/Max/Start On/Off THigh/Low Time B/E Period Hum H/L
config.ac1 = {CONTROL_TEMP_HEAT_PID, 0, 1,1, 0, 1000, 0, 250,0, 920,880, 0,24*60-1, 60, 5, 920,880 };
config.ac2 = {CONTROL_TEMP_HEAT, 0, 0,0, 0, 1000, 0, 250,0, 920,880, 0,25*60-1, 60, 5, 920,880 };
config.ac1 = {CONTROL_TEMP_HEAT_PID, 0, 1,1, 0, 1000, 0, 250,0, 920,880, 0,24*60-1, 60, 5, 820,780 };
config.ac2 = {CONTROL_TEMP_HEAT, 0, 0,0, 0, 1000, 0, 250,0, 920,880, 0,25*60-1, 60, 5, 820,780 };
// Block 4 = Mist and Fan
// Day/Night Min/Max/Start On/Off THigh/Low Time B/E Period Hum H/L
config.mist = {CONTROL_HUMIDITY_INC_PID, 0, 1,1, 0, 1000, 0, 250,0, 920,880, 0,25*60-1, 60, 5, 920,880 };
config.fan = {CONTROL_TEMP_COOL, 0, 1,1, 0, 1000, 0, 250,0, 920,880, 0,25*60-1, 60, 5, 920,880 };
config.mist = {CONTROL_HUMIDITY_INC_PID, 0, 1,1, 0, 1000, 0, 250,0, 920,880, 0,25*60-1, 60, 5, 820,780 };
config.fan = {CONTROL_TEMP_COOL, 0, 1,1, 0, 1000, 0, 250,0, 920,880, 0,25*60-1, 60, 5, 820,780 };
// Block 5 - Motor and Light
// Day/Night Min/Max/Start On/Off THigh/Low Time B/E Period Hum H/L
config.motor = {CONTROL_PERIOD, 0, 1,1, 0, 1000, 0, 250,0, 920,880, 0,25*60-1, 60, 5, 920,880 };
config.light = {CONTROL_DAY_NIGHT, 0, 1,1, 0, 1000, 0, 250,0, 920,880, 0,25*60-1, 60, 5, 920,880 };
config.motor = {CONTROL_PERIOD, 0, 1,1, 0, 1000, 0, 250,0, 920,880, 0,25*60-1, 60, 5, 820,780 };
config.light = {CONTROL_DAY_NIGHT, 0, 1,1, 0, 1000, 0, 250,0, 920,880, 0,25*60-1, 60, 5, 820,780 };
// Block 6 - Environment and Operations
bSendStatusSerial = false;
bConfigSaved = false;
bStatusSaved = false;
bSendStatusSerial = false;
//
// Reserved
@ -81,8 +104,8 @@ void CONFIG_TYPE::init() {
for (int i = 0; i < 17; i = i + 8) {
m_nChipId |= ((ESP.getEfuseMac() >> (40 - i)) & 0xff) << i;
}
m_nPublicPort = 3939;
m_nDeviceType = THIS_DEVICE_TYPE;
m_nPublicPort = 3939;
//
// WiFi Client Only
@ -90,19 +113,26 @@ void CONFIG_TYPE::init() {
m_nDisplayTime = 1800;
m_nDisplayTempHigh = 40;
m_nDisplayTempLow = 20;
m_nTempHigh = 20;
m_nTempHigh = 25;
m_fShowRealTime = 0x000F;
// Names
strcpy(m_sDeviceName, "Beta X");
strcpy(m_sMake, "VisionSoft");
strcpy(m_sModel, "HermitCrab");
strncpy(m_sVersion, HC__VERSION, 11);
m_fShowHistory = 0x000F;
m_nEpochTime = 0;
m_nTimeOffset = 9 * 60 * 60;
m_bFahrenheit = false;
// WiFi - SSID and Password
strcpy(ssid, "RECALL");
strcpy(pw, "BBBB9999");
//Block 10
strcpy(m_sDeviceName, "Beta X");
strcpy(m_sMake, "VisionSoft");
// Block 11
strcpy(m_sModel, "HermitCrab");
strncpy(m_sVersion, HC__VERSION, 11);
ESP_LOGI(TAG,"Config Initialized");
}

View File

@ -70,17 +70,14 @@ enum TEMP_SENSOR_TYPE {
typedef struct CONFIG_STRUCT {
uint16_t m_nSignature1;
// Block 1 - Control and EnvironMent
// Offset 2
bool bSmartControl;
bool bNightControl;
bool bControlTemperature;
bool bControlHumidity;
bool bEnableIO;
bool bCheckAC;
bool bAC2_OnOff;
bool bdummy;
uint8_t nNightStartHour, nNightStartMin, nNightEndHour, nNightEndMin;
float Kp_Temp2; // Load Kp for Temperature control
float Kd_Temp2; // Load Kd for Temperature control
@ -88,28 +85,33 @@ typedef struct CONFIG_STRUCT {
float Kp_Temp3; // Load Kp for Temperature control
float Kd_Temp3; // Load Kd for Temperature control
float LR_Temp3; // Load learning rate for Temperature
uint8_t ac1ControlMode, ac2ControlMode; // ZCD_CONTROL || PHASE_CONTROL
uint8_t bPadding1[2];
union {
uint64_t nBLESensorAddr2;
uint8_t nBLESensorAddrBytes2[8];
};
uint8_t ac1ControlMode, ac2ControlMode; // ZCD_CONTROL || PHASE_CONTROL
char bExtra[64 - 8 * sizeof(bool) - 4 * sizeof(uint8_t) - 6 * sizeof(float) - sizeof(uint64_t) - 2 * sizeof(uint8_t)];
float Kp_Humid2;
float Kd_Humid2;
float LR_Humid2;
char bExtra[64 - 6 * sizeof(bool) - 8 * sizeof(uint8_t) - 9 * sizeof(float) - sizeof(uint64_t)];
// Block 2 - Sensor and TargetTemperature and Himidity
// Offset 64 + 2
int16_t nTempTarget, nTempTargetNight; // Target Temperature
int16_t nTemp1Offset, nTemp2Offset, nTemp3Offset;
uint16_t nHumidTarget, nHumidTargetNight;
int16_t nHumid1Offset, nHumid2Offset;
uint8_t nTemp1SensorType; // TempSensor Type enum
uint8_t nTemp2SensorType; // TempSensor Type enum
float Kp_Temp1; // Load Kp for Temperature control
float Kd_Temp1; // Load Kd for Temperature control
float LR_Temp1; // Load learning rate for Temperature
float Kp_Humidity; // Load Kp for humidity control
float Kd_Humidity; // Load Kd for humidity control
float LR_Humidity; // Load learning rate for humidity
uint8_t nTemp1SensorType; // TempSensor Type enum
uint8_t nTemp2SensorType; // TempSensor Type enum
int16_t nTempSafety;
float Kp_Temp1; // Load Kp for Temperature control
float Kd_Temp1; // Load Kd for Temperature control
float LR_Temp1; // Load learning rate for Temperature
float Kp_Humidity; // Load Kp for humidity control
float Kd_Humidity; // Load Kd for humidity control
float LR_Humidity; // Load learning rate for humidity
union {
uint64_t nBLESensorAddr;
uint8_t nBLESensorAddrBytes[8];
@ -118,28 +120,36 @@ typedef struct CONFIG_STRUCT {
uint8_t nBLEScanInterval;
uint8_t bBLETest;
char nTempExtra[64 - 10 * sizeof(int16_t) - 6 * sizeof(float) - 5 * sizeof(uint8_t) - sizeof(uint64_t)];
union {
struct {
// Block 3 - AC1 and AC2
// Offset 128 + 2
DEVICE_PARAM_TYPE ac1;
DEVICE_PARAM_TYPE ac2;
// Block 4 - Mist and Fan
// Offset 192 + 2
DEVICE_PARAM_TYPE mist;
DEVICE_PARAM_TYPE fan;
// Block 5 - Motor and Light
// Offset 256 + 2
DEVICE_PARAM_TYPE motor;
DEVICE_PARAM_TYPE light;
};
DEVICE_PARAM_TYPE deviceParamArray[6];
};
// Block 3 - AC1 and AC2
// Offset 128 + 2
DEVICE_PARAM_TYPE ac1;
DEVICE_PARAM_TYPE ac2;
// Block 4 - Mist and Fan
// Offset 192 + 2
DEVICE_PARAM_TYPE mist;
DEVICE_PARAM_TYPE fan;
// Block 5 - Motor and Light
// Offset 256 + 2
DEVICE_PARAM_TYPE motor;
DEVICE_PARAM_TYPE light;
// Block 6 - Environment and Operations
// Offset 320 + 2
bool bSendStatusSerial;
bool bConfigSaved;
bool bStatusSaved;
char nEnvExtra[32 - 3 * sizeof(bool)];
float Kp_Humid3; // Load Kd for humidity control
float Kd_Humid3; // Load Kp for humidity control
float LR_Humid3; // Load learning rate for humidity
bool bSendStatusSerial;
char nEnvExtra[32 - 3 * sizeof(bool) - 3*sizeof(float)];
// Offset 352 + 2
STATUS_TYPE statusSave;
@ -177,17 +187,18 @@ typedef struct CONFIG_STRUCT {
char nModelExtra[64 - 44];
// Offset 704 + 2
char padAlign8[4];
uint16_t m_nSignature2;
#ifdef ESP32
// ConfigStruct Size: 708
// ConfigStruct Size: 712
public:
void init();
bool load();
void save();
//bool saveToServer();
#endif
} CONFIG_TYPE;
} __attribute__((aligned(8))) CONFIG_TYPE;
#pragma pack(pop) // Restore previous alignment setting
extern class Preferences preferences;

View File

@ -4,6 +4,7 @@
extern bool g_bWiFiSetupExecuted;
extern bool g_bWiFiHasBeenConnected;
void setupPostWiFi(bool bBoot = false);
void reconnectWiFi(unsigned long tickMillis, bool bConnecting, wl_status_t status);
void WiFiEvent(WiFiEvent_t event) {
switch (event) {
@ -40,20 +41,24 @@ void checkAndUpdateWiFiCredentials() {
}
}
IRAM_ATTR
void checkWiFi(unsigned long tickMillis) {
static unsigned long lastAttempt = 0;
IRAM_ATTR void checkWiFi(unsigned long tickMillis) {
static bool bConnecting = false;
wl_status_t status = WiFi.status();
// Connected
if (status == WL_CONNECTED) {
bConnecting = false;
g_bWiFiHasBeenConnected = true;
return; // Already connected, no need to proceed further
bConnecting = false;
g_bWiFiHasBeenConnected = true;
return; // Already connected, no need to proceed further
}
// Not Connected
reconnectWiFi(tickMillis, bConnecting, status);
}
void reconnectWiFi(unsigned long tickMillis, bool bConnecting, wl_status_t status) {
static unsigned long lastAttempt = 0;
checkAndUpdateWiFiCredentials();
// Connecting

View File

@ -20,7 +20,7 @@
#ifndef DEBUG
#define DEBUG 1 // Set to 0 to disable debug output
#endif
//#undef DEBUG
#undef DEBUG
//#define BLE_DEBUG
@ -152,6 +152,8 @@ enum EVENT_TYPE {
#define FLAG_BLE_NODATA (0x0800)
#define FLAG_BLE_LOST (0x1000)
#define PHASE_CONTROL 0
#define ZCD_CONTROL 1
#pragma pack(push) /* push current alignment to stack */
#pragma pack(1) /* set alignment to 1 byte boundary */
@ -200,14 +202,15 @@ typedef struct STATUS_STRUCT {
uint16_t nLightDuty;
uint16_t nLightTargetDuty;
// 24
uint16_t nFlags;
// 26
// Current Time
uint32_t now;
// 28
uint16_t nFlags;
// 30
// AC status
uint8_t zcdAC;
uint8_t zcdLoad;

View File

@ -22,6 +22,11 @@
STATUS_TYPE status;
// 코어 버전이 3.0.2가 아니면 컴파일 중단
#include <esp_arduino_version.h>
static_assert(ESP_ARDUINO_VERSION == ESP_ARDUINO_VERSION_VAL(3, 0, 2),
"This project requires ESP32 Arduino Core 3.0.2");
// Time
volatile unsigned short g_nYear, g_nMonth, g_nDay, g_nHour, g_nMinute, g_nSecond;
volatile uint32_t g_millis = 0l;
@ -584,9 +589,6 @@ MY_IRAM_ATTR char *printStatus(unsigned long tick, bool bLong) {
printTime(bLong), strHeat1, strMist, strLight1,
history.getKpTemperature(), history.getKdTemperature(),
history.getKpHumidity(), history.getKdHumidity());
// Send out to clients
// ESP_LOGI(TAG_MAIN,"%s\n", szStatus);
}
return szStatus;
}

View File

@ -1,11 +1,8 @@
#include "Arduino.h"
#include <Arduino.h>
#include "HermitCrab.h"
#include "NTC_10K.h"
#include "Config.h"
#include "NTC_10K.h"
#include "driver/gpio.h"
#include "driver/adc.h"
const float resistance[] = {
3360850.37, // -40°C
@ -74,6 +71,23 @@ void NTC_10K::setup(bool bNegativePolarity) {
m_nTemp = -9999;
m_fTemp = -9999.0f;
m_fLastTemp = 0.0f;
// =========================
// 1. NTC (ADC 설정)
// =========================
// 1.1. 핸들 및 설정 변수 선언
adc_oneshot_unit_init_cfg_t init_config = {
.unit_id = ADC_UNIT_1,
};
adc_oneshot_new_unit(&init_config, &adc1_handle);
// 1.2. 채널 설정 (감쇠비 포함)
adc_oneshot_chan_cfg_t config = {
.atten = ADC_ATTEN_DB_12, // 11 대신 12 사용 (이전 답변 참고)
.bitwidth = ADC_BITWIDTH_DEFAULT,
};
adc_oneshot_config_channel(adc1_handle, ADC_CHANNEL_3, &config);
}
/**
@ -90,7 +104,9 @@ void NTC_10K::readSensor() {
float currentInstantTemp; // High-precision intermediate
// 1. Hardware Acquisition
int adcValue = constrain(adc1_get_raw(ADC1_CHANNEL_3), 1, 4094);
//int adcValue = constrain(adc1_get_raw(ADC1_CHANNEL_3), 1, 4094);
int adcValue;
adc_oneshot_read(adc1_handle, ADC_CHANNEL_3, &adcValue);
// 2. Voltage and Resistance Calculation
Vin = (float)adcValue * _vRef / _RESO;

View File

@ -7,6 +7,7 @@
#define NTC_COUNT 32
#define NTC_MASK (NTC_COUNT - 1)
#include <esp_adc/adc_oneshot.h>
class NTC_10K {
private:
@ -24,6 +25,8 @@ private:
float m_fTemp;
float m_fLastTemp;
adc_oneshot_unit_handle_t adc1_handle;
public:
void setup(bool bNegativePolarity);
void readSensor();

View File

@ -17,7 +17,7 @@
// OTA
//
// ==============================================================
const char *HC__VERSION = "20260419022";
const char *HC__VERSION = "20260424001";
#define UPDATE_PORT ((uint16_t) 443)
const char *url = "visionsoft.kr";
const char *uri = "/sc/pages/firmware_download.php";

View File

@ -14,12 +14,9 @@
#include "esp_coexist.h"
// GPIO Headers
#include "driver/gpio.h"
#include "driver/timer.h"
#include "driver/adc.h"
#include <driver/gpio.h>
#include <driver/timer.h>
#define TAG_SETUP "TAG_SETUP"
// Task handle
TaskHandle_t TaskHandle_0;
@ -68,17 +65,23 @@ void setup() {
bShowSensor = false;
// Hardware
setupPWM();
// Basic settings before wifi/OTA
setupPWM(); // Required for LED blinking
setupGPIO1();
setupConfig();
setupStatus();
scanI2C();
setupSensor();
ui.setup();
setupWiFi();
setupConfig(); // Wifi SSID/PW
scanI2C(); // Wire init
setupSensor(); // Wire Scan
ui.setup(); // ui for OLED Display
// Wifi and Update Check
setupWiFi(); // Wifi AP, OTA, Time Service
setupStatus(); // Requires Time Service from WiFi Setup.
// Pins
// Temp/Humod Sensor
if (aht25.sensor() || aht10_0x39.sensor()) {
ui.message(4, (char *) "Sensor... OK!");
} else {
@ -124,9 +127,6 @@ void setupGPIO1() {
// =========================
// 1. NTC (ADC 설정)
// =========================
// adc1_config_channel_atten에서 내부적으로 핀 설정을 하므로 방향 설정은 생략 가능합니다.
adc1_config_width(ADC_WIDTH_BIT_12); // 0~4095
adc1_config_channel_atten(ADC1_CHANNEL_3, ADC_ATTEN_DB_11);
// =========================
// 2. UI Buttons 설정

7
UI.cpp
View File

@ -222,7 +222,7 @@ CUI::CUI()
void CUI::setup() {
// Initialize the display
ESP_LOGI(TAG_UI," UI - setup()");
DPRINTLN("[UI] setup()");
bOK = false;
bDot = false;
bButtonChanged = false;
@ -249,18 +249,19 @@ void CUI::setup() {
lastpDUnit = nullptr;
// Check if device exists
// Wire.begin();
for (int i = 0; i < 5; i++) {
Wire.beginTransmission(i2caddr);
if (Wire.endTransmission() == 0) {
bOK = true;
ESP_LOGI(TAG_UI," UI - device Found at 0x%02X\n", i2caddr);
DPRINTF("[UI] Setup - device Found at 0x%02X\n", i2caddr);
break;
}
delay(50);
}
if (!bOK) {
ESP_LOGI(TAG_UI," UI - device NOT found at 0x%02X\n", i2caddr);
DPRINTF("[UI] Setup - device NOT found at 0x%02X\n", i2caddr);
return;
}

6
UI.h
View File

@ -102,9 +102,9 @@ private:
//
// Button ISR's
//
void IRAM_ATTR buttonSetISR(void *);
void IRAM_ATTR buttonUpISR(void *);
void IRAM_ATTR buttonDownISR(void *);
void buttonSetISR(void *);
void buttonUpISR(void *);
void buttonDownISR(void *);
extern CUI ui;
#endif

View File

@ -164,8 +164,7 @@ void CWiFiHost::CloseConnection()
m_nMode = MODE_WAITING;
}
IRAM_ATTR
void CWiFiHost::Loop(unsigned long clock)
IRAM_ATTR void CWiFiHost::Loop(unsigned long clock)
{
if (!isWiFiConnected()) return;
@ -251,8 +250,7 @@ void CWiFiHost::Loop(unsigned long clock)
}
}
MY_IRAM_ATTR
void CWiFiHost::SendHeartBeat(unsigned long clock) {
MY_IRAM_ATTR void CWiFiHost::SendHeartBeat(unsigned long clock) {
if (!isWiFiConnected()) {
//ESP_LOGI(TAG_WIFI_HOST,"WiFiHost - SendHeartBeat() called while not connected!");
return;
@ -304,8 +302,7 @@ void CWiFiHost::SendHeartBeat(unsigned long clock) {
}
}
MY_IRAM_ATTR
void CWiFiHost::MonitorUDP() {
MY_IRAM_ATTR void CWiFiHost::MonitorUDP() {
// Listen for UDP External port
IPAddress ip;
int size = udpExternal.parsePacket();
@ -358,8 +355,42 @@ void CWiFiHost::MonitorUDP() {
}
}
IRAM_ATTR
void CWiFiHost::CheckClient(unsigned long clock)
typedef union {
float f;
uint32_t u;
} float_bits;
// Optimized for range +/- 0.0001 to +/- 3000
IRAM_ATTR uint16_t f32tof16(float f32) {
float_bits fb;
fb.f = f32;
// Extract sign, move to bit 15
uint32_t sign = (fb.u >> 16) & 0x8000;
// Shift exponent from 8-bit (bias 127) to 5-bit (bias 15)
// 0x7f800000 masks the exponent
uint32_t exp = ((((fb.u & 0x7f800000) >> 23) - 127 + 15) & 0x1f) << 10;
// Truncate 23-bit mantissa to 10-bit
uint32_t mant = (fb.u >> 13) & 0x03ff;
return (uint16_t)(sign | exp | mant);
}
IRAM_ATTR float f16tof32(uint16_t f16) {
float_bits fb;
// Shift sign to bit 31
uint32_t sign = (uint32_t)(f16 & 0x8000) << 16;
// Shift exponent from 5-bit (bias 15) back to 8-bit (bias 127)
uint32_t exp = (((f16 >> 10) & 0x1f) - 15 + 127) << 23;
// Shift 10-bit mantissa back to 23-bit
uint32_t mant = (f16 & 0x03ff) << 13;
fb.u = sign | exp | mant;
return fb.f;
}
IRAM_ATTR void CWiFiHost::CheckClient(unsigned long clock)
{
// 1. Quick exit if no data is ready to be read
int available = wifiClient.available();
@ -370,7 +401,6 @@ void CWiFiHost::CheckClient(unsigned long clock)
// 2. Peek or Read the packet
// We use readBytes because we already verified 'available' >= size
int count = wifiClient.readBytes((uint8_t*)&cpkt, sizeof(TCP_PACKET));
if (count == sizeof(TCP_PACKET)) {
// 3. Validation Logic
bool sigMatch = (cpkt.sig1 == SIGNATURE1 && cpkt.sig2 == SIGNATURE2);
@ -382,7 +412,7 @@ void CWiFiHost::CheckClient(unsigned long clock)
} else {
// 4. Recovery Logic: Instead of a blocking while-loop,
// clear the socket buffer and wait for the next loop cycle.
ESP_LOGW(TAG_WIFI_HOST, "Protocol out of sync. Flushing %d bytes", available);
DPRINTF("[Host] ErrPacket CMD(%d) OP(%d) len(%d) sig(%s)\n", cpkt.cmd, cpkt.op, cpkt.len, sigMatch ? "OK" : "fail");
while(wifiClient.available() > 0) {
wifiClient.read(); // Efficiently dump the garbage
}
@ -390,327 +420,333 @@ void CWiFiHost::CheckClient(unsigned long clock)
}
}
IRAM_ATTR
void CWiFiHost::ProcessPacket(TCP_PACKET& pkt)
IRAM_ATTR void CWiFiHost::ProcessPacket(TCP_PACKET& pkt)
{
switch (pkt.cmd)
{
// System
case CMD_HEARTBEAT:
m_nLastReceivedTime = millis();
//ESP_LOGI(TAG_WIFI_HOST,"H");
break;
case CMD_HELLO:
case CMD_HELLO_DEBUG:
{
// Send the Config Data to PC
// Send Packet Back
ESP_LOGI(TAG_WIFI_HOST,"WiFi - HELLO received");
pkt.u16[0] = SIGNATURE1;
pkt.n16[1] = sizeof(CONFIG_TYPE);
pkt.u16[2] = SIGNATURE2;
config.m_nChipId;
SendPacket(pkt);
// Send Data Packets
ESP_LOGI(TAG_WIFI_HOST,"WiFi - Config Send pending...");
int sent = SendData((uint8_t*)&config, sizeof(CONFIG_TYPE));
m_bHelloSent = true;
}
break;
case CMD_DROP_CONNECTION:
wifiClient.stop();
m_bClientConnected = false;
m_nMode = MODE_WAITING;
ESP_LOGI(TAG_WIFI_HOST,"WiFI - Client requets to DROP CONNECTION");
break;
case CMD_RESET_REASON:
pkt.n16[0] = esp_reset_reason();
SendPacket(pkt);
break;
case CMD_SAVE_RESTART:
if (pkt.u16[0] == SIGNATURE1 &&
pkt.u16[1] == SIGNATURE2) {
yield();
Restart();
}
break;
case CMD_RESET_RESTART:
if (pkt.u16[0] == SIGNATURE1 &&
pkt.u16[1] == SIGNATURE2) {
pkt.cmd = CMD_DROP_CONNECTION;
SendPacket(pkt);
yield();
Restart();
}
break;
case CMD_SEND_HISTORY:
if (pkt.u16[0] == SIGNATURE1 && pkt.u16[1] == SIGNATURE2) {
int16_t count = history.getRingCount();
if (count > 0 ) {
// inform client the count of history
pkt.op = count;
SendPacket(pkt);
int16_t size = history.getRingSize();
if (count < size) {
ESP_LOGI(TAG_WIFI_HOST,"WfFi Host - SendData - Whold part of History (%d)\n", count);
SendData(history.getRingData1()/* &ring[tail] */, sizeof(STATUS_TYPE) * count);
} else {
int count1st = size - history.getRingTail();
ESP_LOGI(TAG_WIFI_HOST,"WfFi Host - SendData - 1st part of History Total(%d), 1st(%d) H(%d) T(%d)\n",
count, count1st, history.getRingHead(), history.getRingTail());
SendData(history.getRingData1(), sizeof(STATUS_TYPE) * count1st),
// Mark pending to send the second part: from the start to head-1
//SendData(history.getRingData2() /* &ring[0] */, sizeof(STATUS_TYPE) * head);
m_bSendHistoryPending = true;
m_nPendingHistoryCount = history.getRingHead();
}
}
}
break;
case CMD_RESET_SENSOR:
aht25.setScanFlag(true);
aht10_0x39.setScanFlag(true);
break;
// Jump Table definition (GCC Labels-as-values)
static const void* jump_table[] = {
[0] = &&L_DEFAULT,
// Connection & Control
[CMD_HEARTBEAT] = &&L_CMD_HEARTBEAT,
[CMD_HELLO] = &&L_CMD_HELLO,
[CMD_DROP_CONNECTION] = &&L_CMD_DROP_CONNECTION,
[CMD_RESET_REASON] = &&L_CMD_RESET_REASON,
[CMD_RESTART] = &&L_CMD_RESTART,
[CMD_SEND_HISTORY] = &&L_CMD_SEND_HISTORY,
[CMD_RESET_SENSOR] = &&L_CMD_RESET_SENSOR,
[CMD_RESET_DISPLAY] = &&L_CMD_RESET_DISPLAY,
// Config
case CMD_INIT_CONFIG:
if (pkt.u16[0] == SIGNATURE1 &&
pkt.u16[1] == sizeof(CONFIG_STRUCT) &&
pkt.u16[2] == SIGNATURE2) {
config.init();
config.save();
}
break;
case CMD_LOAD_CONFIG:
if (pkt.u16[0] == SIGNATURE1 &&
pkt.u16[1] == sizeof(CONFIG_STRUCT) &&
pkt.u16[2] == SIGNATURE2) {
config.load();
history.loadPID();
}
break;
case CMD_SAVE_CONFIG:
if (pkt.u16[0] == SIGNATURE1 &&
pkt.u16[1] == sizeof(CONFIG_STRUCT) &&
pkt.u16[2] == SIGNATURE2) {
config.save();
}
break;
case CMD_RECV_CONFIG:
// Receive Confif Data from PC
if (pkt.u16[0] == SIGNATURE1 &&
pkt.u16[1] == sizeof(CONFIG_STRUCT) &&
pkt.u16[2] == SIGNATURE2) {
ReceiveData((uint8_t *)&configCopy, sizeof(CONFIG_TYPE));
m_bReceiveConfigPending = true;
ESP_LOGI(TAG_WIFI_HOST,"WiFi - Receive Config initiated...");
}
break;
case CMD_SEND_CONFIG:
if (pkt.u16[0] == SIGNATURE1 &&
pkt.u16[1] == sizeof(CONFIG_STRUCT) &&
pkt.u16[2] == SIGNATURE2) {
SendPacket(pkt);
SendData((const uint8_t *)&config, (unsigned int) sizeof(config));
ESP_LOGI(TAG_WIFI_HOST,"WiFi - Send Config initiated...");
}
break;
// PID
case CMD_INIT_PID_PARAM:
history.savePID();
break;
case CMD_LOAD_PID_PARAM:
history.loadPID();
break;
case CMD_SAVE_PID_PARAM:
history.savePID();
break;
case CMD_SET_PID:
config.Kp_Temp1 = pkt.f[0];
config.Kd_Temp1 = pkt.f[1];
config.LR_Temp1 = pkt.f[2];
config.Kp_Humidity = pkt.f[3];
config.Kd_Humidity = pkt.f[4];
config.LR_Humidity = pkt.f[5];
history.loadPID();
break;
case CMD_GET_PID:
pkt.f[0] = config.Kp_Temp1;
pkt.f[1] = config.Kd_Temp1;
pkt.f[2] = config.LR_Temp1;
pkt.f[3] = config.Kp_Humidity;
pkt.f[4] = config.Kd_Humidity;
pkt.f[5] = config.LR_Humidity;
SendPacket(pkt);
break;
[CMD_INIT_CONFIG] = &&L_CMD_INIT_CONFIG,
[CMD_LOAD_CONFIG] = &&L_CMD_LOAD_CONFIG,
[CMD_SAVE_CONFIG] = &&L_CMD_SAVE_CONFIG,
[CMD_SEND_CONFIG] = &&L_CMD_SEND_CONFIG,
[CMD_RECV_CONFIG] = &&L_CMD_RECV_CONFIG,
[CMD_SET_DEVICE_PARAM] = &&L_CMD_SET_DEVICE_PARAM,
[CMD_GET_DEVICE_PARAM] = &&L_CMD_GET_DEVICE_PARAM,
// Control
case CMD_SET_CONTROL:
config.bSmartControl = pkt.by[0] ? true : false;
config.bNightControl = pkt.by[1] ? true : false;
config.bControlTemperature = pkt.by[2] ? true : false;
config.bControlHumidity = pkt.by[3] ? true : false;
break;
case CMD_GET_CONTROL:
pkt.by[0] = config.bSmartControl ? 0xFF : 0;
pkt.by[1] = config.bNightControl ? 0xFF : 0;
pkt.by[2] = config.bControlTemperature ? 0xFF : 0;
pkt.by[3] = config.bControlHumidity ? 0xFF : 0;
SendPacket(pkt);
break;
[CMD_SET_CONTROL] = &&L_CMD_SET_CONTROL,
[CMD_GET_CONTROL] = &&L_CMD_GET_CONTROL,
// Operation
case CMD_SET_TEMP_TARGET:
config.nTempTarget = pkt.u16[0];
ESP_LOGI(TAG_WIFI_HOST,"WiFi - TempTarget changed to: %d\n", pkt.u16[0]);
break;
case CMD_SET_TEMP_TARGET_NIGHT:
config.nTempTargetNight = pkt.u16[0];
ESP_LOGI(TAG_WIFI_HOST,"WiFi - TempTargetNight changed to: %d\n", pkt.u16[0]);
break;
case CMD_SET_HUMID_TARGET:
config.nHumidTarget = pkt.u16[0];
ESP_LOGI(TAG_WIFI_HOST,"WiFi - HumidTarget changed to: %d\n", pkt.u16[0]);
break;
case CMD_SET_SENSOR_OFFSET:
config.nTemp1Offset = pkt.n16[0];
config.nHumid1Offset = pkt.n16[1];
if (pkt.n16[2] > 1) {
config.nTemp2Offset = pkt.n16[2];
config.nHumid2Offset = pkt.n16[3];
if (pkt.n16[2] > 2)
config.nTemp3Offset = pkt.n16[4];
}
ESP_LOGI(TAG_WIFI_HOST,"WiFi - SensorOffset changed to: %d, %d\n", pkt.n16[0], pkt.n16[1]);
break;
// Set
[CMD_SET_TEMP_TARGET] = &&L_CMD_SET_TEMP_TARGET,
[CMD_SET_TEMP_TARGET_NIGHT] = &&L_CMD_SET_TEMP_TARGET_NIGHT,
[CMD_SET_HUMID_TARGET] = &&L_CMD_SET_HUMID_TARGET,
[CMD_SET_SENSOR_OFFSET] = &&L_CMD_SET_SENSOR_OFFSET,
[CMD_SET_HEATER1_DUTY] = &&L_CMD_SET_HEATER1_DUTY,
[CMD_SET_MANUAL_HEATER1] = &&L_CMD_SET_MANUAL_HEATER1,
[CMD_SET_HEATER2_DUTY] = &&L_CMD_SET_HEATER2_DUTY,
[CMD_SET_MANUAL_HEATER2] = &&L_CMD_SET_MANUAL_HEATER2,
[CMD_SET_MIST_DUTY] = &&L_CMD_SET_MIST_DUTY,
[CMD_SET_MANUAL_MIST] = &&L_CMD_SET_MANUAL_MIST,
[CMD_SET_FAN_DUTY] = &&L_CMD_SET_FAN_DUTY,
[CMD_SET_MANUAL_FAN] = &&L_CMD_SET_MANUAL_FAN,
[CMD_SET_MOTOR_DUTY] = &&L_CMD_SET_MOTOR_DUTY,
[CMD_SET_MANUAL_MOTOR] = &&L_CMD_SET_MANUAL_MOTOR,
[CMD_SET_LIGHT_DUTY] = &&L_CMD_SET_LIGHT_DUTY,
[CMD_SET_MANUAL_LIGHT] = &&L_CMD_SET_MANUAL_LIGHT,
[CMD_SET_TIME_NIGHT] = &&L_CMD_SET_TIME_NIGHT,
[CMD_SET_WIFI_CLIENT_DISPLAY] = &&L_CMD_SET_WIFI_CLIENT_DISPLAY,
case CMD_SET_AC1_PARAM:
config.ac1 = pkt.device;
break;
case CMD_SET_AC2_PARAM:
config.ac2 = pkt.device;
break;
case CMD_SET_MIST_PARAM:
config.mist = pkt.device;
break;
case CMD_SET_FAN_PARAM:
config.fan = pkt.device;
break;
case CMD_SET_MOTOR_PARAM:
config.motor = pkt.device;
break;
case CMD_SET_LIGHT_PARAM:
config.light = pkt.device;
break;
// PID
[CMD_INIT_PID_PARAM] = &&L_CMD_INIT_PID_PARAM,
[CMD_LOAD_PID_PARAM] = &&L_CMD_LOAD_PID_PARAM,
[CMD_SAVE_PID_PARAM] = &&L_CMD_SAVE_PID_PARAM,
[CMD_SET_PID] = &&L_CMD_SET_PID,
[CMD_GET_PID] = &&L_CMD_GET_PID
};
// Status
case CMD_SET_HEATER1_DUTY:
status.nHeater1Duty = pkt.u16[0];
if (pkt.u16[1])
status.nFlags |= FLAG_MANUAL_HEATER1;
else
status.nFlags &= ~FLAG_MANUAL_HEATER1;
if (status.nHeater1Duty == 0) {
setHeater1Duty(0);
}
break;
case CMD_SET_HEATER2_DUTY:
status.nHeater2Duty = pkt.u16[0];
if (pkt.u16[1])
status.nFlags |= FLAG_MANUAL_HEATER2;
else
status.nFlags &= ~FLAG_MANUAL_HEATER2;
if (status.nHeater2Duty == 0) {
setHeater2Duty(0);
}
break;
case CMD_SET_MIST_DUTY:
status.nMistDuty = pkt.u16[0];
if (pkt.u16[1])
status.nFlags |= FLAG_MANUAL_MIST;
else
status.nFlags &= ~FLAG_MANUAL_MIST;
break;
case CMD_SET_FAN_DUTY:
status.nFanDuty = pkt.u16[0];
if (pkt.u16[1])
status.nFlags |= FLAG_MANUAL_FAN;
else
status.nFlags &= ~FLAG_MANUAL_FAN;
// Bounds check to prevent illegal memory access
if (pkt.cmd >= CMD_COUNT || pkt.cmd <= 0) goto L_DEFAULT;
DPRINTF("[HOST] CMD(%d) OP(%d) LEN(%d) U[%d][%d][%d][%d]\n",
pkt.cmd, pkt.op, pkt.len, pkt.u16[0], pkt.u16[1], pkt.u16[2], pkt.u16[3]);
break;
case CMD_SET_MOTOR_DUTY:
status.nMotorDuty = pkt.u16[0];
if (pkt.u16[1])
status.nFlags |= FLAG_MANUAL_MOTOR;
else
status.nFlags &= ~FLAG_MANUAL_MOTOR;
break;
case CMD_SET_LIGHT_DUTY:
status.nLightTargetDuty = pkt.u16[0];
if (pkt.u16[1])
status.nFlags |= FLAG_MANUAL_LIGHT;
else
status.nFlags &= ~FLAG_MANUAL_LIGHT;
break;
// Direct jump
goto *jump_table[pkt.cmd];
// Manual Operation
case CMD_SET_MANUAL_HEATER1:
if (pkt.u16[0])
status.nFlags |= FLAG_MANUAL_HEATER1;
else
status.nFlags &= ~FLAG_MANUAL_HEATER1;
break;
case CMD_SET_MANUAL_HEATER2:
if (pkt.u16[0])
status.nFlags |= FLAG_MANUAL_HEATER2;
else
status.nFlags &= ~FLAG_MANUAL_HEATER2;
break;
case CMD_SET_MANUAL_MIST:
if (pkt.u16[0])
status.nFlags |= FLAG_MANUAL_MIST;
else
status.nFlags &= ~FLAG_MANUAL_MIST;
break;
case CMD_SET_MANUAL_FAN:
if (pkt.u16[0])
status.nFlags |= FLAG_MANUAL_FAN;
else
status.nFlags &= ~FLAG_MANUAL_FAN;
break;
case CMD_SET_MANUAL_LIGHT:
if (pkt.u16[0])
status.nFlags |= FLAG_MANUAL_LIGHT;
else
status.nFlags &= ~FLAG_MANUAL_LIGHT;
break;
L_CMD_HEARTBEAT:
m_nLastReceivedTime = millis();
return;
// Time
case CMD_SET_TIME_NIGHT:
config.nNightStartHour = pkt.u16[0];
config.nNightStartMin = pkt.u16[1];
config.nNightEndHour = pkt.u16[2];
config.nNightEndMin = pkt.u16[3];
break;
case CMD_SET_WIFI_CLIENT_DISPLAY:
config.m_nDisplayTempHigh = pkt.n16[0];
config.m_nDisplayTempLow = pkt.n16[1];
config.m_nDisplayTime = pkt.n16[2];
config.m_fShowRealTime = pkt.n16[3];
config.m_fShowHistory = pkt.n16[4];
ESP_LOGI(TAG_WIFI_HOST,"WiFi - Client Display Settings changed.");
break;
L_CMD_HELLO:
DPRINTLN("[WiFi] HELLO received");
pkt.u16[0] = SIGNATURE1;
pkt.n16[1] = (int16_t)sizeof(CONFIG_TYPE);
pkt.u16[2] = SIGNATURE2;
SendPacket(pkt);
SendData((uint8_t*)&config, sizeof(CONFIG_TYPE));
m_bHelloSent = true;
return;
default:
ESP_LOGI(TAG_WIFI_HOST,"WiFi - Packet Received Type: %d\n", pkt.cmd);
break;
L_CMD_DROP_CONNECTION:
wifiClient.stop();
m_bClientConnected = false;
m_nMode = MODE_WAITING;
DPRINTLN("[WiFI] Host - Client requests to DROP CONNECTION");
return;
L_CMD_RESET_REASON:
pkt.n16[0] = (int16_t)esp_reset_reason();
SendPacket(pkt);
return;
L_CMD_RESTART:
if (pkt.u16[0] == SIGNATURE1 && pkt.u16[1] == SIGNATURE2) {
if (pkt.op)
config.save();
pkt.cmd = CMD_DROP_CONNECTION;
SendPacket(pkt);
Restart();
}
return;
L_CMD_SEND_HISTORY:
if (pkt.u16[0] == SIGNATURE1 && pkt.u16[1] == SIGNATURE2) {
int16_t count = history.getRingCount();
if (count > 0 ) {
pkt.op = count;
SendPacket(pkt);
int16_t size = history.getRingSize();
if (count < size) {
SendData(history.getRingData1(), sizeof(STATUS_TYPE) * count);
} else {
int count1st = size - history.getRingTail();
SendData(history.getRingData1(), sizeof(STATUS_TYPE) * count1st);
m_bSendHistoryPending = true;
m_nPendingHistoryCount = history.getRingHead();
}
}
}
return;
L_CMD_RESET_SENSOR:
aht25.setScanFlag(true);
aht10_0x39.setScanFlag(true);
return;
L_CMD_RESET_DISPLAY:
return;
L_CMD_INIT_CONFIG:
if (pkt.u16[0] == SIGNATURE1 && pkt.u16[1] == sizeof(CONFIG_STRUCT) && pkt.u16[2] == SIGNATURE2) {
config.init();
config.save();
}
return;
L_CMD_LOAD_CONFIG:
if (pkt.u16[0] == SIGNATURE1 && pkt.u16[1] == sizeof(CONFIG_STRUCT) && pkt.u16[2] == SIGNATURE2) {
config.load();
history.loadPID();
}
return;
L_CMD_SAVE_CONFIG:
if (pkt.u16[0] == SIGNATURE1 && pkt.u16[1] == sizeof(CONFIG_STRUCT) && pkt.u16[2] == SIGNATURE2) {
config.save();
}
return;
L_CMD_RECV_CONFIG:
if (pkt.u16[0] == SIGNATURE1 && pkt.u16[1] == sizeof(CONFIG_STRUCT) && pkt.u16[2] == SIGNATURE2) {
ReceiveData((uint8_t *)&configCopy, sizeof(CONFIG_TYPE));
m_bReceiveConfigPending = true;
m_bSaveReceivedConfig = pkt.op ? true : false;
DPRINTLN("[WiFi] Host - Receive Config initiated...");
}
return;
L_CMD_SEND_CONFIG:
if (pkt.u16[0] == SIGNATURE1 && pkt.u16[1] == sizeof(CONFIG_STRUCT) && pkt.u16[2] == SIGNATURE2) {
SendPacket(pkt);
SendData((const uint8_t *)&config, sizeof(config));
DPRINTLN("[WiFi] Host - Send Config initiated...");
}
return;
L_CMD_SET_DEVICE_PARAM:
config.deviceParamArray[pkt.op] = pkt.device;
return;
L_CMD_GET_DEVICE_PARAM:
pkt.device = config.deviceParamArray[pkt.op];
return;
L_CMD_GET_CONTROL:
pkt.by[0] = config.bSmartControl ? 0xFF : 0x00;
pkt.by[1] = config.bNightControl ? 0xFF : 0x00;
pkt.by[2] = config.bControlTemperature ? 0xFF : 0x00;
pkt.by[3] = config.bControlHumidity ? 0xFF : 0x00;
SendPacket(pkt);
return;
L_CMD_SET_CONTROL:
config.bSmartControl = pkt.by[0] ? true : false;
config.bNightControl = pkt.by[1] ? true : false;
config.bControlTemperature = pkt.by[2] ? true : false;
config.bControlHumidity = pkt.by[3] ? true : false;
return;
L_CMD_SET_TEMP_TARGET:
config.nTempTarget = pkt.u16[0];
config.nTempTargetNight = pkt.u16[1];
return;
L_CMD_SET_TEMP_TARGET_NIGHT:
config.nTempTargetNight = pkt.u16[0];
return;
L_CMD_SET_HUMID_TARGET:
config.nHumidTarget = pkt.u16[0];
return;
L_CMD_SET_SENSOR_OFFSET:
config.nTemp1Offset = pkt.n16[0];
config.nTemp2Offset = pkt.n16[1];
config.nTemp3Offset = pkt.n16[2];
config.nHumid1Offset = pkt.n16[3];
config.nHumid2Offset = pkt.n16[4];
//config.nHumid3Offset = pkt.n16[5]; T3 = NTC No Humidity
return;
L_CMD_SET_HEATER1_DUTY:
status.nHeater1Duty = pkt.u16[0];
L_CMD_SET_MANUAL_HEATER1:
if (pkt.u16[1]) status.nFlags |= FLAG_MANUAL_HEATER1;
else status.nFlags &= ~FLAG_MANUAL_HEATER1;
if (status.nHeater1Duty == 0) setHeater1Duty(0);
return;
L_CMD_SET_HEATER2_DUTY:
status.nHeater2Duty = pkt.u16[0];
L_CMD_SET_MANUAL_HEATER2:
if (pkt.u16[1]) status.nFlags |= FLAG_MANUAL_HEATER2;
else status.nFlags &= ~FLAG_MANUAL_HEATER2;
if (status.nHeater2Duty == 0) setHeater2Duty(0);
return;
L_CMD_SET_MIST_DUTY:
status.nMistDuty = pkt.u16[0];
L_CMD_SET_MANUAL_MIST:
if (pkt.u16[1]) status.nFlags |= FLAG_MANUAL_MIST;
else status.nFlags &= ~FLAG_MANUAL_MIST;
return;
L_CMD_SET_FAN_DUTY:
status.nFanDuty = pkt.u16[0];
L_CMD_SET_MANUAL_FAN:
if (pkt.u16[1]) status.nFlags |= FLAG_MANUAL_FAN;
else status.nFlags &= ~FLAG_MANUAL_FAN;
return;
L_CMD_SET_MOTOR_DUTY:
status.nMotorDuty = pkt.u16[0];
L_CMD_SET_MANUAL_MOTOR:
if (pkt.u16[1]) status.nFlags |= FLAG_MANUAL_MOTOR;
else status.nFlags &= ~FLAG_MANUAL_MOTOR;
return;
L_CMD_SET_LIGHT_DUTY:
status.nLightTargetDuty = pkt.u16[0];
L_CMD_SET_MANUAL_LIGHT:
if (pkt.u16[1]) status.nFlags |= FLAG_MANUAL_LIGHT;
else status.nFlags &= ~FLAG_MANUAL_LIGHT;
return;
L_CMD_SET_TIME_NIGHT:
config.nNightStartHour = pkt.u16[0];
config.nNightStartMin = pkt.u16[1];
config.nNightEndHour = pkt.u16[2];
config.nNightEndMin = pkt.u16[3];
return;
L_CMD_SET_WIFI_CLIENT_DISPLAY:
config.m_nDisplayTempHigh = pkt.n16[0];
config.m_nDisplayTempLow = pkt.n16[1];
config.m_nDisplayTime = pkt.n16[2];
config.m_fShowRealTime = pkt.n16[3];
config.m_fShowHistory = pkt.n16[4];
return;
L_CMD_INIT_PID_PARAM:
L_CMD_SAVE_PID_PARAM:
history.savePID();
return;
L_CMD_LOAD_PID_PARAM:
history.loadPID();
return;
L_CMD_SET_PID:
config.Kp_Temp1 = f16tof32(pkt.u16[0]);
config.Kd_Temp1 = f16tof32(pkt.u16[1]);
config.LR_Temp1 = f16tof32(pkt.u16[2]);
config.Kp_Temp2 = f16tof32(pkt.u16[3]);
config.Kd_Temp2 = f16tof32(pkt.u16[4]);
config.LR_Temp2 = f16tof32(pkt.u16[5]);
config.Kp_Temp3 = f16tof32(pkt.u16[6]);
config.Kd_Temp3 = f16tof32(pkt.u16[7]);
config.LR_Temp3 = f16tof32(pkt.u16[8]);
config.Kp_Humidity = f16tof32(pkt.u16[9]);
config.Kd_Humidity = f16tof32(pkt.u16[10]);
config.LR_Humidity = f16tof32(pkt.u16[11]);
config.Kp_Humid2 = f16tof32(pkt.u16[12]);
config.Kd_Humid2 = f16tof32(pkt.u16[13]);
config.LR_Humid2 = f16tof32(pkt.u16[14]);
config.Kp_Humid3 = f16tof32(pkt.u16[15]);
config.Kd_Humid3 = f16tof32(pkt.u16[16]);
config.LR_Humid3 = f16tof32(pkt.u16[17]);
history.loadPID();
return;
L_CMD_GET_PID:
pkt.u16[0] = f32tof16(config.Kp_Temp1);
pkt.u16[1] = f32tof16(config.Kd_Temp1);
pkt.u16[2] = f32tof16(config.LR_Temp1);
pkt.u16[3] = f32tof16(config.Kp_Temp2);
pkt.u16[4] = f32tof16(config.Kd_Temp2);
pkt.u16[5] = f32tof16(config.LR_Temp2);
pkt.u16[6] = f32tof16(config.Kp_Temp3);
pkt.u16[7] = f32tof16(config.Kd_Temp3);
pkt.u16[8] = f32tof16(config.LR_Temp3);
pkt.u16[9] = f32tof16(config.Kp_Humidity);
pkt.u16[10] = f32tof16(config.Kd_Humidity);
pkt.u16[11] = f32tof16(config.LR_Humidity);
pkt.u16[12] = f32tof16(config.Kp_Humid2);
pkt.u16[13] = f32tof16(config.Kd_Humid2);
pkt.u16[14] = f32tof16(config.LR_Humid2);
pkt.u16[15] = f32tof16(config.Kp_Humid3);
pkt.u16[16] = f32tof16(config.Kd_Humid3);
pkt.u16[17] = f32tof16(config.LR_Humid3);
SendPacket(pkt);
return;
L_DEFAULT:
DPRINTF("[WiFi] Host - Unknown Packet: %d\n", pkt.cmd);
return;
}
IRAM_ATTR
int CWiFiHost::SendPacket(TCP_PACKET& pkt)
IRAM_ATTR int CWiFiHost::SendPacket(TCP_PACKET& pkt)
{
size_t sent = 0;
if (m_bClientConnected && wifiClient && wifiClient.connected())
@ -720,23 +756,21 @@ int CWiFiHost::SendPacket(TCP_PACKET& pkt)
return sent;
}
IRAM_ATTR
size_t CWiFiHost::SendData(const uint8_t* data, size_t size) {
IRAM_ATTR size_t CWiFiHost::SendData(const uint8_t* data, size_t size) {
if (data != nullptr) {
m_nMode = MODE_SEND;
m_pDataSend_data = (char *) data;
m_nDataSend_size = size;
m_nDataSend_sent = 0;
ESP_LOGI(TAG_WIFI_HOST,"WfFi Host - SendData(size: %d)\n", size);
DPRINTF("[HOST] Host - SendData(size: %d)\n", size);
return size;
}
return 0;
}
IRAM_ATTR
// This function sends a small "chunk" then returns false.
// It returns true ONLY when the entire buffer is finished.
bool CWiFiHost::SendData(unsigned long clock)
IRAM_ATTR bool CWiFiHost::SendData(unsigned long clock)
{
if (!m_pDataSend_data || m_nDataSend_size == 0) return true;
@ -766,8 +800,7 @@ bool CWiFiHost::SendData(unsigned long clock)
return true;
}
IRAM_ATTR
size_t CWiFiHost::ReceiveData(uint8_t* data, size_t size)
IRAM_ATTR size_t CWiFiHost::ReceiveData(uint8_t* data, size_t size)
{
m_nMode = MODE_RECV;
m_pDataReceive_data = (char *) data;
@ -776,8 +809,7 @@ size_t CWiFiHost::ReceiveData(uint8_t* data, size_t size)
return size;
}
IRAM_ATTR
bool CWiFiHost::ReceiveData(unsigned long clock)
MY_IRAM_ATTR bool CWiFiHost::ReceiveData(unsigned long clock)
{
// Receive Data
size_t nSize = 0;
@ -806,22 +838,25 @@ bool CWiFiHost::ReceiveData(unsigned long clock)
if (m_bReceiveConfigPending && m_pDataReceive_data == (char *)&configCopy) {
config = configCopy;
history.loadPID();
ESP_LOGI(TAG_WIFI_HOST,"WiFi - Config Received");
DPRINTLN("[WiFi] Host - Config Received");
m_bReceiveConfigPending = false;
if (m_bSaveReceivedConfig) {
config.save();
m_bSaveReceivedConfig = false;
}
}
ESP_LOGI(TAG_WIFI_HOST," ReceiveData: Data Receive Completed!");
DPRINTLN("[WIFI] Host - ReceiveData: Data Receive Completed!");
return true;
}
if (nSize <= 0 && clock - m_nLastReceivedTime > 5000) {
ESP_LOGI(TAG_WIFI_HOST," ReceiveData: TimeOut Abort!");
DPRINTLN("[WIFI] Host - ReceiveData: TimeOut Abort!");
return true;
}
return false;
}
IRAM_ATTR
void CWiFiHost::SendHeartBeat() {
IRAM_ATTR void CWiFiHost::SendHeartBeat() {
if (m_bHelloSent) {
hostPacket.cmd = CMD_HEARTBEAT;
time_t now = time(NULL); // Get current time in seconds

View File

@ -46,97 +46,58 @@ enum OPERATION_MODE {
enum ENUM_COMMAND
{
// Command
// Connection & control
CMD_HEARTBEAT = 1, // 1 HeartBeat - prevents disconnect from the host
// Connection
CMD_HELLO = 101, // 0 Hello
CMD_HELLO, // 0 Hello
CMD_DROP_CONNECTION,
CMD_RESET_REASON,
// Device Command
CMD_SAVE_RESTART = 201,
CMD_RESET_RESTART,
CMD_RESTART,
CMD_SEND_HISTORY,
CMD_PAUSE,
CMD_RESUME,
CMD_RESET_SENSOR,
CMD_RESET_DISPLAY,
// OTA Update
CMD_UPDATE_CHECK = 301,
CMD_UPDATE_AVAILABLE,
CMD_UPDATE_FORCED,
// Config
CMD_INIT_CONFIG = 1201,
CMD_INIT_CONFIG,
CMD_LOAD_CONFIG,
CMD_SAVE_CONFIG,
CMD_SEND_CONFIG,
CMD_RECV_CONFIG,
CMD_SEND_CONFIG_SERVER,
CMD_LOAD_CONFIG_SERVER,
CMD_SET_DEVICE_PARAM,
CMD_GET_DEVICE_PARAM,
// control
CMD_SET_CONTROL,
CMD_GET_CONTROL,
// Set
CMD_SET_TEMP_TARGET,
CMD_SET_TEMP_TARGET_NIGHT,
CMD_SET_HUMID_TARGET,
CMD_SET_SENSOR_OFFSET,
CMD_SET_HEATER1_DUTY,
CMD_SET_MANUAL_HEATER1,
CMD_SET_HEATER2_DUTY,
CMD_SET_MANUAL_HEATER2,
CMD_SET_MIST_DUTY,
CMD_SET_MANUAL_MIST,
CMD_SET_FAN_DUTY,
CMD_SET_MANUAL_FAN,
CMD_SET_MOTOR_DUTY,
CMD_SET_MANUAL_MOTOR,
CMD_SET_LIGHT_DUTY,
CMD_SET_MANUAL_LIGHT,
CMD_SET_TIME_NIGHT,
CMD_SET_WIFI_CLIENT_DISPLAY, // Graph TempHigh, TempLow, TimeScale etc.
// PID
CMD_INIT_PID_PARAM = 1301,
CMD_INIT_PID_PARAM,
CMD_LOAD_PID_PARAM,
CMD_SAVE_PID_PARAM,
CMD_SET_PID,
CMD_GET_PID,
// Control
CMD_SET_CONTROL = 1401,
CMD_GET_CONTROL,
// Operation
CMD_SET_TEMP_TARGET = 1501,
CMD_SET_TEMP_TARGET_NIGHT,
CMD_SET_HUMID_TARGET,
CMD_SET_SENSOR_OFFSET,
CMD_SET_AC1_PARAM,
CMD_SET_AC2_PARAM,
CMD_SET_MIST_PARAM,
CMD_SET_FAN_PARAM,
CMD_SET_MOTOR_PARAM,
CMD_SET_LIGHT_PARAM,
// Status
CMD_SET_HEATER1_DUTY = 2101,
CMD_SET_HEATER2_DUTY,
CMD_SET_MIST_DUTY,
CMD_SET_FAN_DUTY,
CMD_SET_FAN_DUTY_AUTO,
CMD_SET_MOTOR_DUTY,
CMD_SET_MOTOR_DUTY_AUTO,
CMD_SET_LIGHT_DUTY,
// Manual Operations
CMD_SET_MANUAL_HEATER1 = 2201,
CMD_SET_MANUAL_HEATER2,
CMD_SET_MANUAL_MIST,
CMD_SET_MANUAL_FAN,
CMD_SET_MANUAL_MOTOR,
CMD_SET_MANUAL_LIGHT,
// Time
CMD_SET_TIME_HEATER1 = 2301,
CMD_SET_TIME_HEATER2,
CMD_SET_TIME_MIST,
CMD_SET_TIME_FAN,
CMD_SET_TIME_MOTOR,
CMD_SET_TIME_LIGHT,
CMD_SET_TIME_NIGHT,
// UI
CMD_SET_WIFI_CLIENT_DISPLAY = 2401, // Graph TempHigh, TempLow, TimeScale etc.
CMD_SET_OLED_CONTRAST,
CMD_SET_OLED_DISPLAY_CHECKAC,
// Debugging
CMD_HELLO_DEBUG = 9101,
CMD_SHOW_CODE,
COMPUTE_TIME_MAX,
CMD_INVALID = 9999
// End of valid command
CMD_COUNT
};
#pragma pack(push) /* push current alignment to stack */
@ -157,6 +118,7 @@ typedef struct TCP_PACKET_STRUCT
int32_t n32[10];
uint32_t u32[10];
float f[10];
float f16[20];
STATUS_TYPE status;
DEVICE_PARAM_TYPE device;
}; //40 : 52
@ -250,6 +212,7 @@ private:
size_t m_nDataReceive_received;
bool m_bReceiveConfigPending;
bool m_bSaveReceivedConfig;
bool m_bSendHistoryPending;
int16_t m_nPendingHistoryCount;

27
zcd.cpp
View File

@ -26,9 +26,6 @@
#define EFFECTIVE_POWER 0.86
#define LEADING_TIME_RATIO 0.06
#define PHASE_CONTROL 0
#define ZCD_CONTROL 1
// ESP32 Clock Constants
const uint32_t AC_CYCLE_TIME_CLOCKS = 8333; // Half cycle of 60Hz AC in clock cycles
const uint32_t EFFECTIVE_HALF_CYCLE = EFFECTIVE_POWER * AC_CYCLE_TIME_CLOCKS; // Effective half cycle in clock cycles
@ -103,7 +100,7 @@ short getHeater2Duty() {
}
// Function to set the duty based on percentage (0 to 10000)
void IRAM_ATTR setHeater1Duty(short duty) {
MY_IRAM_ATTR void setHeater1Duty(short duty) {
if (ac1ControlMode == ZCD_CONTROL) {
if (duty > 10000) duty = 10000;
dutyAC1TableIndex = (uint8_t)((duty + 10000/32)/625);
@ -130,11 +127,11 @@ void IRAM_ATTR setHeater1Duty(short duty) {
uint32_t nDuty = duty * PWM_FULL / 10000;
ledcWrite(PIN_LED_HEATER1, PWM_FULL - nDuty);
ESP_LOGD(TAG_ZCD,"Set Duty: %.2f%%, Timer Count: %u clock cycles", duty, dutyHeater1);
//DPRINTF("[ZCD] Set Duty: %.2f%%, Timer Count: %u clock cycles", duty, dutyHeater1);
}
// Function to set the duty based on percentage (0 to 10000)
void IRAM_ATTR setHeater2Duty(short duty) {
MY_IRAM_ATTR void setHeater2Duty(short duty) {
if (config.bAC2_OnOff) {
if (duty >= 10000) {
duty = 10000;
@ -171,19 +168,9 @@ void IRAM_ATTR setHeater2Duty(short duty) {
uint32_t nDuty = duty * PWM_FULL / 10000;
ledcWrite(PIN_LED_HEATER2, PWM_FULL - nDuty);
ESP_LOGD(TAG_ZCD,"Set Duty: %.2f%%, Timer Count: %u clock cycles\n", duty, dutyHeater2);
//DPRINTF("[ZCD] Set Duty: %.2f%%, Timer Count: %u clock cycles\n", duty, dutyHeater2);
}
#define SET_TIMER_0_SAFE(duty) do { \
timerWrite(timerHeater1, 0); \
timerAlarm(timerHeater1, duty, false, 0); \
} while(0)
#define SET_TIMER_1_SAFE(duty) do { \
timerWrite(timerHeater2, 0); \
timerAlarm(timerHeater2, duty, false, 0); \
} while(0)
void IRAM_ATTR timer0ISR(void *) {
#ifdef DEBUG_ZCD
zcdLoadISRCount++;
@ -233,7 +220,7 @@ void IRAM_ATTR timer1ISR(void *)
// Zero-Cross Detection Interrupt Service Routine
void IRAM_ATTR zcdACISR(void *) {
// 1. Power side AC ZCD Count
zcdACISRCount++;
zcdACISRCount = zcdACISRCount + 1;
fireStatusTimer0 = 0;
fireStatusTimer1 = 0;
@ -267,13 +254,13 @@ void IRAM_ATTR zcdACISR(void *) {
timer_set_alarm(TIMER_GROUP_1, TIMER_1, TIMER_ALARM_EN);
fire_enable_2 = true;
}
seqStep = ++seqStep & 0x0F;
seqStep = (seqStep + 1) & 0x0F;
}
void IRAM_ATTR zcdLoadISR(void *) {
// Load side AC ZCD Count
#ifndef DEBUG_ZCD
zcdLoadISRCount++;
zcdLoadISRCount = zcdLoadISRCount + 1;
#endif
}

13
zcd.h
View File

@ -3,17 +3,16 @@
// ZCD
void setupZCD();
short getHeater1Duty();
void setHeater1Duty(short duty);
void setHeater2Duty(short duty);
short getHeater1Duty();
void IRAM_ATTR zcdACISR(void *);
void IRAM_ATTR zcdLoadISR(void *);
void IRAM_ATTR timer0ISR(void *);
void IRAM_ATTR timer1ISR(void *);
void zcdACISR(void *);
void zcdLoadISR(void *);
void timer0ISR(void *);
void timer1ISR(void *);
#define DEBUG_ZCD
#define ENABLE_TIMERS
//#define DEBUG_ZCD
#if defined(ESP8266)
void setMistDuty(short duty);