use pio native to build standalone

This commit is contained in:
Proddy
2023-01-06 14:14:03 +01:00
parent ad2dbd6fc5
commit fbf799e4c4
13 changed files with 484 additions and 134 deletions

5
.gitignore vendored
View File

@@ -1,5 +1,7 @@
# vscode
.vscode
.vscode/c_cpp_properties.json
.vscode/extensions.json
.vscode/launch.json
# build
build/
@@ -43,3 +45,4 @@ build_wrapper_output_directory/
# other build files
dump_entities.csv
dump_entities.xls*

23
.vscode/tasks.json vendored Normal file
View File

@@ -0,0 +1,23 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "PlatformIO: Execute EMS-ESP (standalone)",
"type": "shell",
"command": "./.pio/build/standalone/program",
"linux": {
"options": {
"env": {
// Workaroung for sdl2 `-m32` crash
// https://bugs.launchpad.net/ubuntu/+source/libsdl2/+bug/1775067/comments/7
"DBUS_FATAL_WARNINGS": "0"
}
}
},
"dependsOn": ["PlatformIO: Build EMS-ESP (standalone)"],
"problemMatcher": []
}
]
}

View File

@@ -15,6 +15,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef EMSESP_STANDALONE
#include <Arduino.h>
#include <stdio.h>
#include <stdarg.h>
@@ -125,3 +127,5 @@ double ledcSetup(uint8_t chan, double freq, uint8_t bit_num) {
};
void ledcAttachPin(uint8_t pin, uint8_t chan){};
void ledcWrite(uint8_t chan, uint32_t duty){};
#endif

View File

