ESP3D/esp3d/espcom.cpp
2020-12-22 19:27:01 +01:00

479 lines
12 KiB
C++

/*
espcom.cpp - esp3d communication serial/tcp/etc.. class
Copyright (c) 2014 Luc Lebosse. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "config.h"
#include "espcom.h"
#include "command.h"
#include "webinterface.h"
#if defined (ASYNCWEBSERVER)
#include "asyncwebserver.h"
#else
#include "syncwebserver.h"
#endif
#ifdef ESP_OLED_FEATURE
#include "esp_oled.h"
bool ESPCOM::block_2_oled = false;
#endif
uint8_t ESPCOM::current_socket_id=0;
#ifdef TCP_IP_DATA_FEATURE
WiFiServer * data_server;
WiFiClient serverClients[MAX_SRV_CLIENTS];
#endif
bool ESPCOM::block_2_printer = false;
void ESPCOM::bridge(bool async)
{
#if defined (ASYNCWEBSERVER)
if(can_process_serial) {
#endif
//be sure wifi is on to proceed wifi function
if ((WiFi.getMode() != WIFI_OFF) || wifi_config.WiFi_on) {
//read tcp port input
#ifdef TCP_IP_DATA_FEATURE
ESPCOM::processFromTCP2Serial();
#endif
}
//read serial input
ESPCOM::processFromSerial();
#if defined (ASYNCWEBSERVER)
}
#endif
}
long ESPCOM::readBytes (tpipe output, uint8_t * sbuf, size_t len)
{
switch (output) {
#ifdef USE_SERIAL_0
case SERIAL_PIPE:{
long l = Serial.readBytes(sbuf,len);
#ifdef DEBUG_OUTPUT_SOCKET
if(socket_server){
socket_server->sendBIN(ESPCOM::current_socket_id,sbuf,l);
}
#endif
return l;
}
break;
#endif
#ifdef USE_SERIAL_1
case SERIAL_PIPE:
return Serial1.readBytes(sbuf,len);
break;
#endif
#ifdef USE_SERIAL_2
case SERIAL_PIPE:
return Serial2.readBytes(sbuf,len);
break;
#endif
default:
return 0;
break;
}
}
long ESPCOM::baudRate(tpipe output)
{
long br = 0;
switch (output) {
#ifdef USE_SERIAL_0
case SERIAL_PIPE:
br = Serial.baudRate();
break;
#endif
#ifdef USE_SERIAL_1
case SERIAL_PIPE:
br = Serial1.baudRate();
break;
#endif
#ifdef USE_SERIAL_2
case SERIAL_PIPE:
br = Serial2.baudRate();
break;
#endif
default:
return 0;
break;
}
#ifdef ARDUINO_ARCH_ESP32
//workaround for ESP32
if (br == 115201) {
br = 115200;
}
if (br == 230423) {
br = 230400;
}
#endif
return br;
}
size_t ESPCOM::available(tpipe output)
{
switch (output) {
#ifdef USE_SERIAL_0
case SERIAL_PIPE:
return Serial.available();
break;
#endif
#ifdef USE_SERIAL_1
case SERIAL_PIPE:
return Serial1.available();
break;
#endif
#ifdef USE_SERIAL_2
case SERIAL_PIPE:
return Serial2.available();
break;
#endif
default:
return 0;
break;
}
}
size_t ESPCOM::write(tpipe output, uint8_t d)
{
if ((DEFAULT_PRINTER_PIPE == output) && (block_2_printer || CONFIG::is_locked(FLAG_BLOCK_SERIAL))) {
return 0;
}
if ((SERIAL_PIPE == output) && CONFIG::is_locked(FLAG_BLOCK_SERIAL)) {
return 0;
}
switch (output) {
#ifdef USE_SERIAL_0
case SERIAL_PIPE:
return Serial.write(d);
break;
#endif
#ifdef USE_SERIAL_1
case SERIAL_PIPE:
return Serial1.write(d);
break;
#endif
#ifdef USE_SERIAL_2
case SERIAL_PIPE:
return Serial2.write(d);
break;
#endif
default:
return 0;
break;
}
}
void ESPCOM::flush (tpipe output, ESPResponseStream *espresponse)
{
switch (output) {
#ifdef USE_SERIAL_0
case SERIAL_PIPE:
Serial.flush();
break;
#endif
#ifdef USE_SERIAL_1
case SERIAL_PIPE:
Serial1.flush();
break;
#endif
#ifdef USE_SERIAL_2
case SERIAL_PIPE:
Serial2.flush();
break;
#endif
#if !defined (ASYNCWEBSERVER)
case WEB_PIPE:
if (espresponse) {
if(espresponse->header_sent) {
//send data
web_interface->web_server.sendContent(espresponse->buffer_web);
//close line
web_interface->web_server.sendContent("");
}
espresponse->header_sent = false;
espresponse->buffer_web = String();
}
break;
#endif
default:
break;
}
}
void ESPCOM::print (const __FlashStringHelper *data, tpipe output, ESPResponseStream *espresponse)
{
String tmp = data;
ESPCOM::print (tmp.c_str(), output, espresponse);
}
void ESPCOM::print (String & data, tpipe output, ESPResponseStream *espresponse)
{
ESPCOM::print (data.c_str(), output, espresponse);
}
void ESPCOM::print (const char * data, tpipe output, ESPResponseStream *espresponse)
{
if ((DEFAULT_PRINTER_PIPE == output) && ( block_2_printer || CONFIG::is_locked(FLAG_BLOCK_SERIAL))) {
return;
}
if ((SERIAL_PIPE == output) && CONFIG::is_locked(FLAG_BLOCK_SERIAL)) {
return;
}
#ifdef TCP_IP_DATA_FEATURE
if ((TCP_PIPE == output) && CONFIG::is_locked(FLAG_BLOCK_TCP)) {
return;
}
#endif
#ifdef WS_DATA_FEATURE
if ((WS_PIPE == output) && CONFIG::is_locked(FLAG_BLOCK_WSOCKET)) {
return;
}
#endif
#ifdef ESP_OLED_FEATURE
if ((OLED_PIPE == output) && CONFIG::is_locked(FLAG_BLOCK_OLED)) {
return;
}
#endif
switch (output) {
#ifdef USE_SERIAL_0
case SERIAL_PIPE:
#ifdef DEBUG_OUTPUT_SOCKET
if(socket_server){
socket_server->sendBIN(ESPCOM::current_socket_id,(const uint8_t*)data,strlen(data));
}
#endif
Serial.print (data);
break;
#endif
#ifdef USE_SERIAL_1
case SERIAL_PIPE:
Serial1.print (data);
break;
#endif
#ifdef USE_SERIAL_2
case SERIAL_PIPE:
Serial2.print (data);
break;
#endif
#ifdef TCP_IP_DATA_FEATURE
case TCP_PIPE:
ESPCOM::send2TCP (data);
break;
#endif
case WEB_PIPE:
if (espresponse != NULL) {
#if defined(ASYNCWEBSERVER)
espresponse->print (data);
#else
if (!espresponse->header_sent) {
web_interface->web_server.setContentLength(CONTENT_LENGTH_UNKNOWN);
web_interface->web_server.sendHeader("Content-Type","text/html");
web_interface->web_server.sendHeader("Cache-Control","no-cache");
web_interface->web_server.send(200);
espresponse->header_sent = true;
}
espresponse->buffer_web+=data;
if (espresponse->buffer_web.length() > 1200) {
//send data
web_interface->web_server.sendContent(espresponse->buffer_web);
//reset buffer
espresponse->buffer_web="";
}
#endif
}
break;
#ifdef WS_DATA_FEATURE
case WS_PIPE: {
#if defined(ASYNCWEBSERVER)
//Todo
#else
if(socket_server){
socket_server->sendBIN(current_socket_id,(const uint8_t *)data,strlen(data));
}
#endif
}
break;
#endif
#ifdef ESP_OLED_FEATURE
case OLED_PIPE: {
if (!ESPCOM::block_2_oled) {
if(!(!strcmp(data,"\n")||!strcmp(data,"\r")||!strcmp(data,"\r\n"))) {
OLED_DISPLAY::print(data);
OLED_DISPLAY::update_lcd();
}
}
}
break;
#endif
case PRINTER_PIPE: {
#ifdef ESP_OLED_FEATURE
OLED_DISPLAY::setCursor(0, 48);
if(!(!strcmp(data,"\n")||!strcmp(data,"\r")||!strcmp(data,"\r\n"))) {
ESPCOM::print(data, OLED_PIPE);
}
#endif
if (!CONFIG::is_locked(FLAG_BLOCK_M117)) {
if(!(!strcmp(data,"\n")||!strcmp(data,"\r")||!strcmp(data,"\r\n"))) {
ESPCOM::print ("M117 ", DEFAULT_PRINTER_PIPE);
}
ESPCOM::print (data, DEFAULT_PRINTER_PIPE);
}
}
break;
default:
break;
}
}
void ESPCOM::println (const __FlashStringHelper *data, tpipe output, ESPResponseStream *espresponse)
{
ESPCOM::print (data, output, espresponse);
#ifdef TCP_IP_DATA_FEATURE
ESPCOM::print ("\r", output, espresponse);
#endif
ESPCOM::print ("\n", output, espresponse);
}
void ESPCOM::println (String & data, tpipe output, ESPResponseStream *espresponse)
{
ESPCOM::print (data, output, espresponse);
#ifdef TCP_IP_DATA_FEATURE
ESPCOM::print ("\r", output, espresponse);
#endif
ESPCOM::print ("\n", output, espresponse);
}
void ESPCOM::println (const char * data, tpipe output, ESPResponseStream *espresponse)
{
ESPCOM::print (data, output, espresponse);
#ifdef TCP_IP_DATA_FEATURE
ESPCOM::print ("\r", output, espresponse);
#endif
ESPCOM::print ("\n", output, espresponse);
}
#ifdef TCP_IP_DATA_FEATURE
void ESPCOM::send2TCP (const __FlashStringHelper *data, bool async)
{
String tmp = data;
ESPCOM::send2TCP (tmp.c_str(), async);
}
void ESPCOM::send2TCP (String data, bool async)
{
ESPCOM::send2TCP (data.c_str(), async);
}
void ESPCOM::send2TCP (const char * data, bool async)
{
if (!async) {
for (uint8_t i = 0; i < MAX_SRV_CLIENTS; i++) {
if (serverClients[i] && serverClients[i].connected() ) {
serverClients[i].write (data, strlen (data) );
delay (0);
}
}
}
}
#endif
bool ESPCOM::processFromSerial (bool async)
{
uint8_t i;
(void)i; //avoid warning if updater only
//check UART for data
if (ESPCOM::available(DEFAULT_PRINTER_PIPE)) {
size_t len = ESPCOM::available(DEFAULT_PRINTER_PIPE);
uint8_t * sbuf = (uint8_t *)malloc(len+1);
if(!sbuf) {
return false;
}
sbuf[len] = '\0';
ESPCOM::readBytes (DEFAULT_PRINTER_PIPE, sbuf, len);
#ifdef TCP_IP_DATA_FEATURE
if (!async && !CONFIG::is_locked(FLAG_BLOCK_TCP)) {
if ((WiFi.getMode() != WIFI_OFF) || !wifi_config.WiFi_on) {
//push UART data to all connected tcp clients
for (i = 0; i < MAX_SRV_CLIENTS; i++) {
if (serverClients[i] && serverClients[i].connected() ) {
serverClients[i].write (sbuf, len);
delay (0);
}
}
}
}
#endif
#ifdef WS_DATA_FEATURE
#if defined (ASYNCWEBSERVER)
if (!CONFIG::is_locked(FLAG_BLOCK_WSOCKET)) {
web_interface->web_socket.textAll(sbuf, len);
}
#else
if (!CONFIG::is_locked(FLAG_BLOCK_WSOCKET) && socket_server) {
#ifndef DEBUG_OUTPUT_SOCKET
if(socket_server){
socket_server->sendBIN(current_socket_id,sbuf,len);
}
#endif
}
#endif
#endif
//process data if any
COMMAND::read_buffer_serial (sbuf, len);
free(sbuf);
return true;
} else {
return false;
}
}
#ifdef TCP_IP_DATA_FEATURE
void ESPCOM::processFromTCP2Serial()
{
uint8_t i, data;
//check if there are any new clients
if (data_server->hasClient() ) {
for (i = 0; i < MAX_SRV_CLIENTS; i++) {
//find free/disconnected spot
if (!serverClients[i] || !serverClients[i].connected() ) {
if (serverClients[i]) {
serverClients[i].stop();
}
serverClients[i] = data_server->available();
continue;
}
}
//no free/disconnected spot so reject
WiFiClient serverClient = data_server->available();
serverClient.stop();
}
//check clients for data
//to avoid any pollution if Uploading file to SDCard
if (!((web_interface->blockserial) || CONFIG::is_locked(FLAG_BLOCK_TCP) || CONFIG::is_locked(FLAG_BLOCK_SERIAL))) {
for (i = 0; i < MAX_SRV_CLIENTS; i++) {
if (serverClients[i] && serverClients[i].connected() ) {
if (serverClients[i].available() ) {
//get data from the tcp client and push it to the UART
while (serverClients[i].available() ) {
data = serverClients[i].read();
ESPCOM::write(DEFAULT_PRINTER_PIPE, data);
COMMAND::read_buffer_tcp (data);
}
}
}
}
}
}
#endif