initial commit
This commit is contained in:
commit
d46849736f
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
.pio
|
||||
.vscode/.browse.c_cpp.db*
|
||||
.vscode/c_cpp_properties.json
|
||||
.vscode/launch.json
|
||||
.vscode/ipch
|
10
.vscode/extensions.json
vendored
Normal file
10
.vscode/extensions.json
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
// See http://go.microsoft.com/fwlink/?LinkId=827846
|
||||
// for the documentation about the extensions.json format
|
||||
"recommendations": [
|
||||
"platformio.platformio-ide"
|
||||
],
|
||||
"unwantedRecommendations": [
|
||||
"ms-vscode.cpptools-extension-pack"
|
||||
]
|
||||
}
|
58
.vscode/settings.json
vendored
Normal file
58
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,58 @@
|
||||
{
|
||||
"files.associations": {
|
||||
"algorithm": "cpp",
|
||||
"array": "cpp",
|
||||
"atomic": "cpp",
|
||||
"*.tcc": "cpp",
|
||||
"cctype": "cpp",
|
||||
"cerrno": "cpp",
|
||||
"climits": "cpp",
|
||||
"clocale": "cpp",
|
||||
"cmath": "cpp",
|
||||
"cstdarg": "cpp",
|
||||
"cstddef": "cpp",
|
||||
"cstdint": "cpp",
|
||||
"cstdio": "cpp",
|
||||
"cstdlib": "cpp",
|
||||
"cstring": "cpp",
|
||||
"ctime": "cpp",
|
||||
"cwchar": "cpp",
|
||||
"cwctype": "cpp",
|
||||
"deque": "cpp",
|
||||
"map": "cpp",
|
||||
"string": "cpp",
|
||||
"unordered_map": "cpp",
|
||||
"unordered_set": "cpp",
|
||||
"vector": "cpp",
|
||||
"exception": "cpp",
|
||||
"functional": "cpp",
|
||||
"iterator": "cpp",
|
||||
"memory": "cpp",
|
||||
"memory_resource": "cpp",
|
||||
"numeric": "cpp",
|
||||
"optional": "cpp",
|
||||
"random": "cpp",
|
||||
"string_view": "cpp",
|
||||
"system_error": "cpp",
|
||||
"tuple": "cpp",
|
||||
"type_traits": "cpp",
|
||||
"utility": "cpp",
|
||||
"fstream": "cpp",
|
||||
"initializer_list": "cpp",
|
||||
"iomanip": "cpp",
|
||||
"ios": "cpp",
|
||||
"iosfwd": "cpp",
|
||||
"istream": "cpp",
|
||||
"limits": "cpp",
|
||||
"locale": "cpp",
|
||||
"new": "cpp",
|
||||
"ostream": "cpp",
|
||||
"queue": "cpp",
|
||||
"sstream": "cpp",
|
||||
"stdexcept": "cpp",
|
||||
"streambuf": "cpp",
|
||||
"cinttypes": "cpp",
|
||||
"cstdbool": "cpp",
|
||||
"typeinfo": "cpp"
|
||||
}
|
||||
}
|
39
include/README
Normal file
39
include/README
Normal file
@ -0,0 +1,39 @@
|
||||
|
||||
This directory is intended for project header files.
|
||||
|
||||
A header file is a file containing C declarations and macro definitions
|
||||
to be shared between several project source files. You request the use of a
|
||||
header file in your project source file (C, C++, etc) located in `src` folder
|
||||
by including it, with the C preprocessing directive `#include'.
|
||||
|
||||
```src/main.c
|
||||
|
||||
#include "header.h"
|
||||
|
||||
int main (void)
|
||||
{
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
Including a header file produces the same results as copying the header file
|
||||
into each source file that needs it. Such copying would be time-consuming
|
||||
and error-prone. With a header file, the related declarations appear
|
||||
in only one place. If they need to be changed, they can be changed in one
|
||||
place, and programs that include the header file will automatically use the
|
||||
new version when next recompiled. The header file eliminates the labor of
|
||||
finding and changing all the copies as well as the risk that a failure to
|
||||
find one copy will result in inconsistencies within a program.
|
||||
|
||||
In C, the usual convention is to give header files names that end with `.h'.
|
||||
It is most portable to use only letters, digits, dashes, and underscores in
|
||||
header file names, and at most one dot.
|
||||
|
||||
Read more about using header files in official GCC documentation:
|
||||
|
||||
* Include Syntax
|
||||
* Include Operation
|
||||
* Once-Only Headers
|
||||
* Computed Includes
|
||||
|
||||
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
|
21
platformio.ini
Normal file
21
platformio.ini
Normal file
@ -0,0 +1,21 @@
|
||||
; PlatformIO Project Configuration File
|
||||
;
|
||||
; Build options: build flags, source filter
|
||||
; Upload options: custom upload port, speed and extra flags
|
||||
; Library options: dependencies, extra library storages
|
||||
; Advanced options: extra scripting
|
||||
;
|
||||
; Please visit documentation for the other options and examples
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[env:esp32dev]
|
||||
platform = espressif32
|
||||
board = esp32dev
|
||||
framework = arduino
|
||||
check_skip_packages = yes
|
||||
monitor_speed = 115200
|
||||
debug_tool = esp-prog
|
||||
board_build.partitions = no_ota.csv
|
||||
lib_deps =
|
||||
adafruit/Adafruit NeoPixel@^1.11.0
|
||||
ottowinter/AsyncMqttClient-esphome@^0.8.6
|
0
src/config/config.h
Normal file
0
src/config/config.h
Normal file
50
src/infra/mqtt.cpp
Normal file
50
src/infra/mqtt.cpp
Normal file
@ -0,0 +1,50 @@
|
||||
#include <Arduino.h>
|
||||
#include "infra/mqtt.h"
|
||||
|
||||
void connectToMqtt() {
|
||||
Serial.println("Connecting to MQTT...");
|
||||
mqttClient.connect();
|
||||
}
|
||||
|
||||
void onMqttConnect(bool sessionPresent) {
|
||||
Serial.println("Connected to MQTT.");
|
||||
Serial.print("Session present: ");
|
||||
Serial.println(sessionPresent);
|
||||
|
||||
uint16_t packetIdSub = mqttClient.subscribe("esp32/led", 0);
|
||||
Serial.print("Subscribing at QoS 0, packetId: ");
|
||||
Serial.println(packetIdSub);
|
||||
}
|
||||
|
||||
void onMqttDisconnect(AsyncMqttClientDisconnectReason reason) {
|
||||
Serial.println("Disconnected from MQTT.");
|
||||
if (WiFi.isConnected()) {
|
||||
xTimerStart(mqttReconnectTimer, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void onMqttSubscribe(uint16_t packetId, uint8_t qos) {
|
||||
Serial.println("Subscribe acknowledged.");
|
||||
Serial.print(" packetId: ");
|
||||
Serial.println(packetId);
|
||||
Serial.print(" qos: ");
|
||||
Serial.println(qos);
|
||||
}
|
||||
|
||||
void onMqttUnsubscribe(uint16_t packetId) {
|
||||
Serial.println("Unsubscribe acknowledged.");
|
||||
Serial.print(" packetId: ");
|
||||
Serial.println(packetId);
|
||||
}
|
||||
|
||||
void onMqttPublish(uint16_t packetId) {
|
||||
Serial.println("Publish acknowledged.");
|
||||
Serial.print(" packetId: ");
|
||||
Serial.println(packetId);
|
||||
}
|
||||
|
||||
void sendDataToMQTT(int flatNumber) {
|
||||
char num_char[3];
|
||||
sprintf(num_char, "%d", flatNumber);
|
||||
mqttClient.publish("/digitum/out/flat_number", 2, true, num_char);
|
||||
}
|
18
src/infra/mqtt.h
Normal file
18
src/infra/mqtt.h
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef INFRA_MQTT_H
|
||||
#define INFRA_MQTT_H
|
||||
|
||||
#include <HTTPClient.h>
|
||||
#include <AsyncMqttClient.h>
|
||||
|
||||
AsyncMqttClient mqttClient;
|
||||
TimerHandle_t mqttReconnectTimer;
|
||||
|
||||
void connectToMqtt();
|
||||
void onMqttConnect(bool sessionPresent);
|
||||
void onMqttDisconnect(AsyncMqttClientDisconnectReason reason);
|
||||
void onMqttSubscribe(uint16_t packetId, uint8_t qos);
|
||||
void onMqttUnsubscribe(uint16_t packetId);
|
||||
void onMqttPublish(uint16_t packetId);
|
||||
void sendDataToMQTT(int flatNumber);
|
||||
|
||||
#endif // INFRA_MQTT_H
|
214
src/main.cpp
Normal file
214
src/main.cpp
Normal file
@ -0,0 +1,214 @@
|
||||
#include <Arduino.h>
|
||||
#include <ETH.h>
|
||||
#include <SPI.h>
|
||||
#include <SD.h>
|
||||
#include <HTTPClient.h>
|
||||
#include <IPAddress.h>
|
||||
#include <AsyncMqttClient.h>
|
||||
|
||||
#include "infra/mqtt.h"
|
||||
#include "utils/print.h"
|
||||
#include "stateMachine.h"
|
||||
|
||||
#define LEDS_PIN 32
|
||||
#define DRY_CONT_PIN 15
|
||||
#define DOOR_SENS_PIN 114
|
||||
|
||||
#define DATA_PIN 12
|
||||
#define DATA_PERIOD 240 // microseconds
|
||||
|
||||
#define PRINT_RAW_SIGNAL_FLAG 0
|
||||
|
||||
/*
|
||||
* ETH_CLOCK_GPIO0_IN - default: external clock from crystal oscillator
|
||||
* ETH_CLOCK_GPIO0_OUT - 50MHz clock from internal APLL output on GPIO0 - possibly an inverter is needed for LAN8720
|
||||
* ETH_CLOCK_GPIO16_OUT - 50MHz clock from internal APLL output on GPIO16 - possibly an inverter is needed for LAN8720
|
||||
* ETH_CLOCK_GPIO17_OUT - 50MHz clock from internal APLL inverted output on GPIO17 - tested with LAN8720
|
||||
*/
|
||||
#define ETH_CLK_MODE ETH_CLOCK_GPIO17_OUT
|
||||
|
||||
// Pin# of the enable signal for the external crystal oscillator (-1 to disable for internal APLL source)
|
||||
#define ETH_POWER_PIN 16
|
||||
|
||||
// Type of the Ethernet PHY (LAN8720 or TLK110)
|
||||
#define ETH_TYPE ETH_PHY_LAN8720
|
||||
|
||||
// I²C-address of Ethernet PHY (0 or 1 for LAN8720, 31 for TLK110)
|
||||
#define ETH_ADDR 1
|
||||
|
||||
// Pin# of the I²C clock signal for the Ethernet PHY
|
||||
#define ETH_MDC_PIN 23
|
||||
|
||||
// Pin# of the I²C IO signal for the Ethernet PHY
|
||||
#define ETH_MDIO_PIN 18
|
||||
|
||||
#define NRST 5
|
||||
|
||||
#define MQTT_HOST IPAddress(192, 168, 1, 173)
|
||||
#define MQTT_PORT 1883
|
||||
|
||||
uint32_t lastMillis;
|
||||
uint64_t lastMicros;
|
||||
|
||||
static bool eth_connected = false;
|
||||
|
||||
TimerHandle_t ethReconnectTimer;
|
||||
|
||||
void WiFiEvent(WiFiEvent_t event)
|
||||
{
|
||||
#if ESP_IDF_VERSION_MAJOR > 3
|
||||
switch (event) {
|
||||
case ARDUINO_EVENT_ETH_START:
|
||||
Serial.println("ETH Started");
|
||||
// set eth hostname here
|
||||
ETH.setHostname("esp32-ethernet");
|
||||
break;
|
||||
case ARDUINO_EVENT_ETH_CONNECTED:
|
||||
Serial.println("ETH Connected");
|
||||
break;
|
||||
case ARDUINO_EVENT_ETH_GOT_IP:
|
||||
Serial.print("ETH MAC: ");
|
||||
Serial.print(ETH.macAddress());
|
||||
Serial.print(", IPv4: ");
|
||||
Serial.print(ETH.localIP());
|
||||
if (ETH.fullDuplex()) {
|
||||
Serial.print(", FULL_DUPLEX");
|
||||
}
|
||||
Serial.print(", ");
|
||||
Serial.print(ETH.linkSpeed());
|
||||
Serial.println("Mbps");
|
||||
eth_connected = true;
|
||||
connectToMqtt();
|
||||
break;
|
||||
case ARDUINO_EVENT_ETH_DISCONNECTED:
|
||||
Serial.println("ETH Disconnected");
|
||||
eth_connected = false;
|
||||
break;
|
||||
case ARDUINO_EVENT_ETH_STOP:
|
||||
Serial.println("ETH Stopped");
|
||||
eth_connected = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#elif
|
||||
switch (event) {
|
||||
case SYSTEM_EVENT_ETH_START:
|
||||
Serial.println("ETH Started");
|
||||
// set eth hostname here
|
||||
ETH.setHostname("esp32-ethernet");
|
||||
break;
|
||||
case SYSTEM_EVENT_ETH_CONNECTED:
|
||||
Serial.println("ETH Connected");
|
||||
break;
|
||||
case SYSTEM_EVENT_ETH_GOT_IP:
|
||||
Serial.print("ETH MAC: ");
|
||||
Serial.print(ETH.macAddress());
|
||||
Serial.print(", IPv4: ");
|
||||
Serial.print(ETH.localIP());
|
||||
if (ETH.fullDuplex()) {
|
||||
Serial.print(", FULL_DUPLEX");
|
||||
}
|
||||
Serial.print(", ");
|
||||
Serial.print(ETH.linkSpeed());
|
||||
Serial.println("Mbps");
|
||||
eth_connected = true;
|
||||
break;
|
||||
case SYSTEM_EVENT_ETH_DISCONNECTED:
|
||||
Serial.println("ETH Disconnected");
|
||||
eth_connected = false;
|
||||
break;
|
||||
case SYSTEM_EVENT_ETH_STOP:
|
||||
Serial.println("ETH Stopped");
|
||||
eth_connected = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void connectEth() {
|
||||
pinMode(NRST, OUTPUT);
|
||||
digitalWrite(NRST, 0);
|
||||
delay(200);
|
||||
digitalWrite(NRST, 1);
|
||||
delay(200);
|
||||
digitalWrite(NRST, 0);
|
||||
delay(200);
|
||||
digitalWrite(NRST, 1);
|
||||
delay(200);
|
||||
|
||||
ETH.begin(ETH_ADDR,
|
||||
ETH_POWER_PIN,
|
||||
ETH_MDC_PIN,
|
||||
ETH_MDIO_PIN,
|
||||
ETH_TYPE,
|
||||
ETH_CLK_MODE);
|
||||
}
|
||||
|
||||
void testClient(const char * host, uint16_t port)
|
||||
{
|
||||
Serial.print("\nconnecting to ");
|
||||
Serial.println(host);
|
||||
|
||||
WiFiClient client;
|
||||
if (!client.connect(host, port)) {
|
||||
Serial.println("connection failed");
|
||||
return;
|
||||
}
|
||||
client.printf("GET / HTTP/1.1\r\nHost: %s\r\n\r\n", host);
|
||||
while (client.connected() && !client.available());
|
||||
while (client.available()) {
|
||||
Serial.write(client.read());
|
||||
}
|
||||
|
||||
Serial.println("closing connection\n");
|
||||
client.stop();
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
WiFi.onEvent(WiFiEvent);
|
||||
|
||||
connectEth();
|
||||
|
||||
mqttReconnectTimer = xTimerCreate("mqttTimer", pdMS_TO_TICKS(2000), pdFALSE, (void*)0, reinterpret_cast<TimerCallbackFunction_t>(connectToMqtt));
|
||||
|
||||
mqttClient.onConnect(onMqttConnect);
|
||||
mqttClient.onDisconnect(onMqttDisconnect);
|
||||
mqttClient.onSubscribe(onMqttSubscribe);
|
||||
mqttClient.onUnsubscribe(onMqttUnsubscribe);
|
||||
//mqttClient.onMessage(onMqttMessage);
|
||||
mqttClient.onPublish(onMqttPublish);
|
||||
mqttClient.setServer(MQTT_HOST, MQTT_PORT);
|
||||
|
||||
pinMode(DATA_PIN, INPUT);
|
||||
|
||||
pinMode(DRY_CONT_PIN, OUTPUT);
|
||||
digitalWrite(DRY_CONT_PIN, 0);
|
||||
delay(2000);
|
||||
digitalWrite(DRY_CONT_PIN, 1);
|
||||
delay(2000);
|
||||
digitalWrite(DRY_CONT_PIN, 0);
|
||||
delay(2000);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (lastMicros < micros()) {
|
||||
data = digitalRead(DATA_PIN);
|
||||
updateStateMachine(data);
|
||||
|
||||
if (PRINT_RAW_SIGNAL_FLAG)
|
||||
printf("{}", data);
|
||||
|
||||
lastMillis = micros() + DATA_PERIOD;
|
||||
}
|
||||
|
||||
if (eth_connected) {
|
||||
if (lastMillis < millis()) {;
|
||||
lastMillis = millis() + 3000;
|
||||
}
|
||||
}
|
||||
}
|
100
src/stateMachine.cpp
Normal file
100
src/stateMachine.cpp
Normal file
@ -0,0 +1,100 @@
|
||||
#include "stateMachine.h"
|
||||
|
||||
void updateStateMachine(int data) {
|
||||
switch (currentState) {
|
||||
case NOT_CONNECTED:
|
||||
if (data == 0) {
|
||||
// Stay in the NOT_CONNECTED state
|
||||
} else if (data == 1) {
|
||||
currentState = CONNECTED;
|
||||
println("connected");
|
||||
}
|
||||
break;
|
||||
|
||||
case CONNECTED:
|
||||
if (data == 0) {
|
||||
countZeros++;
|
||||
if (countZeros >= NOT_CONNECTED_THRESHOLD) {
|
||||
currentState = NOT_CONNECTED;
|
||||
println("not connected");
|
||||
resetCounters();
|
||||
}
|
||||
} else if (data == 1) {
|
||||
if (countZeros >= INITIALIZING_CALL_THRESHOLD) {
|
||||
currentState = RECEIVING_DATA;
|
||||
println("receiving data");
|
||||
resetCounters();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case RECEIVING_DATA:
|
||||
if (data != previousData) {
|
||||
if (previousData == HIGH) {
|
||||
dataLength++;
|
||||
}
|
||||
signalDuration = 0;
|
||||
} else {
|
||||
signalDuration++;
|
||||
}
|
||||
previousData = data;
|
||||
if (data == 0) {
|
||||
countOnes = 0;
|
||||
countZeros++;
|
||||
if (countZeros >= DATA_RECEIVED_THESHOLD) {
|
||||
println("| data length: ", dataLength);
|
||||
println("| flat: ", dataLength/2);
|
||||
//sendDataToMQTT(dataLength/2);
|
||||
|
||||
currentState = DATA_RECEIVED;
|
||||
println("data received");
|
||||
resetCounters();
|
||||
}
|
||||
} else if (data == 1) {
|
||||
countZeros = 0;
|
||||
countOnes++;
|
||||
if (countOnes >= CONNECTED_THRESHOLD) {
|
||||
currentState = CONNECTED;
|
||||
println("connected");
|
||||
resetCounters();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case DATA_RECEIVED:
|
||||
if (data == 0) {
|
||||
countZeros++;
|
||||
if (countZeros >= CALL_ENDED_THRESHOLD) {
|
||||
currentState = CALL_ENDED;
|
||||
println("call ended");
|
||||
resetCounters();
|
||||
}
|
||||
} else if (data == 1) {
|
||||
countOnes++;
|
||||
if (countOnes >= CONNECTED_THRESHOLD) {
|
||||
currentState = CONNECTED;
|
||||
println("connected");
|
||||
resetCounters();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case CALL_ENDED:
|
||||
if (data == 0) {
|
||||
countZeros++;
|
||||
if (countZeros >= NOT_CONNECTED_THRESHOLD) {
|
||||
currentState = NOT_CONNECTED;
|
||||
println("not connected");
|
||||
resetCounters();
|
||||
}
|
||||
} else if (data == 1) {
|
||||
countOnes++;
|
||||
if (countOnes >= CONNECTED_THRESHOLD) {
|
||||
currentState = CONNECTED;
|
||||
println("connected");
|
||||
resetCounters();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
33
src/stateMachine.h
Normal file
33
src/stateMachine.h
Normal file
@ -0,0 +1,33 @@
|
||||
#ifndef STATE_MACHINE_H
|
||||
#define STATE_MACHINE_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "utils/print.cpp"
|
||||
|
||||
#define CONNECTED_THRESHOLD 50000
|
||||
#define NOT_CONNECTED_THRESHOLD 50000
|
||||
#define INITIALIZING_CALL_THRESHOLD 15000
|
||||
#define DATA_RECEIVED_THESHOLD 30000
|
||||
#define CALL_ENDED_THRESHOLD 10000
|
||||
|
||||
enum State {
|
||||
NOT_CONNECTED,
|
||||
CONNECTED,
|
||||
RECEIVING_DATA,
|
||||
DATA_RECEIVED,
|
||||
CALL_ENDED
|
||||
};
|
||||
|
||||
int data = 0;
|
||||
State currentState = NOT_CONNECTED;
|
||||
int countZeros = 0;
|
||||
int countOnes = 0;
|
||||
|
||||
int previousData = 0;
|
||||
int dataLength = 0;
|
||||
int signalDuration = 0;
|
||||
|
||||
void resetCounters();
|
||||
void updateStateMachine(int data);
|
||||
|
||||
#endif // STATE_MACHINE_H
|
77
src/utils/print.cpp
Normal file
77
src/utils/print.cpp
Normal file
@ -0,0 +1,77 @@
|
||||
#include <Arduino.h>
|
||||
#include "utils/print.h"
|
||||
|
||||
void print() {
|
||||
// Empty function to terminate recursion
|
||||
}
|
||||
|
||||
// Overloaded function to print a single value
|
||||
template <typename T>
|
||||
void print(T value) {
|
||||
Serial.print(value);
|
||||
}
|
||||
|
||||
// Recursive function to print multiple values
|
||||
template <typename T, typename... Args>
|
||||
void print(T value, Args... args) {
|
||||
Serial.print(value);
|
||||
print(args...); // Recursively call print for the remaining arguments
|
||||
}
|
||||
|
||||
// Function to print a newline
|
||||
void println() {
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
// Overloaded function to print a single value and a newline
|
||||
template <typename T>
|
||||
void println(T value) {
|
||||
Serial.println(value);
|
||||
}
|
||||
|
||||
// Recursive function to print multiple values and a newline
|
||||
template <typename T, typename... Args>
|
||||
void println(T value, Args... args) {
|
||||
Serial.print(value);
|
||||
println(args...); // Recursively call println for the remaining arguments
|
||||
}
|
||||
|
||||
// Convenience functions for easy usage
|
||||
template <typename... Args>
|
||||
void print(Args... args) {
|
||||
print(args...);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void println(Args... args) {
|
||||
println(args...);
|
||||
}
|
||||
|
||||
String fstring(const char* format) {
|
||||
String result = format;
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
String fstring(const char* format, Args... args) {
|
||||
String result = "";
|
||||
while (*format) {
|
||||
if (*format == '{' && *(format + 1) == '}' && sizeof...(args) > 0) {
|
||||
result += String(args...);
|
||||
format += 2; // Skip the "{}" in the format string
|
||||
} else {
|
||||
result += *format;
|
||||
format++;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void printf(const char* format) {
|
||||
Serial.print(fstring(format));
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void printf(const char* format, Args... args) {
|
||||
Serial.print(fstring(format, args...));
|
||||
}
|
44
src/utils/print.h
Normal file
44
src/utils/print.h
Normal file
@ -0,0 +1,44 @@
|
||||
#ifndef UTILS_PRINT_H
|
||||
#define UTILS_PRINT_H
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
void print();
|
||||
|
||||
// Overloaded function to print a single value
|
||||
template <typename T>
|
||||
void print(T value);
|
||||
|
||||
// Recursive function to print multiple values
|
||||
template <typename T, typename... Args>
|
||||
void print(T value, Args... args);
|
||||
|
||||
// Function to print a newline
|
||||
void println();
|
||||
|
||||
// Overloaded function to print a single value and a newline
|
||||
template <typename T>
|
||||
void println(T value);
|
||||
|
||||
// Recursive function to print multiple values and a newline
|
||||
template <typename T, typename... Args>
|
||||
void println(T value, Args... args);
|
||||
|
||||
// Convenience functions for easy usage
|
||||
template <typename... Args>
|
||||
void print(Args... args);
|
||||
|
||||
template <typename... Args>
|
||||
void println(Args... args);
|
||||
|
||||
String fstring(const char* format);
|
||||
|
||||
template <typename... Args>
|
||||
String fstring(const char* format, Args... args);
|
||||
|
||||
void printf(const char* format);
|
||||
|
||||
template <typename... Args>
|
||||
void printf(const char* format, Args... args);
|
||||
|
||||
#endif // UTILS_PRINT_H
|
Loading…
x
Reference in New Issue
Block a user