@@ -24,9 +24,13 @@
#include <cstdint>
#include <cstring>
#include <string>
#include <algorithm> // for count_if
#include "WString.h"
#include <Print.h>
#include <Printable.h>
#include <Stream.h>
#include <WString.h>
#include <iostream>
@@ -86,129 +90,83 @@ int vsnprintf_P(char * str, size_t size, const char * format, va_list ap);
class Print;
class Printable {
public:
virtual size_t printTo(Print & print) const = 0;
};
class Print {
public:
virtual size_t write(uint8_t c) = 0;
virtual size_t write(const uint8_t * buffer, size_t size) = 0;
size_t print(char c) {
return write((uint8_t)c);
}
size_t print(const char * data) {
return write(reinterpret_cast<const uint8_t *>(data), strlen(data));
}
size_t print(const __FlashStringHelper * data) {
return print(reinterpret_cast<const char *>(data));
}
size_t print(const Printable & printable) {
return printable.printTo(*this);
}
size_t print(int value) {
return print(std::to_string(value).c_str());
}
size_t print(unsigned int value) {
return print(std::to_string(value).c_str());
}
size_t print(long value) {
return print(std::to_string(value).c_str());
}
size_t print(unsigned long value) {
return print(std::to_string(value).c_str());
}
size_t println() {
return print("\r\n");
}
size_t println(const char * data) {
return print(data) + println();
}
size_t println(const __FlashStringHelper * data) {
return print(reinterpret_cast<const char *>(data)) + println();
}
size_t println(const Printable & printable) {
return printable.printTo(*this) + println();
}
size_t println(int value) {
return print(std::to_string(value).c_str()) + println();
}
size_t println(unsigned int value) {
return print(std::to_string(value).c_str()) + println();
}
size_t println(long value) {
return print(std::to_string(value).c_str()) + println();
}
size_t println(unsigned long value) {
return print(std::to_string(value).c_str()) + println();
}
virtual void flush(){};
size_t print(const String & str) {
return print(str.c_str());
}
};
class Stream : public Print {
public:
virtual int available() = 0;
virtual int read() = 0;
virtual int peek() = 0;
};
class NativeConsole : public Stream {
public:
class NativeConsole: public Stream {
public:
void begin(unsigned long baud __attribute__((unused))) {
}
int available() override {
if (peek() >= 0) {
if (peek_ != -1)
return 1;
} else {
return 0;
}
struct timeval timeout;
fd_set rfds;
FD_ZERO(&rfds);
FD_SET(STDIN_FILENO, &rfds);
timeout.tv_sec = 0;
timeout.tv_usec = 1000;
return ::select(STDIN_FILENO + 1, &rfds, NULL, NULL, &timeout) > 0 ? 1 : 0;
}
int read() override {
peek();
if (peek_) {
peek_ = false;
return peek_data_;
} else {
return -1;
if (peek_ != -1) {
uint8_t c = peek_;
peek_ = -1;
return c;
}
if (available() > 0) {
uint8_t c;
int ret = ::read(STDIN_FILENO, &c, 1);
if (ret == 0) {
/* Ctrl+D */
return '\x04';
} else if (ret == 1) {
/* Remap Ctrl+Z to Ctrl-\ */
if (c == '\x1A')
c = '\x1C';
return c;
} else {
exit(1);
}
}
return -1;
}
int peek() override {
if (!peek_) {
int ret = ::read(STDIN_FILENO, &peek_data_, 1);
peek_ = ret > 0;
}
if (peek_ == -1)
peek_ = read();
if (peek_) {
return peek_data_;
} else {
return -1;
}
return peek_;
}
size_t write(uint8_t c) override {
return ::write(STDOUT_FILENO, &c, 1);
if (::write(STDOUT_FILENO, &c, 1) == 1) {
return 1;
} else {
exit(1);
}
}
size_t write(const uint8_t * buffer, size_t size) override {
return ::write(STDOUT_FILENO, buffer, size);
size_t write(const uint8_t *buffer, size_t size) {
if (::write(STDOUT_FILENO, buffer, size) == (ssize_t)size) {
return size;
} else {
exit(1);
}
}
private:
bool peek_ = false;
unsigned char peek_data_;
private:
int peek_ = -1;
};
#include <Network.h>
#include "Network.h"
extern NativeConsole Serial;
extern ETHClass ETH;

75
lib_standalone/Print.h Normal file
View File

@@ -0,0 +1,75 @@
/*
* mcu-app - Microcontroller application framework
* Copyright 2022 Simon Arlott
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PRINT_H_
#define PRINT_H_
#include <stdarg.h>
#include <unistd.h>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <string>
#include <Printable.h>
#include <WString.h>
int vsnprintf_P(char *str, size_t size, const char *format, va_list ap);
class Print {
public:
virtual size_t write(uint8_t c) = 0;
virtual size_t write(const uint8_t *buffer, size_t size) { for (size_t i = 0; i < size; i++) { write(*buffer); buffer++; }; return size; };
void setWriteError(int err = 1) { err_ = err; }
int getWriteError() { return err_; }
void clearWriteError() {}
size_t print(char c) { return write((uint8_t)c); }
size_t print(const char *data) { return write(reinterpret_cast<const uint8_t *>(data), strlen(data)); }
size_t print(const Printable &printable) { return printable.printTo(*this); }
size_t print(int value) { return print(std::to_string(value).c_str()); }
size_t print(unsigned int value) { return print(std::to_string(value).c_str()); }
size_t print(long value) { return print(std::to_string(value).c_str()); }
size_t print(unsigned long value) { return print(std::to_string(value).c_str()); }
size_t printf(const char * format, ...) {
char str[4096] = { 0 };
va_list ap;
va_start(ap, format);
int ret = vsnprintf_P(str, sizeof(str), format, ap);
va_end(ap);
if (ret < 0)
return ret;
return print(str);
}
size_t println() { return print("\r\n"); }
size_t println(const char *data) { return print(data) + println(); }
size_t println(const Printable &printable) { return printable.printTo(*this) + println(); }
size_t println(int value) { return print(std::to_string(value).c_str()) + println(); }
size_t println(unsigned int value) { return print(std::to_string(value).c_str()) + println(); }
size_t println(long value) { return print(std::to_string(value).c_str()) + println(); }
size_t println(unsigned long value) { return print(std::to_string(value).c_str()) + println(); }
virtual void flush() { };
private:
int err_{0};
};
#endif

View File

@@ -0,0 +1,41 @@
/*
Printable.h - Interface class that allows printing of complex types
Copyright (c) 2011 Adrian McEwen. All right 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
*/
#ifndef Printable_h
#define Printable_h
#include <stdlib.h>
class Print;
/** The Printable class provides a way for new classes to allow themselves to be printed.
By deriving from Printable and implementing the printTo method, it will then be possible
for users to print out instances of this class by passing them into the usual
Print::print and Print::println methods.
*/
class Printable
{
public:
virtual ~Printable() {}
virtual size_t printTo(Print& p) const = 0;
};
#endif

View File

@@ -1,3 +1,5 @@
#ifdef EMSESP_STANDALONE
#include <SecuritySettingsService.h>
#if FT_ENABLED(FT_SECURITY)
@@ -137,3 +139,5 @@ ArJsonRequestHandlerFunction SecuritySettingsService::wrapCallback(ArJsonRequest
}
#endif
#endif

197
lib_standalone/Stream.h Normal file
View File

@@ -0,0 +1,197 @@
/*
Stream.h - base class for character-based streams.
Copyright (c) 2010 David A. Mellis. All right 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
parsing functions based on TextFinder library by Michael Margolis
*/
#ifndef Stream_h
#define Stream_h
#include <inttypes.h>
#include "Print.h"
#include "WString.h"
// compatability macros for testing
/*
#define getInt() parseInt()
#define getInt(skipChar) parseInt(skipchar)
#define getFloat() parseFloat()
#define getFloat(skipChar) parseFloat(skipChar)
#define getString( pre_string, post_string, buffer, length)
readBytesBetween( pre_string, terminator, buffer, length)
*/
class Stream: public Print
{
protected:
unsigned long _timeout; // number of milliseconds to wait for the next char before aborting timed read
unsigned long _startMillis; // used for timeout measurement
int timedRead(); // private method to read stream with timeout
int timedPeek(); // private method to peek stream with timeout
int peekNextDigit(); // returns the next numeric digit in the stream or -1 if timeout
public:
virtual int available() = 0;
virtual int read() = 0;
virtual int peek() = 0;
Stream():_startMillis(0)
{
_timeout = 1000;
}
virtual ~Stream() {}
// parsing methods
void setTimeout(unsigned long timeout); // sets maximum milliseconds to wait for stream data, default is 1 second
unsigned long getTimeout(void);
bool find(const char *target); // reads data from the stream until the target string is found
bool find(uint8_t *target)
{
return find((char *) target);
}
// returns true if target string is found, false if timed out (see setTimeout)
bool find(const char *target, size_t length); // reads data from the stream until the target string of given length is found
bool find(const uint8_t *target, size_t length)
{
return find((char *) target, length);
}
// returns true if target string is found, false if timed out
bool find(char target)
{
return find (&target, 1);
}
bool findUntil(const char *target, const char *terminator); // as find but search ends if the terminator string is found
bool findUntil(const uint8_t *target, const char *terminator)
{
return findUntil((char *) target, terminator);
}
bool findUntil(const char *target, size_t targetLen, const char *terminate, size_t termLen); // as above but search ends if the terminate string is found
bool findUntil(const uint8_t *target, size_t targetLen, const char *terminate, size_t termLen)
{
return findUntil((char *) target, targetLen, terminate, termLen);
}
long parseInt(); // returns the first valid (long) integer value from the current position.
// initial characters that are not digits (or the minus sign) are skipped
// integer is terminated by the first character that is not a digit.
float parseFloat(); // float version of parseInt
virtual size_t readBytes(char *buffer, size_t length) // read chars from stream into buffer
{
size_t total = 0;
while (length-- > 0) {
int c = read();
if (c == -1)
return total;
*buffer = c;
total++;
}
return total;
}
virtual size_t readBytes(uint8_t *buffer, size_t length)
{
return readBytes((char *) buffer, length);
}
// terminates if length characters have been read or timeout (see setTimeout)
// returns the number of characters placed in the buffer (0 means no valid data found)
size_t readBytesUntil(char terminator, char *buffer, size_t length) // as readBytes with terminator character
{
size_t total = 0;
while (length-- > 0) {
int c = read();
if (c == -1 || c == terminator)
return total;
*buffer = c;
total++;
}
return total;
}
size_t readBytesUntil(char terminator, uint8_t *buffer, size_t length)
{
return readBytesUntil(terminator, (char *) buffer, length);
}
// terminates if length characters have been read, timeout, or if the terminator character detected
// returns the number of characters placed in the buffer (0 means no valid data found)
#if 0
// Arduino String functions to be added here
virtual String readString() {
String str;
while (1) {
int c = read();
if (c == -1) {
break;
}
str.concat(c);
}
return str;
}
String readStringUntil(char terminator) {
String str;
while (1) {
int c = read();
if (c == -1 || c == terminator) {
break;
}
str.concat(c);
}
return str;
}
#endif
protected:
long parseInt(char skipChar); // as above but the given skipChar is ignored
// as above but the given skipChar is ignored
// this allows format characters (typically commas) in values to be ignored
float parseFloat(char skipChar); // as above but the given skipChar is ignored
struct MultiTarget {
const char *str; // string you're searching for
size_t len; // length of string you're searching for
size_t index; // index used by the search routine.
};
// This allows you to search for an arbitrary number of strings.
// Returns index of the target that is found first or -1 if timeout occurs.
int findMulti(struct MultiTarget *targets, int tCount);
};
#endif

View File

@@ -1,4 +1,6 @@
#ifdef EMSESP_STANDALONE
#include <Arduino.h>
#include "WString.h"
@@ -66,3 +68,5 @@ size_t strlcat(char * dst, const char * src, size_t siz) {
return (dlen + (s - src)); /* count does not include NUL */
}
#endif

View File

@@ -16,6 +16,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef EMSESP_STANDALONE
#include "emsuart_standalone.h"
#pragma GCC diagnostic push
@@ -86,3 +88,5 @@ char * EMSuart::hextoa(char * result, const uint8_t value) {
} // namespace emsesp
#pragma GCC diagnostic pop
#endif

View File

@@ -2,8 +2,9 @@
; override any settings with your own local ones in pio_local.ini
[platformio]
default_envs = esp32_4M
; default_envs = esp32_4M
; default_envs = esp32_16M
default_envs = standalone
extra_configs =
factory_settings.ini
@@ -16,8 +17,8 @@ core_build_flags =
-D NDEBUG
-D ARDUINO_ARCH_ESP32=1
-D ESP32=1
; -std=gnu++17
; -Os
-std=gnu++17
-Os
; core_unbuild_flags = -std=gnu++11
; core_unbuild_flags = -std=gnu++17
@@ -40,7 +41,6 @@ unbuild_flags =
${common.core_unbuild_flags}
[env]
framework = arduino
monitor_speed = 115200
monitor_raw = yes
upload_speed = 921600
@@ -58,6 +58,7 @@ check_flags =
[env:ci]
extra_scripts = scripts/rename_fw.py
board = esp32dev
framework = arduino
platform = espressif32
board_build.partitions = esp32_partition_4M.csv
board_build.filesystem = littlefs
@@ -69,6 +70,7 @@ extra_scripts =
pre:scripts/build_interface.py
scripts/rename_fw.py
board = esp32dev
framework = arduino
platform = espressif32
board_upload.flash_size = 4MB
board_build.partitions = esp32_partition_4M.csv
@@ -80,6 +82,7 @@ extra_scripts =
pre:scripts/build_interface.py
scripts/rename_fw.py
board = esp32dev
framework = arduino
platform = espressif32
board_upload.flash_size = 16MB
board_build.partitions = esp32_partition_16M.csv
@@ -91,6 +94,7 @@ extra_scripts =
pre:scripts/build_interface.py
scripts/rename_fw.py
board = lolin_c3_mini
framework = arduino
platform = espressif32
board_upload.flash_size = 4MB
board_build.partitions = esp32_partition_4M.csv
@@ -104,6 +108,7 @@ extra_scripts =
pre:scripts/build_interface.py
scripts/rename_fw.py
board = lolin_c3_mini
framework = arduino
platform = espressif32
board_upload.flash_size = 4MB
board_build.partitions = esp32_partition_4M.csv
@@ -115,8 +120,42 @@ extra_scripts =
pre:scripts/build_interface.py
scripts/rename_fw.py
board = lolin_s2_mini
framework = arduino
platform = espressif32
board_upload.flash_size = 4MB
board_build.partitions = esp32_partition_4M.csv
build_flags = ${common.build_flags}
build_unflags = ${common.unbuild_flags}
; see https://docs.platformio.org/en/latest/platforms/native.html#id1
; to build: pio run -e standalone
; to run and build: pio run -e standalone -t exec
[env:standalone]
platform = native
build_flags =
-DARDUINO
-DARDUINOJSON_ENABLE_STD_STRING=1 -DARDUINOJSON_ENABLE_PROGMEM=1 -DARDUINOJSON_ENABLE_ARDUINO_STRING -DARDUINOJSON_USE_DOUBLE=0
-DEMSESP_DEBUG -DEMSESP_STANDALONE -DEMSESP_USE_SERIAL
-DEMSESP_DEFAULT_LOCALE=\"en\" -DEMSESP_DEFAULT_TX_MODE=8 -DEMSESP_DEFAULT_VERSION=\"3.5.0-dev\" -DEMSESP_DEFAULT_BOARD_PROFILE=\"S32\"
-lpthread
-std=gnu++17 -Og -ggdb
build_src_flags =
-Wall -Wextra -Werror -Wswitch-enum -Wno-unused-parameter -Wno-inconsistent-missing-override
-I./lib_standalone
-I./lib/ArduinoJson/src
-I./lib/uuid-common/src
-I./lib/uuid-console/src
-I./lib/uuid-log/src
-I./lib/semver
-I./lib/PButton
build_src_filter =
+<*>
-<.git/>
+<../lib_standalone>
+<../lib/uuid-common>
+<../lib/uuid-console>
+<../lib/uuid-log>
+<../lib/semver>
+<../lib/PButton>
lib_compat_mode = off
lib_ldf_mode = off

View File

@@ -1451,7 +1451,8 @@ void Boiler::process_UBAErrorMessage2(std::shared_ptr<const Telegram> telegram)
snprintf(&code[3], sizeof(code) - 3, "(%d) %02d.%02d.%04d %02d:%02d - now", codeNo, start_day, start_month, start_year, start_hour, start_min);
}
} else { // no clock, the uptime is stored https://github.com/emsesp/EMS-ESP32/issues/121
uint32_t starttime, endtime;
uint32_t starttime = 0;
uint32_t endtime = 0;
telegram->read_value(starttime, 11, 3);
telegram->read_value(endtime, 16, 3);
snprintf(&code[3], sizeof(code) - 3, "(%d) @uptime %d - %d min", codeNo, starttime, endtime);

View File

@@ -32,6 +32,8 @@ WebStatusService::WebStatusService(AsyncWebServer * server, SecurityManager * se
// handles both WiFI and Ethernet
void WebStatusService::WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info) {
#ifndef EMSESP_STANDALONE
switch (event) {
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
EMSESP::logger().warning("WiFi disconnected. Reason code=%s", disconnectReason(info.wifi_sta_disconnected.reason)); // IDF 4.0
@@ -39,9 +41,7 @@ void WebStatusService::WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info) {
break;
case ARDUINO_EVENT_WIFI_STA_GOT_IP:
#ifndef EMSESP_STANDALONE
EMSESP::logger().info("WiFi connected with IP=%s, hostname=%s", WiFi.localIP().toString().c_str(), WiFi.getHostname());
#endif
EMSESP::system_.syslog_init();
mDNS_start();
EMSESP::system_.send_info_mqtt("connected");
@@ -63,9 +63,7 @@ void WebStatusService::WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info) {
case ARDUINO_EVENT_ETH_GOT_IP:
// prevent double calls
if (!EMSESP::system_.ethernet_connected()) {
#ifndef EMSESP_STANDALONE
EMSESP::logger().info("Ethernet connected with IP=%s, speed %d Mbps", ETH.localIP().toString().c_str(), ETH.linkSpeed());
#endif
// EMSESP::system_.send_heartbeat();
EMSESP::system_.syslog_init();
EMSESP::system_.ethernet_connected(true);
@@ -84,7 +82,6 @@ void WebStatusService::WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info) {
EMSESP::system_.ethernet_connected(false);
break;
#ifndef EMSESP_STANDALONE
case ARDUINO_EVENT_WIFI_STA_CONNECTED:
EMSESP::esp8266React.getNetworkSettingsService()->read([&](NetworkSettings & networkSettings) {
if (networkSettings.enableIPv6) {
@@ -112,11 +109,11 @@ void WebStatusService::WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info) {
mDNS_start();
EMSESP::system_.send_info_mqtt("connected");
break;
#endif
default:
break;
}
#endif
}
void WebStatusService::webStatusService(AsyncWebServerRequest * request) {