2024-08-16 01:11:02 +02:00

302 lines
6.6 KiB
C

#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
#include <nvs_flash.h>
#include <esp_task_wdt.h>
#include <freertos/idf_additions.h>
#include <CLI/CLI.h>
#include <CMDList/CMDList.h>
#include "config.h"
#include "utils.h"
#include "commands.h"
#include "wifi.h"
#include "logger.h"
#include "ws.h"
#if TARGET == TARGET_TX
#include "led.h"
#include "adc.h"
#elif TARGET == TARGET_RX
#include "servos.h"
#endif
bool volatile running = true;
CMDList_t* cmdList;
bool rxBuffer_overflow = false;
typedef enum {
STATE_WIFI_CONNECTING,
STATE_WIFI_WAIT_CONNECTION,
#if TARGET == TARGET_RX
STATE_WS_CONNECTING,
STATE_WS_WAIT_CONNECTION,
STATE_IDEL,
STATE_DRIVING
#elif TARGET == TARGET_TX
STATE_WIFI_CONNECTED,
#endif
} MainState_t;
MainState_t MainState = STATE_WIFI_CONNECTING;
#if TARGET == TARGET_TX
typedef enum {
STATE_WS_CONNECTING,
STATE_WS_WAIT_CONNECTION,
STATE_IDEL,
STATE_DRIVING
} WSState_t;
WSState_t WSStates[3] = {STATE_WS_CONNECTING, STATE_WS_CONNECTING, STATE_WS_CONNECTING};
uint8_t WS_conn_proc = 0;
#endif
#if TARGET == TARGET_RX
ws_client_t ws_client;
#elif TARGET == TARGET_TX
ws_client_t ws_client[3];
#endif
int charOut_uart(const char* c)
{
printf("%c", *c);
return 0;
}
#if TARGET == TARGET_RX
int charOut_ws(const char* c)
{
ws_putchar(ws_client, *c);
return 0;
}
#endif
void app_main() {
// disable watchdog
ESP_ERROR_CHECK(esp_task_wdt_deinit());
/* Initialize NVS — it is used to store PHY calibration data */
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND)
{
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);
printChipInfo();
#if TARGET == TARGET_TX
led_init();
led_setRGB(0, 0, 20);
#elif TARGET == TARGET_RX
servo_init();
#endif
wifiInit();
bool adc_inited = false;
uint8_t adc_counter = 0;
running = true;
// init cli
cmdList = getCMDList();
CLI_t cli_uart = CLI_init((CLI_charOutFn)&charOut_uart, cmdList);
uint8_t charIn = 0;
EventBits_t bits;
MainState_t lastMainState = MainState;
#if TARGET == TARGET_RX
CLI_t cli_ws_client;
#elif TARGET == TARGET_TX
CLI_t cli_ws_client[3];
#endif
LOG_D("main: main loop starting in state %d", MainState);
while (running)
{
charIn = getchar();
if (charIn != 255)
{
CLI_charIn(&cli_uart, charIn);
}
if (lastMainState != MainState)
{
LOG_D("main: MainState changed from %d to %d", lastMainState, MainState);
lastMainState = MainState;
}
switch (MainState)
{
case STATE_WIFI_CONNECTING:
wifi_connect();
MainState = STATE_WIFI_WAIT_CONNECTION;
break;
case STATE_WIFI_WAIT_CONNECTION:
bits = xEventGroupGetBits(s_wifi_event_group);
if ((bits & WIFI_CONNECTED_BIT) != 0)
{
#if TARGET == TARGET_TX
led_setRGB(0, 20, 0);
MainState = STATE_WIFI_CONNECTED;
#elif TARGET == TARGET_RX
MainState = STATE_WS_CONNECTING;
#endif
LOG_I("main: connected to ap SSID '%s'", WIFI_SSID);
}
else if ((bits & WIFI_FAIL_BIT) != 0)
{
#if TARGET == TARGET_TX
led_setRGB(2, 0, 0);
#endif
MainState = STATE_WIFI_CONNECTING;
// wifi_reconnect();
LOG_E("main: Failed to connect to SSID '%s'", WIFI_SSID);
}
else if (bits != 0)
{
#if TARGET == TARGET_TX
led_setRGB(20, 0, 0);
#endif
// MainState = STATE_WIFI_CONNECTING;
LOG_C("main: UNEXPECTED EVENT (bits: 0x%04x)", bits);
}
break;
#if TARGET == TARGET_TX
case STATE_WIFI_CONNECTED:
if (!adc_inited)
{
adc_init();
adc_inited = true;
}
ADC_Data_t adc_data;
bool adc_data_valid = false;
if (adc_read(&adc_data))
{
adc_counter++;
if (adc_counter >= 20)
{
// LOG_D("ADC_DATA: %d, %d, %d, %d, %d, %d", adc_data.value[0], adc_data.value[1], adc_data.value[2], adc_data.value[3], adc_data.value[4], adc_data.value[5]);
adc_data_valid = true;
adc_counter = 0;
}
}
for (WS_conn_proc = 0; WS_conn_proc <3; WS_conn_proc++)
{
switch (WSStates[WS_conn_proc])
{
case STATE_WS_CONNECTING:
LOG_I("main: websocket %d: connecting", WS_conn_proc);
ws_client[WS_conn_proc] = ws_connect(WS_URL, BoatId + WS_conn_proc, WS_DEV_CODE_CLIENT);
WSStates[WS_conn_proc] = STATE_WS_WAIT_CONNECTION;
break;
case STATE_WS_WAIT_CONNECTION:
if (ws_client[WS_conn_proc]->connected)
{
LOG_I("main: websocket %d: connected", WS_conn_proc);
WSStates[WS_conn_proc] = STATE_IDEL;
}
break;
case STATE_IDEL:
if (adc_data_valid)
{
char cmd[100];
snprintf(&cmd[0], 100, "%04u;ctrl;%04u",
ws_client[WS_conn_proc]->id,
ws_client[WS_conn_proc]->id
);
ws_sendString(ws_client[WS_conn_proc], &cmd[0]);
}
case STATE_DRIVING:
if (!ws_client[WS_conn_proc]->connected)
{
WSStates[WS_conn_proc] = STATE_WS_WAIT_CONNECTION;
}
char ws_resp[10];
uint16_t ws_resp_len;
while ((ws_resp_len = ws_getstr(ws_client[WS_conn_proc], 10, &ws_resp[0])) > 0)
{
LOG_D("main: websocket %d: resv: %.*s", WS_conn_proc, ws_resp_len, ws_resp);
if (ws_resp_len == 4)
{
ws_resp[4] = 0;
if (strcmp(&ws_resp[0], "FAIL") == 0)
{
WSStates[WS_conn_proc] = STATE_IDEL;
}
}
else if (ws_resp_len == 2)
{
ws_resp[2] = 0;
if (strcmp(&ws_resp[0], "OK") == 0)
{
WSStates[WS_conn_proc] = STATE_DRIVING;
}
}
}
if ((WSStates[WS_conn_proc] == STATE_DRIVING) && adc_data_valid)
{
char ctrl_cmd[100];
snprintf(&ctrl_cmd[0], 100, "%04u;d;%u,%u",
ws_client[WS_conn_proc]->id,
adc_data.value[WS_conn_proc][0] >> 4,
adc_data.value[WS_conn_proc][1] >> 4
);
ws_sendString(ws_client[WS_conn_proc], &ctrl_cmd[0]);
}
break;
}
}
break;
#elif TARGET == TARGET_RX
case STATE_WS_CONNECTING:
ws_client = ws_connect(WS_URL, BoatId, WS_DEV_CODE_BOAT);
MainState = STATE_WS_WAIT_CONNECTION;
break;
case STATE_WS_WAIT_CONNECTION:
if (ws_client->connected)
{
cli_ws_client = CLI_init((CLI_charOutFn)&charOut_ws, cmdList);
cli_ws_client.echo = false;
MainState = STATE_IDEL;
}
break;
case STATE_IDEL:
case STATE_DRIVING:
if (!ws_client->connected)
{
CLI_deinit(&cli_ws_client);
MainState = STATE_WS_WAIT_CONNECTION;
}
while ((charIn = ws_getchar(ws_client)) != 255)
{
CLI_charIn(&cli_ws_client, charIn);
}
ws_sendData(ws_client);
break;
#endif
}
}
#if TARGET == TARGET_TX
led_setRGB(0, 0, 0);
#endif
servo_deinit();
CLI_deinit(&cli_uart);
CMDList_deinit(cmdList);
return;
}