mirror of
https://github.com/openshwprojects/OpenBK7231T_App.git
synced 2026-08-18 02:54:53 +00:00
Add support for Gaitek Airconditioner Protocol (#2099)
* Add GaitekAC driver header with function declarations * Add GAITEK AC driver implementation Implement GAITEK AC driver with UART protocol handling and commands. * Add GaitekAC driver integration * Enable GAITEKAC driver in obk_config.h * Add GAITEK AC custom UART driver support * Remove ENABLE_DRIVER_GAITEKAC definition * Re-add GAITEK AC custom UART driver source
This commit is contained in:
@ -3,6 +3,9 @@ OBK_DIR = ../../../../..
|
||||
CFLAGS += -DPLATFORM_RTL87X0C -DPLATFORM_REALTEK -Wno-error=implicit-function-declaration -Wno-error=incompatible-pointer-types -Wno-error=return-mismatch -Wno-error=int-conversion -Wno-error=changes-meaning
|
||||
CFLAGS += -DENABLE_DRIVER_MDNS=1 -DLWIP_MDNS_RESPONDER=1
|
||||
|
||||
# GAITEK AC custom UART driver
|
||||
CFLAGS += -DENABLE_DRIVER_GAITEKAC=1
|
||||
|
||||
# Ensure our lwIP option wrapper is picked before SDK lwipopts.h.
|
||||
INCLUDES := -I$(OBK_DIR)/platforms/RTL87X0C $(INCLUDES)
|
||||
|
||||
@ -27,6 +30,10 @@ SRC_C += $(OBK_DIR)/src/hal/realtek/hal_ota_realtek.c
|
||||
OBK_SRCS = $(OBK_DIR)/src/
|
||||
include $(OBK_DIR)/platforms/obk_main.mk
|
||||
SRC_C += $(OBKM_SRC)
|
||||
|
||||
# GAITEK AC custom UART driver source
|
||||
SRC_C += $(OBK_DIR)/src/driver/drv_gaitekAC.c
|
||||
|
||||
SRC_CPP += $(OBKM_SRC_CXX)
|
||||
CFLAGS += $(OBK_CFLAGS) -D__FILE__=\"\" -Wno-builtin-macro-redefined
|
||||
CPPFLAGS += $(INCLUDES) -fpermissive
|
||||
|
||||
516
src/driver/drv_gaitekAC.c
Normal file
516
src/driver/drv_gaitekAC.c
Normal file
@ -0,0 +1,516 @@
|
||||
#include "../obk_config.h"
|
||||
|
||||
#if ENABLE_DRIVER_GAITEKAC
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../cmnds/cmd_public.h"
|
||||
#include "../httpserver/new_http.h"
|
||||
#include "drv_uart.h"
|
||||
#include "drv_gaitekAC.h"
|
||||
|
||||
#if ENABLE_MQTT
|
||||
#include "../mqtt/new_mqtt.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* GAITEK AC UART protocol
|
||||
*
|
||||
* UART: 9600 8N1
|
||||
*
|
||||
* OpenRTL -> AC:
|
||||
* "GAITEK" BD CMD VAL 00 00 00 CMD CHK
|
||||
* CHK = XOR(BD CMD VAL 00 00 00 CMD)
|
||||
*
|
||||
* AC -> OpenRTL:
|
||||
* "GAITEK" BD PP FF MF RT ST 20 20 TM 00 AUX CHK "KETIAG"
|
||||
* CHK = XOR(BD..AUX)
|
||||
*
|
||||
* PP = power, 00 off, 01 on
|
||||
* FF = flags, bit 0x04 = night/sleep mode
|
||||
* MF = fan/mode, high nibble fan, low nibble mode
|
||||
* fan: 1 high, 2 medium, 3 low
|
||||
* mode: 1 cold/cool, 3 dry, 6 fan only
|
||||
* RT = room temperature in Celsius
|
||||
* ST = set temperature in Celsius
|
||||
* TM = timer hours, 0 disabled
|
||||
*/
|
||||
|
||||
#define GAITEK_CH_POWER 1
|
||||
#define GAITEK_CH_MODE 2
|
||||
#define GAITEK_CH_FAN 3
|
||||
#define GAITEK_CH_NIGHT 4
|
||||
#define GAITEK_CH_SET_TEMP 5
|
||||
#define GAITEK_CH_TIMER 6
|
||||
#define GAITEK_CH_ROOM_TEMP 10
|
||||
|
||||
#define GAITEK_UART_BAUD 9600
|
||||
#define GAITEK_RXBUF_SIZE 256
|
||||
#define GAITEK_FRAME_LEN 24
|
||||
#define GAITEK_BODY_OFF 6
|
||||
#define GAITEK_BODY_LEN 12
|
||||
|
||||
static const byte GAITEK_HEADER[6] = { 'G', 'A', 'I', 'T', 'E', 'K' };
|
||||
static const byte GAITEK_FOOTER[6] = { 'K', 'E', 'T', 'I', 'A', 'G' };
|
||||
|
||||
static byte g_gaitek_rx[GAITEK_FRAME_LEN];
|
||||
static int g_gaitek_rxpos = 0;
|
||||
static int g_gaitek_updating_from_ac = 0;
|
||||
static int g_gaitek_dirty = 1;
|
||||
static int g_gaitek_seconds_since_publish = 999;
|
||||
static int g_gaitek_pending_mode = 0;
|
||||
static int g_gaitek_pending_mode_delay = 0;
|
||||
|
||||
static int g_gaitek_power = 0;
|
||||
static int g_gaitek_mode = 1;
|
||||
static int g_gaitek_fan = 2;
|
||||
static int g_gaitek_night = 0;
|
||||
static int g_gaitek_set_temp_x10 = 220;
|
||||
static int g_gaitek_room_temp_x10 = 0;
|
||||
static int g_gaitek_timer = 0;
|
||||
static int g_gaitek_have_status = 0;
|
||||
|
||||
static byte gaitek_xor(const byte *data, int len) {
|
||||
byte x = 0;
|
||||
for (int i = 0; i < len; i++) {
|
||||
x ^= data[i];
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
static int gaitek_clamp(int val, int minVal, int maxVal) {
|
||||
if (val < minVal) return minVal;
|
||||
if (val > maxVal) return maxVal;
|
||||
return val;
|
||||
}
|
||||
|
||||
static int gaitek_streq(const char *a, const char *b) {
|
||||
while (*a && *b) {
|
||||
char ca = *a++;
|
||||
char cb = *b++;
|
||||
if (ca >= 'A' && ca <= 'Z') ca = ca - 'A' + 'a';
|
||||
if (cb >= 'A' && cb <= 'Z') cb = cb - 'A' + 'a';
|
||||
if (ca != cb) return 0;
|
||||
}
|
||||
return *a == 0 && *b == 0;
|
||||
}
|
||||
|
||||
static const char *gaitek_hvac_mode(void) {
|
||||
if (!g_gaitek_power) return "off";
|
||||
switch (g_gaitek_mode) {
|
||||
case 1: return "cool";
|
||||
case 3: return "dry";
|
||||
case 6: return "fan_only";
|
||||
default: return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
static const char *gaitek_fan_mode(void) {
|
||||
switch (g_gaitek_fan) {
|
||||
case 1: return "high";
|
||||
case 2: return "medium";
|
||||
case 3: return "low";
|
||||
default: return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
static const char *gaitek_preset_mode(void) {
|
||||
return g_gaitek_night ? "sleep" : "none";
|
||||
}
|
||||
|
||||
static void gaitek_mark_dirty(void) {
|
||||
g_gaitek_dirty = 1;
|
||||
}
|
||||
|
||||
static void gaitek_write_channel(int ch, int val) {
|
||||
char tmp[48];
|
||||
snprintf(tmp, sizeof(tmp), "setChannel %i %i", ch, val);
|
||||
CMD_ExecuteCommand(tmp, 0);
|
||||
}
|
||||
|
||||
static void gaitek_sync_channels_from_cache(void) {
|
||||
g_gaitek_updating_from_ac = 1;
|
||||
gaitek_write_channel(GAITEK_CH_POWER, g_gaitek_power);
|
||||
gaitek_write_channel(GAITEK_CH_MODE, g_gaitek_mode);
|
||||
gaitek_write_channel(GAITEK_CH_FAN, g_gaitek_fan);
|
||||
gaitek_write_channel(GAITEK_CH_NIGHT, g_gaitek_night);
|
||||
gaitek_write_channel(GAITEK_CH_SET_TEMP, g_gaitek_set_temp_x10);
|
||||
gaitek_write_channel(GAITEK_CH_TIMER, g_gaitek_timer);
|
||||
gaitek_write_channel(GAITEK_CH_ROOM_TEMP, g_gaitek_room_temp_x10);
|
||||
g_gaitek_updating_from_ac = 0;
|
||||
}
|
||||
|
||||
static void gaitek_build_state_json(char *out, int outLen) {
|
||||
snprintf(out, outLen,
|
||||
"{\"power\":%i,\"hvac_mode\":\"%s\",\"mode\":\"%s\",\"mode_raw\":%i,"
|
||||
"\"fan\":\"%s\",\"fan_raw\":%i,\"night\":%i,\"preset\":\"%s\","
|
||||
"\"set_temp\":%i,\"setTemp\":%i,\"room_temp\":%i,\"roomTemp\":%i,"
|
||||
"\"timer\":%i,\"have_status\":%i,\"haveStatus\":%i}",
|
||||
g_gaitek_power,
|
||||
gaitek_hvac_mode(),
|
||||
gaitek_hvac_mode(),
|
||||
g_gaitek_mode,
|
||||
gaitek_fan_mode(),
|
||||
g_gaitek_fan,
|
||||
g_gaitek_night,
|
||||
gaitek_preset_mode(),
|
||||
g_gaitek_set_temp_x10 / 10,
|
||||
g_gaitek_set_temp_x10,
|
||||
g_gaitek_room_temp_x10 / 10,
|
||||
g_gaitek_room_temp_x10,
|
||||
g_gaitek_timer,
|
||||
g_gaitek_have_status,
|
||||
g_gaitek_have_status);
|
||||
}
|
||||
|
||||
static void gaitek_publish_state(int force) {
|
||||
char json[384];
|
||||
|
||||
gaitek_build_state_json(json, sizeof(json));
|
||||
|
||||
#if ENABLE_MQTT
|
||||
if (force || g_gaitek_dirty || g_gaitek_seconds_since_publish >= 60) {
|
||||
if (MQTT_IsReady()) {
|
||||
MQTT_PublishStat("gaitek_ac", json);
|
||||
g_gaitek_dirty = 0;
|
||||
g_gaitek_seconds_since_publish = 0;
|
||||
}
|
||||
}
|
||||
#else
|
||||
(void)force;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void gaitek_cache_command(byte cmd_id, byte value) {
|
||||
switch (cmd_id) {
|
||||
case 0x00:
|
||||
g_gaitek_power = value ? 1 : 0;
|
||||
break;
|
||||
case 0x05:
|
||||
g_gaitek_night = value ? 1 : 0;
|
||||
break;
|
||||
case 0x06:
|
||||
if (value == 1 || value == 3 || value == 6) g_gaitek_mode = value;
|
||||
break;
|
||||
case 0x07:
|
||||
if (value >= 1 && value <= 3) g_gaitek_fan = value;
|
||||
break;
|
||||
case 0x08:
|
||||
g_gaitek_set_temp_x10 = value * 10;
|
||||
break;
|
||||
case 0x0A:
|
||||
g_gaitek_timer = value;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
gaitek_sync_channels_from_cache();
|
||||
gaitek_mark_dirty();
|
||||
gaitek_publish_state(0);
|
||||
}
|
||||
|
||||
static void gaitek_send_command(byte cmd_id, byte value) {
|
||||
byte frame[14] = {
|
||||
'G', 'A', 'I', 'T', 'E', 'K',
|
||||
0xBD, cmd_id, value, 0x00, 0x00, 0x00, cmd_id, 0x00
|
||||
};
|
||||
|
||||
if (cmd_id != 0xFF) {
|
||||
gaitek_cache_command(cmd_id, value);
|
||||
}
|
||||
|
||||
frame[13] = gaitek_xor(&frame[6], 7);
|
||||
|
||||
for (int i = 0; i < (int)sizeof(frame); i++) {
|
||||
UART_SendByte(frame[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void gaitek_parse_status(const byte *frame) {
|
||||
const byte *body = frame + GAITEK_BODY_OFF;
|
||||
|
||||
if (memcmp(frame, GAITEK_HEADER, 6) != 0) return;
|
||||
if (memcmp(frame + 18, GAITEK_FOOTER, 6) != 0) return;
|
||||
if (body[0] != 0xBD) return;
|
||||
|
||||
byte calc = gaitek_xor(body, GAITEK_BODY_LEN - 1);
|
||||
if (calc != body[11]) return;
|
||||
|
||||
int power = body[1] ? 1 : 0;
|
||||
int flags = body[2];
|
||||
int fanmode = body[3];
|
||||
int fan = (fanmode >> 4) & 0x0F;
|
||||
int mode = fanmode & 0x0F;
|
||||
int roomTempC = body[4];
|
||||
int setTempC = body[5];
|
||||
int timerH = body[8];
|
||||
|
||||
g_gaitek_power = power;
|
||||
g_gaitek_mode = mode;
|
||||
g_gaitek_fan = fan;
|
||||
g_gaitek_night = (flags & 0x04) ? 1 : 0;
|
||||
g_gaitek_set_temp_x10 = setTempC * 10;
|
||||
g_gaitek_room_temp_x10 = roomTempC * 10;
|
||||
g_gaitek_timer = timerH;
|
||||
g_gaitek_have_status = 1;
|
||||
|
||||
gaitek_sync_channels_from_cache();
|
||||
gaitek_mark_dirty();
|
||||
gaitek_publish_state(1);
|
||||
}
|
||||
|
||||
static void gaitek_rx_byte(byte b) {
|
||||
if (g_gaitek_rxpos == 0 && b != 'G') {
|
||||
return;
|
||||
}
|
||||
|
||||
g_gaitek_rx[g_gaitek_rxpos++] = b;
|
||||
|
||||
if (g_gaitek_rxpos <= 6) {
|
||||
if (g_gaitek_rx[g_gaitek_rxpos - 1] != GAITEK_HEADER[g_gaitek_rxpos - 1]) {
|
||||
g_gaitek_rxpos = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_gaitek_rxpos == GAITEK_FRAME_LEN) {
|
||||
gaitek_parse_status(g_gaitek_rx);
|
||||
g_gaitek_rxpos = 0;
|
||||
}
|
||||
else if (g_gaitek_rxpos > GAITEK_FRAME_LEN) {
|
||||
g_gaitek_rxpos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void GaitekAC_RunQuickTick(void) {
|
||||
while (UART_GetDataSize() > 0) {
|
||||
byte b = UART_GetByte(0);
|
||||
UART_ConsumeBytes(1);
|
||||
gaitek_rx_byte(b);
|
||||
}
|
||||
}
|
||||
|
||||
static void gaitek_queue_mode_after_power(byte mode) {
|
||||
g_gaitek_pending_mode = mode;
|
||||
g_gaitek_pending_mode_delay = 1;
|
||||
}
|
||||
|
||||
void GaitekAC_RunEverySecond(void) {
|
||||
g_gaitek_seconds_since_publish++;
|
||||
|
||||
if (g_gaitek_pending_mode) {
|
||||
if (g_gaitek_pending_mode_delay > 0) {
|
||||
g_gaitek_pending_mode_delay--;
|
||||
} else {
|
||||
byte mode = g_gaitek_pending_mode;
|
||||
g_gaitek_pending_mode = 0;
|
||||
gaitek_send_command(0x06, mode);
|
||||
}
|
||||
}
|
||||
|
||||
gaitek_publish_state(0);
|
||||
}
|
||||
|
||||
static int http_gaitekac_status(http_request_t *request) {
|
||||
char json[384];
|
||||
|
||||
http_setup(request, httpMimeTypeJson);
|
||||
gaitek_build_state_json(json, sizeof(json));
|
||||
poststr(request, json);
|
||||
poststr(request, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static commandResult_t CMD_GaitekACPower(const void *context, const char *cmd, const char *args, int cmdFlags) {
|
||||
Tokenizer_TokenizeString(args, 0);
|
||||
if (Tokenizer_GetArgsCount() < 1) return CMD_RES_NOT_ENOUGH_ARGUMENTS;
|
||||
gaitek_send_command(0x00, Tokenizer_GetArgInteger(0) ? 1 : 0);
|
||||
return CMD_RES_OK;
|
||||
}
|
||||
|
||||
static commandResult_t CMD_GaitekACNight(const void *context, const char *cmd, const char *args, int cmdFlags) {
|
||||
Tokenizer_TokenizeString(args, 0);
|
||||
if (Tokenizer_GetArgsCount() < 1) return CMD_RES_NOT_ENOUGH_ARGUMENTS;
|
||||
gaitek_send_command(0x05, Tokenizer_GetArgInteger(0) ? 1 : 0);
|
||||
return CMD_RES_OK;
|
||||
}
|
||||
|
||||
static commandResult_t CMD_GaitekACMode(const void *context, const char *cmd, const char *args, int cmdFlags) {
|
||||
Tokenizer_TokenizeString(args, 0);
|
||||
if (Tokenizer_GetArgsCount() < 1) return CMD_RES_NOT_ENOUGH_ARGUMENTS;
|
||||
|
||||
const char *s = Tokenizer_GetArg(0);
|
||||
int v;
|
||||
|
||||
if (gaitek_streq(s, "cold") || gaitek_streq(s, "cool")) v = 0x01;
|
||||
else if (gaitek_streq(s, "dry")) v = 0x03;
|
||||
else if (gaitek_streq(s, "fan") || gaitek_streq(s, "fan_only")) v = 0x06;
|
||||
else v = Tokenizer_GetArgInteger(0);
|
||||
|
||||
if (v != 0x01 && v != 0x03 && v != 0x06) return CMD_RES_BAD_ARGUMENT;
|
||||
gaitek_send_command(0x06, v);
|
||||
return CMD_RES_OK;
|
||||
}
|
||||
|
||||
static commandResult_t CMD_GaitekACHAMode(const void *context, const char *cmd, const char *args, int cmdFlags) {
|
||||
Tokenizer_TokenizeString(args, 0);
|
||||
if (Tokenizer_GetArgsCount() < 1) return CMD_RES_NOT_ENOUGH_ARGUMENTS;
|
||||
|
||||
const char *s = Tokenizer_GetArg(0);
|
||||
byte mode = 0;
|
||||
|
||||
if (gaitek_streq(s, "off")) {
|
||||
g_gaitek_pending_mode = 0;
|
||||
g_gaitek_pending_mode_delay = 0;
|
||||
gaitek_send_command(0x00, 0);
|
||||
return CMD_RES_OK;
|
||||
}
|
||||
|
||||
if (gaitek_streq(s, "cool") || gaitek_streq(s, "cold")) {
|
||||
mode = 1;
|
||||
}
|
||||
else if (gaitek_streq(s, "dry")) {
|
||||
mode = 3;
|
||||
}
|
||||
else if (gaitek_streq(s, "fan") || gaitek_streq(s, "fan_only")) {
|
||||
mode = 6;
|
||||
}
|
||||
else {
|
||||
return CMD_RES_BAD_ARGUMENT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Smart power logic:
|
||||
* If the AC is already on according to the latest cached/status state,
|
||||
* do not send another power-on command. Just change mode.
|
||||
*
|
||||
* If the AC is off, power it on first and send the requested mode
|
||||
* one second later. Some GAITEK units ignore back-to-back power+mode.
|
||||
*/
|
||||
if (g_gaitek_power) {
|
||||
g_gaitek_pending_mode = 0;
|
||||
g_gaitek_pending_mode_delay = 0;
|
||||
gaitek_send_command(0x06, mode);
|
||||
}
|
||||
else {
|
||||
gaitek_send_command(0x00, 1);
|
||||
gaitek_queue_mode_after_power(mode);
|
||||
}
|
||||
|
||||
return CMD_RES_OK;
|
||||
}
|
||||
|
||||
static commandResult_t CMD_GaitekACFan(const void *context, const char *cmd, const char *args, int cmdFlags) {
|
||||
Tokenizer_TokenizeString(args, 0);
|
||||
if (Tokenizer_GetArgsCount() < 1) return CMD_RES_NOT_ENOUGH_ARGUMENTS;
|
||||
|
||||
const char *s = Tokenizer_GetArg(0);
|
||||
int v;
|
||||
|
||||
if (gaitek_streq(s, "high")) v = 0x01;
|
||||
else if (gaitek_streq(s, "medium") || gaitek_streq(s, "med")) v = 0x02;
|
||||
else if (gaitek_streq(s, "low")) v = 0x03;
|
||||
else v = Tokenizer_GetArgInteger(0);
|
||||
|
||||
if (v < 1 || v > 3) return CMD_RES_BAD_ARGUMENT;
|
||||
gaitek_send_command(0x07, v);
|
||||
return CMD_RES_OK;
|
||||
}
|
||||
|
||||
static commandResult_t CMD_GaitekACPreset(const void *context, const char *cmd, const char *args, int cmdFlags) {
|
||||
Tokenizer_TokenizeString(args, 0);
|
||||
if (Tokenizer_GetArgsCount() < 1) return CMD_RES_NOT_ENOUGH_ARGUMENTS;
|
||||
|
||||
const char *s = Tokenizer_GetArg(0);
|
||||
|
||||
if (gaitek_streq(s, "none") || gaitek_streq(s, "normal") || gaitek_streq(s, "off")) {
|
||||
gaitek_send_command(0x05, 0);
|
||||
return CMD_RES_OK;
|
||||
}
|
||||
if (gaitek_streq(s, "sleep") || gaitek_streq(s, "night") || gaitek_streq(s, "on")) {
|
||||
gaitek_send_command(0x05, 1);
|
||||
return CMD_RES_OK;
|
||||
}
|
||||
|
||||
return CMD_RES_BAD_ARGUMENT;
|
||||
}
|
||||
|
||||
static commandResult_t CMD_GaitekACTemp(const void *context, const char *cmd, const char *args, int cmdFlags) {
|
||||
Tokenizer_TokenizeString(args, 0);
|
||||
if (Tokenizer_GetArgsCount() < 1) return CMD_RES_NOT_ENOUGH_ARGUMENTS;
|
||||
gaitek_send_command(0x08, gaitek_clamp(Tokenizer_GetArgInteger(0), 16, 31));
|
||||
return CMD_RES_OK;
|
||||
}
|
||||
|
||||
static commandResult_t CMD_GaitekACTimer(const void *context, const char *cmd, const char *args, int cmdFlags) {
|
||||
Tokenizer_TokenizeString(args, 0);
|
||||
if (Tokenizer_GetArgsCount() < 1) return CMD_RES_NOT_ENOUGH_ARGUMENTS;
|
||||
gaitek_send_command(0x0A, gaitek_clamp(Tokenizer_GetArgInteger(0), 0, 24));
|
||||
return CMD_RES_OK;
|
||||
}
|
||||
|
||||
static commandResult_t CMD_GaitekACRefresh(const void *context, const char *cmd, const char *args, int cmdFlags) {
|
||||
gaitek_send_command(0xFF, 0x01);
|
||||
return CMD_RES_OK;
|
||||
}
|
||||
|
||||
static commandResult_t CMD_GaitekACPublish(const void *context, const char *cmd, const char *args, int cmdFlags) {
|
||||
gaitek_publish_state(1);
|
||||
return CMD_RES_OK;
|
||||
}
|
||||
|
||||
void GaitekAC_OnChannelChanged(int ch, int val) {
|
||||
if (g_gaitek_updating_from_ac) return;
|
||||
|
||||
switch (ch) {
|
||||
case GAITEK_CH_POWER:
|
||||
gaitek_send_command(0x00, val ? 1 : 0);
|
||||
break;
|
||||
case GAITEK_CH_MODE:
|
||||
if (val == 0x01 || val == 0x03 || val == 0x06) gaitek_send_command(0x06, val);
|
||||
break;
|
||||
case GAITEK_CH_FAN:
|
||||
if (val >= 1 && val <= 3) gaitek_send_command(0x07, val);
|
||||
break;
|
||||
case GAITEK_CH_NIGHT:
|
||||
gaitek_send_command(0x05, val ? 1 : 0);
|
||||
break;
|
||||
case GAITEK_CH_SET_TEMP:
|
||||
gaitek_send_command(0x08, gaitek_clamp((val + 5) / 10, 16, 31));
|
||||
break;
|
||||
case GAITEK_CH_TIMER:
|
||||
gaitek_send_command(0x0A, gaitek_clamp(val, 0, 24));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void GaitekAC_Init(void) {
|
||||
UART_InitReceiveRingBuffer(GAITEK_RXBUF_SIZE);
|
||||
UART_InitUART(GAITEK_UART_BAUD, 0, false);
|
||||
|
||||
CMD_RegisterCommand("GaitekACPower", CMD_GaitekACPower, NULL);
|
||||
CMD_RegisterCommand("GaitekACMode", CMD_GaitekACMode, NULL);
|
||||
CMD_RegisterCommand("GaitekACHAMode", CMD_GaitekACHAMode, NULL);
|
||||
CMD_RegisterCommand("GaitekACFan", CMD_GaitekACFan, NULL);
|
||||
CMD_RegisterCommand("GaitekACNight", CMD_GaitekACNight, NULL);
|
||||
CMD_RegisterCommand("GaitekACPreset", CMD_GaitekACPreset, NULL);
|
||||
CMD_RegisterCommand("GaitekACTemp", CMD_GaitekACTemp, NULL);
|
||||
CMD_RegisterCommand("GaitekACTimer", CMD_GaitekACTimer, NULL);
|
||||
CMD_RegisterCommand("GaitekACRefresh", CMD_GaitekACRefresh, NULL);
|
||||
CMD_RegisterCommand("GaitekACPublish", CMD_GaitekACPublish, NULL);
|
||||
|
||||
HTTP_RegisterCallback("/gaitekac", HTTP_GET, http_gaitekac_status, 0);
|
||||
|
||||
gaitek_sync_channels_from_cache();
|
||||
gaitek_mark_dirty();
|
||||
}
|
||||
|
||||
void GaitekAC_Shutdown(void) {
|
||||
g_gaitek_rxpos = 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
7
src/driver/drv_gaitekAC.h
Normal file
7
src/driver/drv_gaitekAC.h
Normal file
@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
void GaitekAC_Init(void);
|
||||
void GaitekAC_Shutdown(void);
|
||||
void GaitekAC_RunQuickTick(void);
|
||||
void GaitekAC_RunEverySecond(void);
|
||||
void GaitekAC_OnChannelChanged(int ch, int val);
|
||||
@ -17,6 +17,7 @@
|
||||
#include "drv_tuyaMCU.h"
|
||||
#include "drv_girierMCU.h"
|
||||
#include "drv_uart.h"
|
||||
#include "drv_gaitekAC.h"
|
||||
#include "drv_ds1820_simple.h"
|
||||
#include "drv_ds1820_full.h"
|
||||
#include "drv_ds1820_common.h"
|
||||
@ -1446,6 +1447,18 @@ static driver_t g_drivers[] = {
|
||||
false, // loaded
|
||||
},
|
||||
#endif
|
||||
#if ENABLE_DRIVER_GAITEKAC
|
||||
{ "GaitekAC",
|
||||
GaitekAC_Init,
|
||||
GaitekAC_RunEverySecond,
|
||||
NULL,
|
||||
GaitekAC_RunQuickTick,
|
||||
GaitekAC_Shutdown,
|
||||
GaitekAC_OnChannelChanged,
|
||||
NULL,
|
||||
false,
|
||||
},
|
||||
#endif
|
||||
#if PLATFORM_TXW81X
|
||||
//drvdetail:{"name":"TXWCAM",
|
||||
//drvdetail:"title":"TODO",
|
||||
|
||||
Reference in New Issue
Block a user