initial commit
This commit is contained in:
38
src/DummyStream.cpp
Normal file
38
src/DummyStream.cpp
Normal file
@ -0,0 +1,38 @@
|
||||
#include <DummyStream.h>
|
||||
|
||||
DummyStream::DummyStream()
|
||||
{
|
||||
}
|
||||
|
||||
DummyStream::~DummyStream()
|
||||
{
|
||||
}
|
||||
|
||||
int DummyStream::available()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DummyStream::read()
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int DummyStream::peek()
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
void DummyStream::flush()
|
||||
{
|
||||
}
|
||||
|
||||
size_t DummyStream::write(uint8_t)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t DummyStream::write(const uint8_t *buffer, size_t size)
|
||||
{
|
||||
return 0;
|
||||
}
|
21
src/DummyStream.h
Normal file
21
src/DummyStream.h
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef DUMMYSTREAM_H
|
||||
#define DUMMYSTREAM_H
|
||||
|
||||
#include <Stream.h>
|
||||
|
||||
class DummyStream : public Stream
|
||||
{
|
||||
public:
|
||||
DummyStream();
|
||||
~DummyStream();
|
||||
|
||||
int available();
|
||||
int read();
|
||||
int peek();
|
||||
void flush();
|
||||
|
||||
size_t write(uint8_t);
|
||||
size_t write(const uint8_t *buffer, size_t size);
|
||||
};
|
||||
|
||||
#endif
|
10
src/bafang.cpp
Normal file
10
src/bafang.cpp
Normal file
@ -0,0 +1,10 @@
|
||||
#include <Arduino.h>
|
||||
|
||||
#include "utils.h"
|
||||
#include "main.h"
|
||||
#include "bafang.h"
|
||||
|
||||
namespace Huawei {
|
||||
|
||||
|
||||
}
|
11
src/bafang.h
Normal file
11
src/bafang.h
Normal file
@ -0,0 +1,11 @@
|
||||
#ifndef BAFANG_H
|
||||
#define BAFANG_H
|
||||
#include <stdint.h>
|
||||
|
||||
namespace Bafang {
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
#endif
|
140
src/commands.cpp
Normal file
140
src/commands.cpp
Normal file
@ -0,0 +1,140 @@
|
||||
#include <Arduino.h>
|
||||
#include <WiFi.h>
|
||||
|
||||
#include "utils.h"
|
||||
#include "main.h"
|
||||
#include "bafang.h"
|
||||
#include "commands.h"
|
||||
|
||||
namespace Commands {
|
||||
|
||||
int parseLine(char *line)
|
||||
{
|
||||
const int MAX_ARGV = 16;
|
||||
char *lineStart = line;
|
||||
char *argv[MAX_ARGV];
|
||||
int argc = 0;
|
||||
bool found = false;
|
||||
bool end = false;
|
||||
bool inString = false;
|
||||
|
||||
while(1)
|
||||
{
|
||||
if(*line == '"' && (line == lineStart || *(line - 1) != '\\'))
|
||||
{
|
||||
inString ^= true;
|
||||
if(!inString)
|
||||
{
|
||||
found = true;
|
||||
end = true;
|
||||
lineStart++;
|
||||
}
|
||||
}
|
||||
|
||||
if(!inString && *line == ' ')
|
||||
end = true;
|
||||
|
||||
if(end || !*line)
|
||||
{
|
||||
if(found && argc < MAX_ARGV)
|
||||
argv[argc++] = lineStart;
|
||||
|
||||
found = false;
|
||||
end = false;
|
||||
|
||||
if(!*line)
|
||||
break;
|
||||
|
||||
*line = 0;
|
||||
lineStart = ++line;
|
||||
continue;
|
||||
}
|
||||
|
||||
line++;
|
||||
found = true;
|
||||
}
|
||||
|
||||
if(!argc)
|
||||
return -1;
|
||||
|
||||
for(int i = 0; g_Commands[i].cmd; i++)
|
||||
{
|
||||
if(strcmp(g_Commands[i].cmd, argv[0]) == 0)
|
||||
{
|
||||
int ret = g_Commands[i].fun(argc, argv);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int CMD_help(int argc, char **argv)
|
||||
{
|
||||
Main::channel()->println("Available Commands\n------------------");
|
||||
|
||||
int i = 0;
|
||||
while(g_Commands[i].cmd)
|
||||
{
|
||||
Main::channel()->printf("%17s %s\n", g_Commands[i].cmd, g_Commands[i].help);
|
||||
i++;
|
||||
}
|
||||
Main::channel()->println();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CMD_debug(int argc, char **argv)
|
||||
{
|
||||
if(argc != 2) {
|
||||
Main::channel()->println("Usage: debug <0|1>");
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool debug = false;
|
||||
if(strtoul(argv[1], NULL, 10))
|
||||
debug = true;
|
||||
|
||||
Main::g_Debug[Main::g_CurrentChannel] = debug;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CMD_wifi(int argc, char **argv)
|
||||
{
|
||||
Main::channel()->printf("connected: %d\n", WiFi.status());
|
||||
Main::channel()->println(WiFi.localIP());
|
||||
WiFi.printDiag(*Main::channel());
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CMD_serial(int argc, char **argv)
|
||||
{
|
||||
if(argc != 3) {
|
||||
Main::channel()->println("Usage: serial <0|1|2> <text>");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int port = strtoul(argv[1], NULL, 10);
|
||||
|
||||
if(port == 0)
|
||||
Serial.println(argv[2]);
|
||||
else if(port == 1)
|
||||
Serial1.println(argv[2]);
|
||||
else if(port == 2)
|
||||
Serial2.println(argv[2]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
CommandEntry g_Commands[] =
|
||||
{
|
||||
{"help", CMD_help, " : Display list of commands"},
|
||||
{"debug", CMD_debug, " : debug <0|1>"},
|
||||
{"wifi", CMD_wifi, " : show wifi config"},
|
||||
{"serial", CMD_serial, " : write to serial <0|1|2> <text>"},
|
||||
{ 0, 0, 0 }
|
||||
};
|
||||
|
||||
}
|
21
src/commands.h
Normal file
21
src/commands.h
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef COMMANDS_H
|
||||
#define COMMANDS_H
|
||||
|
||||
namespace Commands {
|
||||
|
||||
int parseLine(char *line);
|
||||
|
||||
struct CommandEntry
|
||||
{
|
||||
const char *cmd;
|
||||
int (*fun)(int argc, char *argv[]);
|
||||
const char *help;
|
||||
};
|
||||
|
||||
extern CommandEntry g_Commands[];
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
160
src/main.cpp
Normal file
160
src/main.cpp
Normal file
@ -0,0 +1,160 @@
|
||||
#include <Arduino.h>
|
||||
#include <WiFi.h>
|
||||
#include <ArduinoOTA.h>
|
||||
#include <BluetoothSerial.h>
|
||||
#include "DummyStream.h"
|
||||
|
||||
#include "bafang.h"
|
||||
#include "commands.h"
|
||||
#include "main.h"
|
||||
|
||||
WiFiServer server(23);
|
||||
WiFiClient serverClient;
|
||||
|
||||
BluetoothSerial SerialBT;
|
||||
DummyStream SerialDummy;
|
||||
|
||||
const char g_WIFI_SSID[] = "BotoX";
|
||||
const char g_WIFI_Passphrase[] = "D4701B981E5F34EF087DE8DA25F19B47F48E0FEA972FD10E3E6CFEE29C431A1F";
|
||||
|
||||
namespace Main
|
||||
{
|
||||
|
||||
int g_CurrentChannel = HWSERIAL;
|
||||
bool g_Debug[NUM_CHANNELS];
|
||||
char g_SerialBuffer[NUM_CHANNELS][255];
|
||||
int g_SerialBufferPos[NUM_CHANNELS];
|
||||
|
||||
unsigned long g_Time1000;
|
||||
|
||||
|
||||
void init()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while(!Serial);
|
||||
Serial.println("BOOTED!");
|
||||
|
||||
Serial1.begin(115200);
|
||||
Serial2.begin(115200);
|
||||
|
||||
WiFi.setHostname("ESP32-BAFANG");
|
||||
if(!WiFi.begin(g_WIFI_SSID, g_WIFI_Passphrase))
|
||||
Serial.println("WiFi config error!");
|
||||
else {
|
||||
WiFi.setAutoConnect(true);
|
||||
}
|
||||
|
||||
SerialBT.begin("ESP32-BAFANG");
|
||||
|
||||
ArduinoOTA.onStart([]() {
|
||||
String type;
|
||||
if (ArduinoOTA.getCommand() == U_FLASH)
|
||||
type = "sketch";
|
||||
else // U_SPIFFS
|
||||
type = "filesystem";
|
||||
|
||||
// NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
|
||||
Serial.println("Start updating " + type);
|
||||
})
|
||||
.onEnd([]() {
|
||||
Serial.println("\nEnd");
|
||||
})
|
||||
.onProgress([](unsigned int progress, unsigned int total) {
|
||||
Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
|
||||
})
|
||||
.onError([](ota_error_t error) {
|
||||
Serial.printf("Error[%u]: ", error);
|
||||
if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
|
||||
else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
|
||||
else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
|
||||
else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
|
||||
else if (error == OTA_END_ERROR) Serial.println("End Failed");
|
||||
});
|
||||
|
||||
ArduinoOTA.begin();
|
||||
|
||||
server.begin();
|
||||
server.setNoDelay(true);
|
||||
|
||||
|
||||
}
|
||||
|
||||
Stream* channel(int num)
|
||||
{
|
||||
if(num == -1)
|
||||
num = g_CurrentChannel;
|
||||
|
||||
if(num == BTSERIAL && SerialBT.hasClient())
|
||||
return &SerialBT;
|
||||
else if(num == TCPSERIAL && serverClient)
|
||||
return &serverClient;
|
||||
else if(num == HWSERIAL)
|
||||
return &Serial;
|
||||
|
||||
return &SerialDummy;
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
if(g_Debug[g_CurrentChannel])
|
||||
{
|
||||
while(Serial1.available())
|
||||
{
|
||||
channel()->write(Serial1.read());
|
||||
}
|
||||
|
||||
while(Serial2.available())
|
||||
{
|
||||
channel()->write(Serial2.read());
|
||||
}
|
||||
}
|
||||
|
||||
ArduinoOTA.handle();
|
||||
|
||||
if(server.hasClient())
|
||||
{
|
||||
if(serverClient) // disconnect current client if any
|
||||
serverClient.stop();
|
||||
serverClient = server.available();
|
||||
}
|
||||
if(!serverClient)
|
||||
serverClient.stop();
|
||||
|
||||
for(int i = 0; i < NUM_CHANNELS; i++)
|
||||
{
|
||||
while(channel(i)->available())
|
||||
{
|
||||
g_CurrentChannel = i;
|
||||
int c = channel(i)->read();
|
||||
if(c == '\r' || c == '\n' || g_SerialBufferPos[i] == sizeof(*g_SerialBuffer))
|
||||
{
|
||||
g_SerialBuffer[i][g_SerialBufferPos[i]] = 0;
|
||||
|
||||
if(g_SerialBufferPos[i])
|
||||
Commands::parseLine(g_SerialBuffer[i]);
|
||||
|
||||
g_SerialBufferPos[i] = 0;
|
||||
continue;
|
||||
}
|
||||
g_SerialBuffer[i][g_SerialBufferPos[i]] = c;
|
||||
++g_SerialBufferPos[i];
|
||||
}
|
||||
}
|
||||
|
||||
if((millis() - g_Time1000) > 1000)
|
||||
{
|
||||
g_Time1000 = millis();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
Main::init();
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
Main::loop();
|
||||
}
|
30
src/main.h
Normal file
30
src/main.h
Normal file
@ -0,0 +1,30 @@
|
||||
#ifndef MAIN_H
|
||||
#define MAIN_H
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#define MAX_SRV_CLIENTS 4
|
||||
|
||||
namespace Main {
|
||||
|
||||
enum {
|
||||
NOSERIAL = -1,
|
||||
HWSERIAL = 0,
|
||||
BTSERIAL = 1,
|
||||
TCPSERIAL = 2,
|
||||
NUM_CHANNELS
|
||||
};
|
||||
|
||||
void init();
|
||||
void loop();
|
||||
|
||||
Stream* channel(int num = -1);
|
||||
|
||||
extern int g_CurrentChannel;
|
||||
extern bool g_Debug[NUM_CHANNELS];
|
||||
extern char g_SerialBuffer[NUM_CHANNELS][255];
|
||||
extern int g_SerialBufferPos[NUM_CHANNELS];
|
||||
|
||||
};
|
||||
|
||||
#endif
|
63
src/utils.cpp
Normal file
63
src/utils.cpp
Normal file
@ -0,0 +1,63 @@
|
||||
#include <string.h>
|
||||
#include "utils.h"
|
||||
|
||||
static inline uint8_t _char2byte(char c)
|
||||
{
|
||||
if('0' <= c && c <= '9') return (uint8_t)(c - '0');
|
||||
if('A' <= c && c <= 'F') return (uint8_t)(c - 'A' + 10);
|
||||
if('a' <= c && c <= 'f') return (uint8_t)(c - 'a' + 10);
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
int hex2bytes(const char *str, uint8_t *bytes, int32_t length)
|
||||
{
|
||||
int result;
|
||||
if(!str || !bytes || length <= 0)
|
||||
return -1;
|
||||
|
||||
for(result = 0; *str; result++)
|
||||
{
|
||||
uint8_t msn = _char2byte(*str++);
|
||||
if(msn == 0xFF) return -1;
|
||||
|
||||
uint8_t lsn = _char2byte(*str++);
|
||||
if(lsn == 0xFF) return -1;
|
||||
|
||||
uint8_t bin = (msn << 4) + lsn;
|
||||
|
||||
if(length-- <= 0)
|
||||
return -1;
|
||||
|
||||
*bytes++ = bin;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void bytes2hex(const uint8_t *bytes, int32_t length, char *str, int32_t strLength)
|
||||
{
|
||||
const char binHex[] = "0123456789ABCDEF";
|
||||
|
||||
if(!str || strLength < 3)
|
||||
return;
|
||||
*str = 0;
|
||||
|
||||
if(!bytes || length <= 0 || strLength <= 2 * length)
|
||||
{
|
||||
strncpy(str, "ERR", strLength);
|
||||
return;
|
||||
}
|
||||
|
||||
for(; length > 0; length--, strLength -= 2)
|
||||
{
|
||||
uint8_t byte = *bytes++;
|
||||
|
||||
*str++ = binHex[(byte >> 4) & 0x0F];
|
||||
*str++ = binHex[byte & 0x0F];
|
||||
}
|
||||
|
||||
if(strLength-- <= 0)
|
||||
return;
|
||||
|
||||
*str++ = 0;
|
||||
}
|
8
src/utils.h
Normal file
8
src/utils.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef UTILS_H
|
||||
#define UTILS_H
|
||||
#include <stdint.h>
|
||||
|
||||
int hex2bytes(const char *str, uint8_t *bytes, int32_t length);
|
||||
void bytes2hex(const uint8_t *bytes, int32_t length, char *str, int32_t strLength);
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user