esp_socket: [#57] Added driver for esp.
* With small example code in master. * esp_connect currently blocks the execution. * Debug messages in socket don't follow the standart. (It is .c file, while debug messages are done in c++) * LpcUart will work only with UART1, due to the PIN_FUNC.
This commit is contained in:
parent
2b785e5b0c
commit
01784b6a80
@ -116,14 +116,14 @@ void LpcDebugUart::set_on_receive(void(*cb)(void))
|
||||
|
||||
int LpcDebugUart::free()
|
||||
{
|
||||
std::lock_guard<Fmutex> lock(write_mutex);
|
||||
std::lock_guard<Fmutex> lock(write_debug_mutex);
|
||||
|
||||
return UART_RB_SIZE - RingBuffer_GetCount(&txring);
|
||||
}
|
||||
|
||||
int LpcDebugUart::peek()
|
||||
{
|
||||
std::lock_guard<Fmutex> lock(read_mutex);
|
||||
std::lock_guard<Fmutex> lock(read_debug_mutex);
|
||||
|
||||
return RingBuffer_GetCount(&rxring);
|
||||
}
|
||||
@ -135,7 +135,7 @@ int LpcDebugUart::read(char &c)
|
||||
|
||||
int LpcDebugUart::read(char *buffer, int len)
|
||||
{
|
||||
std::lock_guard<Fmutex> lock(read_mutex);
|
||||
std::lock_guard<Fmutex> lock(read_debug_mutex);
|
||||
|
||||
if(RingBuffer_GetCount(&rxring) <= 0) {
|
||||
notify_rx = xTaskGetCurrentTaskHandle();
|
||||
@ -151,7 +151,7 @@ int LpcDebugUart::read(char *buffer, int len)
|
||||
|
||||
int LpcDebugUart::read(char *buffer, int len, TickType_t total_timeout, TickType_t ic_timeout)
|
||||
{
|
||||
std::lock_guard<Fmutex> lock(read_mutex);
|
||||
std::lock_guard<Fmutex> lock(read_debug_mutex);
|
||||
|
||||
// we can't read more than ring buffer size at a time
|
||||
if(len > UART_RB_SIZE) len = UART_RB_SIZE;
|
||||
@ -181,7 +181,7 @@ int LpcDebugUart::write(const char *s)
|
||||
|
||||
int LpcDebugUart::write(const char *buffer, int len)
|
||||
{
|
||||
std::lock_guard<Fmutex> lock(write_mutex);
|
||||
std::lock_guard<Fmutex> lock(write_debug_mutex);
|
||||
|
||||
int pos = 0;
|
||||
notify_tx = xTaskGetCurrentTaskHandle();
|
||||
@ -214,15 +214,15 @@ bool LpcDebugUart::rxbreak()
|
||||
|
||||
void LpcDebugUart::speed(int bps)
|
||||
{
|
||||
std::lock_guard<Fmutex> lockw(write_mutex);
|
||||
std::lock_guard<Fmutex> lockr(read_mutex);
|
||||
std::lock_guard<Fmutex> lockw(write_debug_mutex);
|
||||
std::lock_guard<Fmutex> lockr(read_debug_mutex);
|
||||
|
||||
Chip_UART0_SetBaud(uart, bps);
|
||||
}
|
||||
|
||||
bool LpcDebugUart::txempty()
|
||||
{
|
||||
std::lock_guard<Fmutex> lock(write_mutex);
|
||||
std::lock_guard<Fmutex> lock(write_debug_mutex);
|
||||
|
||||
return (RingBuffer_GetCount(&txring) == 0);
|
||||
}
|
||||
|
||||
@ -56,8 +56,8 @@ private:
|
||||
TaskHandle_t notify_rx;
|
||||
TaskHandle_t notify_tx;
|
||||
void (*on_receive)(void); // callback for received data notifications
|
||||
Fmutex read_mutex;
|
||||
Fmutex write_mutex;
|
||||
Fmutex read_debug_mutex;
|
||||
Fmutex write_debug_mutex;
|
||||
};
|
||||
|
||||
#endif /* LPCUART_H_ */
|
||||
|
||||
@ -8,6 +8,8 @@
|
||||
#include <cstring>
|
||||
#include <mutex>
|
||||
#include "LpcUart.h"
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
/* shoh: Important differences
|
||||
* We don't have movable pins -> not needed.
|
||||
@ -126,6 +128,8 @@ LpcUart::LpcUart(const LpcUartConfig &cfg) {
|
||||
uart = cfg.pUART; // set the actual value after validity checking
|
||||
|
||||
|
||||
//Not that straightforward.
|
||||
//But will work for uart1, kind of...
|
||||
if(cfg.tx.port >= 0) {
|
||||
Chip_IOCON_PinMuxSet(LPC_IOCON, cfg.tx.port, cfg.tx.pin, (IOCON_FUNC4 | IOCON_MODE_INACT | IOCON_DIGMODE_EN));
|
||||
}
|
||||
|
||||
808
source/shoh/src/peripherals/networking/esp8266_socket.c
Normal file
808
source/shoh/src/peripherals/networking/esp8266_socket.c
Normal file
@ -0,0 +1,808 @@
|
||||
/* ========================================
|
||||
*
|
||||
* Copyright YOUR COMPANY, THE YEAR
|
||||
* All Rights Reserved
|
||||
* UNPUBLISHED, LICENSED SOFTWARE.
|
||||
*
|
||||
* CONFIDENTIAL AND PROPRIETARY INFORMATION
|
||||
* WHICH IS THE PROPERTY OF your company.
|
||||
*
|
||||
* ========================================
|
||||
*/
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ring_buffer.h"
|
||||
|
||||
#include "esp8266_socket.h"
|
||||
|
||||
#include "serial_port.h"
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
typedef int EspSocket_t;
|
||||
|
||||
static inline uint32_t get_ticks(void) {
|
||||
return xTaskGetTickCount();
|
||||
}
|
||||
|
||||
#define I_DONT_USE(x) (void) x
|
||||
#define DEBUGP( ... ) printf( __VA_ARGS__ )
|
||||
|
||||
// macro for changing state. Correct operation requires that ctx is a pointer to state machine instance (see state template)
|
||||
#define TRAN(st) ctx->next_state = st
|
||||
|
||||
typedef enum eventTypes { eEnter, eExit, eTick, eReceive, eConnect, eDisconnect, eSend } EventType;
|
||||
|
||||
typedef struct event_ {
|
||||
EventType ev; // event type (= what happened)
|
||||
// we could add additional data
|
||||
} event;
|
||||
|
||||
static const event evEnter = { eEnter };
|
||||
static const event evExit = { eExit };
|
||||
|
||||
|
||||
typedef struct smi_ smi;
|
||||
|
||||
typedef void (*smf)(smi *, const event *); // prototype of state handler function pointer
|
||||
|
||||
#define EVQ_SIZE 32
|
||||
|
||||
#define SMI_BUFSIZE 80
|
||||
#define RC_NOT_AVAILABLE -1
|
||||
#define RC_OK 0
|
||||
#define RC_ERROR 1
|
||||
|
||||
struct smi_ {
|
||||
smf state; // current state (function pointer)
|
||||
smf next_state; // next state (function pointer)
|
||||
RINGBUFF_T EspEventQ;
|
||||
event evq_buf[EVQ_SIZE];
|
||||
int timer;
|
||||
int count;
|
||||
int pos;
|
||||
char buffer[SMI_BUFSIZE];
|
||||
char ssid[32]; // SSID
|
||||
char pwd[32]; // password
|
||||
char sa_data[32]; // ip address
|
||||
char sa_port[14]; // port number (string)
|
||||
};
|
||||
|
||||
static void stInit(smi *ctx, const event *e);
|
||||
static void stEchoOff(smi *ctx, const event *e);
|
||||
static void stStationModeCheck(smi *ctx, const event *e);
|
||||
static void stStationModeSet(smi *ctx, const event *e);
|
||||
static void stConnectAP(smi *ctx, const event *e);
|
||||
static void stReady(smi *ctx, const event *e);
|
||||
static void stConnectTCP(smi *ctx, const event *e);
|
||||
static void stConnected(smi *ctx, const event *e);
|
||||
static void stCloseTCP(smi *ctx, const event *e);
|
||||
static void stPassthrough(smi *ctx, const event *e);
|
||||
static void stPassthroughOK(smi *ctx, const event *e);
|
||||
static void stAT(smi *ctx, const event *e);
|
||||
static void stCommandMode(smi *ctx, const event *e);
|
||||
static int cur_state();
|
||||
|
||||
static void EspSocketRun(smi *ctx);
|
||||
|
||||
|
||||
|
||||
smi EspSocketInstance;
|
||||
|
||||
static void port2str(int i, char *str)
|
||||
{
|
||||
int m = 100000;
|
||||
i %= m; // limit integer size to max 5 digits.
|
||||
while(i / m == 0) m/=10;
|
||||
while(m > 0) {
|
||||
*str++ = '0' + i / m;
|
||||
i %= m;
|
||||
m /= 10;
|
||||
}
|
||||
*str='\0';
|
||||
}
|
||||
|
||||
void smi_init(smi *ctx)
|
||||
{
|
||||
serial_init(ctx);
|
||||
memset(ctx, 0, sizeof(smi));
|
||||
ctx->state = stInit;
|
||||
ctx->next_state = stInit;
|
||||
RingBuffer_Init(&ctx->EspEventQ, ctx->evq_buf, sizeof(event), EVQ_SIZE);
|
||||
|
||||
ctx->state(ctx, &evEnter); // enter initial state
|
||||
}
|
||||
|
||||
|
||||
int esp_socket(const char *ssid, const char *password)
|
||||
{
|
||||
smi_init(&EspSocketInstance);
|
||||
|
||||
|
||||
strncpy(EspSocketInstance.ssid, ssid, 32);
|
||||
strncpy(EspSocketInstance.pwd, password, 32);
|
||||
|
||||
|
||||
while(EspSocketInstance.state != stReady) {
|
||||
//printf("[socket]: Current state %d\r\n", cur_state());
|
||||
// run esp task and run ticks
|
||||
EspSocketRun(&EspSocketInstance);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cur_state()
|
||||
{
|
||||
int st = -1;
|
||||
if (EspSocketInstance.state == stInit )
|
||||
st = 0;
|
||||
else if (EspSocketInstance.state == stEchoOff )
|
||||
st = 1;
|
||||
else if (EspSocketInstance.state == stStationModeCheck )
|
||||
st = 2;
|
||||
else if (EspSocketInstance.state == stStationModeSet )
|
||||
st = 3;
|
||||
else if (EspSocketInstance.state == stConnectAP )
|
||||
st = 4;
|
||||
else if (EspSocketInstance.state == stReady )
|
||||
st = 5;
|
||||
else if (EspSocketInstance.state == stConnectTCP )
|
||||
st = 6;
|
||||
else if (EspSocketInstance.state == stConnected )
|
||||
st = 7;
|
||||
else if (EspSocketInstance.state == stCloseTCP )
|
||||
st = 8;
|
||||
else if (EspSocketInstance.state == stPassthrough )
|
||||
st = 9;
|
||||
else if (EspSocketInstance.state == stPassthroughOK )
|
||||
st = 10;
|
||||
else if (EspSocketInstance.state == stAT )
|
||||
st = 11;
|
||||
else if (EspSocketInstance.state == stCommandMode )
|
||||
st = 12;
|
||||
return st;
|
||||
}
|
||||
|
||||
int esp_connect(int sockfd, const char *addr, int port)
|
||||
{
|
||||
I_DONT_USE(sockfd);
|
||||
|
||||
strncpy(EspSocketInstance.sa_data,addr,sizeof(EspSocketInstance.sa_data)-1);
|
||||
EspSocketInstance.sa_data[sizeof(EspSocketInstance.sa_data)-1] = '\0';
|
||||
port2str(port, EspSocketInstance.sa_port);
|
||||
|
||||
const event e = { eConnect };
|
||||
|
||||
RingBuffer_Insert(&EspSocketInstance.EspEventQ,&e);
|
||||
|
||||
int rc = 0;
|
||||
|
||||
while(EspSocketInstance.state != stConnected) {
|
||||
// run esp task and run ticks
|
||||
EspSocketRun(&EspSocketInstance);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int esp_read(int sockfd, void *data, int length)
|
||||
{
|
||||
I_DONT_USE(sockfd);
|
||||
int count = 0;
|
||||
|
||||
if(EspSocketInstance.state == stConnected) {
|
||||
#if 0
|
||||
DEBUGP("[rd=%d]\r\n", length);
|
||||
// read data
|
||||
while(count < length && serial_get_char(&EspSocketInstance, data)) {
|
||||
//char c = *((unsigned char *)data);
|
||||
//DEBUGP("[%02X %c]\r\n", c , isprint(c) ? c : '.');
|
||||
++count;
|
||||
++data;
|
||||
}
|
||||
#else
|
||||
count = serial_read_buf(&EspSocketInstance, data, length);
|
||||
#endif
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
int esp_write(int sockfd, const void *data, int length)
|
||||
{
|
||||
I_DONT_USE(sockfd);
|
||||
|
||||
if(EspSocketInstance.state == stConnected) {
|
||||
// write data
|
||||
serial_write_buf(&EspSocketInstance, data, length);
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
int esp_close(int sockfd)
|
||||
{
|
||||
return esp_shutdown(sockfd, -1);
|
||||
}
|
||||
|
||||
int esp_shutdown(int sockfd, int how)
|
||||
{
|
||||
I_DONT_USE(sockfd);
|
||||
I_DONT_USE(how);
|
||||
const event e = { eDisconnect };
|
||||
|
||||
RingBuffer_Insert(&EspSocketInstance.EspEventQ,&e);
|
||||
while(EspSocketInstance.state != stReady) {
|
||||
// run esp task and run ticks
|
||||
EspSocketRun(&EspSocketInstance);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int esp_peek(int sockfd)
|
||||
{
|
||||
int cnt = 0;
|
||||
if(EspSocketInstance.state == stConnected) {
|
||||
cnt = serial_peek(&EspSocketInstance);
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
/* this is state template */
|
||||
void stStateTemplate(smi *ctx, const event *e)
|
||||
{
|
||||
switch(e->ev) {
|
||||
case eEnter:
|
||||
break;
|
||||
case eExit:
|
||||
break;
|
||||
case eTick:
|
||||
break;
|
||||
case eReceive:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void init_counters(smi *ctx) {
|
||||
ctx->count = 0;
|
||||
ctx->pos = 0;
|
||||
ctx->timer = 0;
|
||||
}
|
||||
|
||||
/* Read and store characters upto specified length.
|
||||
* Returns true when specified amount of characters have been accumulated. */
|
||||
void sm_flush(smi *ctx)
|
||||
{
|
||||
//DEBUGP("flush: %d\n", (int)xSerialRxWaiting(ctx->ComPort));
|
||||
while(serial_get_char(ctx, ctx->buffer));
|
||||
}
|
||||
|
||||
|
||||
/* Read and store characters upto specified length.
|
||||
* Returns true when specified amount of characters have been accumulated. */
|
||||
bool sm_read_buffer(smi *ctx, int count)
|
||||
{
|
||||
while(ctx->pos < (SMI_BUFSIZE - 1) && ctx->pos < count && serial_get_char(ctx, ctx->buffer + ctx->pos)) {
|
||||
//putchar(ctx->buffer[ctx->pos]); // debugging
|
||||
++ctx->pos;
|
||||
}
|
||||
return (ctx->pos >= count);
|
||||
}
|
||||
|
||||
|
||||
/* Read an integer.
|
||||
* Consumes characters until a non-nondigit is received. The nondigit is also consumed. */
|
||||
bool sm_read_int(smi *ctx, int *value)
|
||||
{
|
||||
bool result = false;
|
||||
while(ctx->pos < (SMI_BUFSIZE - 1) && serial_get_char(ctx, ctx->buffer + ctx->pos)) {
|
||||
if(!isdigit((int)ctx->buffer[ctx->pos])) {
|
||||
ctx->buffer[ctx->pos] = '\0';
|
||||
*value = atoi(ctx->buffer);
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
++ctx->pos;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Read and store data until one of the specified strings is received.
|
||||
* The matched string is also included in the data .*/
|
||||
int sm_read_until(smi *ctx, const char **p)
|
||||
{
|
||||
int result = RC_NOT_AVAILABLE;
|
||||
while(result < 0 && ctx->pos < (SMI_BUFSIZE - 1) && serial_get_char(ctx, ctx->buffer + ctx->pos)) {
|
||||
++ctx->pos;
|
||||
ctx->buffer[ctx->pos] = '\0';
|
||||
for(int i = 0; result < 0 && p[i] != NULL; ++i) {
|
||||
if(strstr(ctx->buffer, p[i]) != NULL) {
|
||||
result = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
/* read and store data until result is received */
|
||||
int sm_read_result(smi *ctx)
|
||||
{
|
||||
static const char *result_list[] = { "OK\r\n", "ERROR\r\n", NULL };
|
||||
return sm_read_until(ctx, result_list);
|
||||
}
|
||||
|
||||
/* read and consume characters until specified string occurs */
|
||||
bool sm_wait_for(smi *ctx, const char *p)
|
||||
{
|
||||
bool result = false;
|
||||
int len = strlen(p);
|
||||
|
||||
while(sm_read_buffer(ctx, len)) {
|
||||
ctx->buffer[ctx->pos] = '\0';
|
||||
if(strstr(ctx->buffer, p) != NULL) {
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
memmove(ctx->buffer, ctx->buffer + 1, ctx->pos);
|
||||
--ctx->pos;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static void stInit(smi *ctx, const event *e)
|
||||
{
|
||||
switch(e->ev) {
|
||||
case eEnter:
|
||||
DEBUGP("stInit\r\n");
|
||||
sm_flush(ctx);
|
||||
init_counters(ctx);
|
||||
serial_write_str(ctx, "AT\r\n");
|
||||
break;
|
||||
case eExit:
|
||||
break;
|
||||
case eTick:
|
||||
++ctx->timer;
|
||||
//if(ctx->timer == 2) DEBUGP("[%s]\r\n", ctx->buffer);
|
||||
if(ctx->timer >= 5) {
|
||||
ctx->timer = 0;
|
||||
++ctx->count;
|
||||
if(ctx->count < 2) {
|
||||
serial_write_str(ctx, "AT\r\n");
|
||||
}
|
||||
else {
|
||||
DEBUGP("Error: Module not responding\r\n");
|
||||
TRAN(stAT);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case eReceive:
|
||||
if(sm_wait_for(ctx, "OK\r\n")) {
|
||||
TRAN(stEchoOff);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void stAT(smi *ctx, const event *e)
|
||||
{
|
||||
switch(e->ev) {
|
||||
case eEnter:
|
||||
DEBUGP("stAT\r\n");
|
||||
init_counters(ctx);
|
||||
break;
|
||||
case eExit:
|
||||
break;
|
||||
case eTick:
|
||||
++ctx->timer;
|
||||
if(ctx->timer == 5) serial_write_str(ctx, "+++");
|
||||
if(ctx->timer == 15) TRAN(stInit);
|
||||
break;
|
||||
case eReceive:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void stEchoOff(smi *ctx, const event *e)
|
||||
{
|
||||
switch(e->ev) {
|
||||
case eEnter:
|
||||
DEBUGP("stEchoOff\r\n");
|
||||
sm_flush(ctx);
|
||||
init_counters(ctx);
|
||||
serial_write_str(ctx, "ATE0\r\n");
|
||||
break;
|
||||
case eExit:
|
||||
break;
|
||||
case eTick:
|
||||
++ctx->timer;
|
||||
if(ctx->timer >= 10) {
|
||||
++ctx->count;
|
||||
if(ctx->count < 3) {
|
||||
serial_write_str(ctx, "ATE0\r\n");
|
||||
}
|
||||
else {
|
||||
DEBUGP("Error: setting local echo off failed\r\n");
|
||||
TRAN(stInit);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case eReceive:
|
||||
if(sm_wait_for(ctx, "OK\r\n")) {
|
||||
TRAN(stStationModeCheck);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void stStationModeCheck(smi *ctx, const event *e)
|
||||
{
|
||||
int rc = -1;
|
||||
switch(e->ev) {
|
||||
case eEnter:
|
||||
DEBUGP("stStationModeCheck\r\n");
|
||||
init_counters(ctx);
|
||||
serial_write_str(ctx, "AT+CWMODE_CUR?\r\n");
|
||||
break;
|
||||
case eExit:
|
||||
break;
|
||||
case eTick:
|
||||
break;
|
||||
case eReceive:
|
||||
rc = sm_read_result(ctx);
|
||||
if(rc == RC_OK) {
|
||||
//DEBUGP("%d: %s", rc, ctx->buffer);
|
||||
if(strstr(ctx->buffer, "+CWMODE_CUR:1\r\n") != NULL) {
|
||||
TRAN(stConnectAP);
|
||||
}
|
||||
else {
|
||||
TRAN(stStationModeSet);
|
||||
}
|
||||
}
|
||||
else if(rc == RC_ERROR) {
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void stStationModeSet(smi *ctx, const event *e)
|
||||
{
|
||||
switch(e->ev) {
|
||||
case eEnter:
|
||||
DEBUGP("stStationModeSet\r\n");
|
||||
init_counters(ctx);
|
||||
serial_write_str(ctx, "AT+CWMODE_CUR=1\r\n");
|
||||
break;
|
||||
case eExit:
|
||||
break;
|
||||
case eTick:
|
||||
break;
|
||||
case eReceive:
|
||||
if(sm_wait_for(ctx, "OK\r\n")) {
|
||||
TRAN(stStationModeCheck);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void connect_ssid(smi *ctx)
|
||||
{
|
||||
serial_write_str(ctx, "AT+CWJAP_CUR=\"");
|
||||
serial_write_str(ctx, ctx->ssid);
|
||||
serial_write_str(ctx, "\",\"");
|
||||
serial_write_str(ctx, ctx->pwd);
|
||||
serial_write_str(ctx, "\"\r\n");
|
||||
}
|
||||
|
||||
static void stConnectAP(smi *ctx, const event *e)
|
||||
{
|
||||
int rc;
|
||||
switch(e->ev) {
|
||||
case eEnter:
|
||||
DEBUGP("stConnectAP\r\n");
|
||||
init_counters(ctx);
|
||||
break;
|
||||
case eExit:
|
||||
break;
|
||||
case eTick:
|
||||
// may take upto 7 seconds. do we need a timeout?
|
||||
++ctx->timer;
|
||||
if(ctx->timer == 1) {
|
||||
connect_ssid(ctx);
|
||||
}
|
||||
if(ctx->timer >= 70) {
|
||||
ctx->timer = 0;
|
||||
}
|
||||
break;
|
||||
case eReceive:
|
||||
rc = sm_read_result(ctx);
|
||||
if(rc == RC_OK) {
|
||||
//DEBUGP("%d: %s", rc, ctx->buffer);
|
||||
TRAN(stReady);
|
||||
}
|
||||
else if(rc == RC_ERROR) {
|
||||
// failed: what to do now?
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void stReady(smi *ctx, const event *e)
|
||||
{
|
||||
switch(e->ev) {
|
||||
case eEnter:
|
||||
DEBUGP("stReady\r\n");
|
||||
init_counters(ctx);
|
||||
break;
|
||||
case eExit:
|
||||
break;
|
||||
case eTick:
|
||||
break;
|
||||
case eReceive:
|
||||
break;
|
||||
case eConnect:
|
||||
TRAN(stConnectTCP);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void connect_tcp(smi *ctx)
|
||||
{
|
||||
serial_write_str(ctx, "AT+CIPSTART=\"TCP\",\"");
|
||||
serial_write_str(ctx, ctx->sa_data);
|
||||
serial_write_str(ctx, "\",");
|
||||
serial_write_str(ctx, ctx->sa_port);
|
||||
serial_write_str(ctx, "\r\n");
|
||||
}
|
||||
|
||||
static void stConnectTCP(smi *ctx, const event *e)
|
||||
{
|
||||
int rc;
|
||||
switch(e->ev) {
|
||||
case eEnter:
|
||||
DEBUGP("stConnectTCP\r\n");
|
||||
init_counters(ctx);
|
||||
connect_tcp(ctx);
|
||||
break;
|
||||
case eExit:
|
||||
break;
|
||||
case eTick:
|
||||
break;
|
||||
case eReceive:
|
||||
rc = sm_read_result(ctx);
|
||||
if(rc == RC_OK) {
|
||||
//DEBUGP("%d: %s", rc, ctx->buffer);
|
||||
if(strstr(ctx->buffer, "CONNECT\r\n") != NULL) {
|
||||
TRAN(stPassthrough);
|
||||
}
|
||||
else {
|
||||
// what else can we get with OK??
|
||||
}
|
||||
}
|
||||
else if(rc == RC_ERROR) {
|
||||
// failed: what to do now?
|
||||
DEBUGP("Connect failed\r\n");
|
||||
connect_tcp(ctx);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void stPassthrough(smi *ctx, const event *e)
|
||||
{
|
||||
int rc;
|
||||
switch(e->ev) {
|
||||
case eEnter:
|
||||
DEBUGP("stPassthrough\r\n");
|
||||
init_counters(ctx);
|
||||
serial_write_str(ctx, "AT+CIPMODE=1\r\n");
|
||||
break;
|
||||
case eExit:
|
||||
break;
|
||||
case eTick:
|
||||
break;
|
||||
case eReceive:
|
||||
rc = sm_read_result(ctx);
|
||||
if(rc == RC_OK) {
|
||||
TRAN(stPassthroughOK);
|
||||
}
|
||||
else if(rc == RC_ERROR) {
|
||||
// failed: what to do now?
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void stPassthroughOK(smi *ctx, const event *e)
|
||||
{
|
||||
switch(e->ev) {
|
||||
case eEnter:
|
||||
DEBUGP("stPassthroughOK\r\n");
|
||||
init_counters(ctx);
|
||||
serial_write_str(ctx, "AT+CIPSEND\r\n");
|
||||
break;
|
||||
case eExit:
|
||||
break;
|
||||
case eTick:
|
||||
break;
|
||||
case eReceive:
|
||||
if(sm_wait_for(ctx, ">")) {
|
||||
TRAN(stConnected);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void stConnected(smi *ctx, const event *e)
|
||||
{
|
||||
switch(e->ev) {
|
||||
case eEnter:
|
||||
DEBUGP("stConnected\r\n");
|
||||
init_counters(ctx);
|
||||
break;
|
||||
case eExit:
|
||||
break;
|
||||
case eTick:
|
||||
break;
|
||||
case eReceive:
|
||||
break;
|
||||
case eDisconnect:
|
||||
TRAN(stCommandMode);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void stCommandMode(smi *ctx, const event *e)
|
||||
{
|
||||
switch(e->ev) {
|
||||
case eEnter:
|
||||
DEBUGP("stCommandMode\r\n");
|
||||
init_counters(ctx);
|
||||
break;
|
||||
case eExit:
|
||||
break;
|
||||
case eTick:
|
||||
++ctx->timer;
|
||||
if(ctx->timer == 10) serial_write_str(ctx, "+++");
|
||||
if(ctx->timer == 25) TRAN(stCloseTCP);
|
||||
break;
|
||||
case eReceive:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void stCloseTCP(smi *ctx, const event *e)
|
||||
{
|
||||
int rc = -1;
|
||||
switch(e->ev) {
|
||||
case eEnter:
|
||||
DEBUGP("stCloseTCP\r\n");
|
||||
init_counters(ctx);
|
||||
serial_write_str(ctx, "AT+CIPMODE=0\r\n");;
|
||||
break;
|
||||
case eReceive:
|
||||
rc = sm_read_result(ctx);
|
||||
if(rc == RC_OK) {
|
||||
if(strstr(ctx->buffer, "CLOSED") != NULL) {
|
||||
TRAN(stReady);
|
||||
}
|
||||
else {
|
||||
init_counters(ctx);
|
||||
serial_write_str(ctx, "AT+CIPCLOSE\r\n");;
|
||||
}
|
||||
}
|
||||
else if(rc == RC_ERROR) {
|
||||
}
|
||||
break;
|
||||
case eExit:
|
||||
break;
|
||||
case eTick:
|
||||
++ctx->timer;
|
||||
if(ctx->timer == 25) TRAN(stCommandMode);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void dispatch_event(smi *ctx, const event *e)
|
||||
{
|
||||
ctx->state(ctx, e); // dispatch event to current state
|
||||
if(ctx->state != ctx->next_state) { // check if state was changed
|
||||
ctx->state(ctx, &evExit); // exit old state (cleanup)
|
||||
ctx->state = ctx->next_state; // change state
|
||||
ctx->state(ctx, &evEnter); // enter new state
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Receive events from queue and dispatch them to state machine
|
||||
*/
|
||||
static void EspSocketRun(smi *ctx)
|
||||
{
|
||||
event e;
|
||||
|
||||
static uint32_t old = 0 ;
|
||||
uint32_t now = 0 ;
|
||||
|
||||
now = get_ticks()/100;
|
||||
if(now != old) {
|
||||
const event tick = { eTick };
|
||||
old = now;
|
||||
// send ESP tick
|
||||
RingBuffer_Insert(&ctx->EspEventQ, &tick);
|
||||
}
|
||||
|
||||
if(serial_peek(ctx)) {
|
||||
const event rcv = { eReceive };
|
||||
RingBuffer_Insert(&ctx->EspEventQ, &rcv);
|
||||
}
|
||||
|
||||
// read queue
|
||||
while (RingBuffer_Pop(&ctx->EspEventQ,&e)) {
|
||||
dispatch_event(ctx, &e); // dispatch event to current state
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* [] END OF FILE */
|
||||
21
source/shoh/src/peripherals/networking/esp8266_socket.h
Normal file
21
source/shoh/src/peripherals/networking/esp8266_socket.h
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef ESP8266_H_
|
||||
#define ESP8266_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
int esp_socket(const char *ssid, const char *password) ;
|
||||
int esp_connect(int sockfd, const char *addr, int port);
|
||||
int esp_read(int sockfd, void *data, int length);
|
||||
int esp_write(int sockfd, const void *data, int length);
|
||||
int esp_close(int sockfd);
|
||||
int esp_shutdown(int sockfd, int how);
|
||||
int esp_peek(int sockfd);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
56
source/shoh/src/peripherals/networking/serial_port.cpp
Normal file
56
source/shoh/src/peripherals/networking/serial_port.cpp
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* serial_port.cpp
|
||||
*
|
||||
* Created on: 25.8.2021
|
||||
* Author: keijo
|
||||
*/
|
||||
#include "LpcUart.h"
|
||||
#include "serial_port.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static LpcUart *EspUart;
|
||||
|
||||
void serial_init(void *ctx)
|
||||
{
|
||||
if(EspUart == nullptr) {
|
||||
LpcPinMap none = {-1, -1}; // unused pin has negative values in it
|
||||
LpcPinMap txpin_esp = { 0, 14 }; // transmit pin
|
||||
LpcPinMap rxpin_esp = { 0, 13 }; // receive pin
|
||||
LpcUartConfig cfg = { LPC_USART1, 115200, UARTN_CFG_DATALEN_8 | UARTN_CFG_PARITY_NONE | UARTN_CFG_STOPLEN_1, false, txpin_esp, rxpin_esp, none, none };
|
||||
|
||||
EspUart = new LpcUart(cfg);
|
||||
}
|
||||
}
|
||||
|
||||
void serial_write_buf(void *ctx, const char *buf, int len)
|
||||
{
|
||||
EspUart->write(buf, len);
|
||||
}
|
||||
|
||||
void serial_write_str(void *ctx, const char *s)
|
||||
{
|
||||
EspUart->write(s);
|
||||
}
|
||||
|
||||
int serial_read_buf(void *ctx, char *buf, int len)
|
||||
{
|
||||
return EspUart->read(buf, len, 20 * len);
|
||||
}
|
||||
|
||||
int serial_get_char(void *ctx, char *p)
|
||||
{
|
||||
return EspUart->read(p, 1, 20);//EspUart->read(p, 1, 20);
|
||||
}
|
||||
|
||||
int serial_peek(void *ctx)
|
||||
{
|
||||
return EspUart->peek();
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
30
source/shoh/src/peripherals/networking/serial_port.h
Normal file
30
source/shoh/src/peripherals/networking/serial_port.h
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* serial_port.h
|
||||
*
|
||||
* Created on: 25.8.2021
|
||||
* Author: keijo
|
||||
*/
|
||||
|
||||
#ifndef SERIAL_PORT_H_
|
||||
#define SERIAL_PORT_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
void serial_init(void *ctx);
|
||||
void serial_write_buf(void *ctx, const char *buf, int len);
|
||||
void serial_write_str(void *ctx, const char *s);
|
||||
int serial_read_buf(void *ctx, char *buf, int len);
|
||||
int serial_get_char(void *ctx, char *p);
|
||||
int serial_peek(void *ctx);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* SERIAL_PORT_H_ */
|
||||
@ -15,6 +15,7 @@
|
||||
#include "UserInterface.h"
|
||||
#include "Temperature.h"
|
||||
#include "queue.h"
|
||||
#include "esp8266_socket.h"
|
||||
|
||||
static const char* rotary_direction[] =
|
||||
{
|
||||
@ -75,6 +76,8 @@ void Master::HandleEventType(Event* e)
|
||||
|
||||
void Master::taskFunction() {
|
||||
Event data(Event::Null, 0);
|
||||
//int soc = esp_socket("SSID", "PASSWORD");
|
||||
//int stat = esp_connect(soc, "IP", 5000);
|
||||
for (;;)
|
||||
{
|
||||
if(!_qm->receive<Event>(ThreadCommon::QueueManager::master_event_all, &data, 10000))
|
||||
@ -85,6 +88,9 @@ void Master::taskFunction() {
|
||||
HandleEventType(&data);
|
||||
|
||||
global_clock->updateClock();
|
||||
//LOG_WARNING("ESP socket status: %d", stat);
|
||||
//if(stat == 0)
|
||||
// stat = esp_connect(soc, "IP", 5000);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user