Add support for serial gateway to Rpi
This commit is contained in:
+5
-5
@@ -410,7 +410,7 @@
|
||||
#define MY_RF24_CE_PIN 4
|
||||
#elif defined(ARDUINO_ARCH_SAMD)
|
||||
#define MY_RF24_CE_PIN 27
|
||||
#elif defined(LINUX)
|
||||
#elif defined(__linux__)
|
||||
#define MY_RF24_CE_PIN 22
|
||||
#else
|
||||
#define MY_RF24_CE_PIN 9
|
||||
@@ -426,7 +426,7 @@
|
||||
#define MY_RF24_CS_PIN 15
|
||||
#elif defined(ARDUINO_ARCH_SAMD)
|
||||
#define MY_RF24_CS_PIN 3
|
||||
#elif defined(LINUX)
|
||||
#elif defined(__linux__)
|
||||
#define MY_RF24_CS_PIN 24
|
||||
#else
|
||||
#define MY_RF24_CS_PIN 10
|
||||
@@ -718,11 +718,11 @@
|
||||
***************************************/
|
||||
|
||||
/**
|
||||
* @def MY_LINUX_TTY_NAME
|
||||
* @def MY_LINUX_SERIAL_PORT
|
||||
* @brief Set the name of predictable tty
|
||||
*/
|
||||
#ifndef MY_LINUX_TTY_NAME
|
||||
#define MY_LINUX_TTY_NAME "/dev/ttyAMA0"
|
||||
#ifndef MY_LINUX_SERIAL_PORT
|
||||
#define MY_LINUX_SERIAL_PORT "/dev/ttyUSB0"
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
||||
+5
-3
@@ -69,7 +69,7 @@
|
||||
#include "core/MyHwATMega328.cpp"
|
||||
#elif defined(ARDUINO_ARCH_SAMD)
|
||||
#include "core/MyHwSAMD.cpp"
|
||||
#elif defined(LINUX)
|
||||
#elif defined(__linux__)
|
||||
// Remove PSTR macros from debug prints
|
||||
#undef PSTR
|
||||
#define PSTR(x) (x)
|
||||
@@ -284,7 +284,9 @@
|
||||
#if defined(MY_RF24_ENABLE_ENCRYPTION)
|
||||
#include "drivers/AES/AES.cpp"
|
||||
#endif
|
||||
#if !defined(LINUX)
|
||||
#if defined(__linux__)
|
||||
#include "drivers/RF24/RF24_Linux.cpp"
|
||||
#else
|
||||
#include "drivers/RF24/RF24.cpp"
|
||||
#endif
|
||||
#include "core/MyTransportNRF24.cpp"
|
||||
@@ -329,7 +331,7 @@
|
||||
#if !defined(MY_CORE_ONLY)
|
||||
#if defined(ARDUINO_ARCH_ESP8266)
|
||||
#include "core/MyMainESP8266.cpp"
|
||||
#elif defined(LINUX)
|
||||
#elif defined(__linux__)
|
||||
#include "core/MyMainLinux.cpp"
|
||||
#else
|
||||
#include "core/MyMainDefault.cpp"
|
||||
|
||||
@@ -35,15 +35,10 @@ MySensors options:
|
||||
--my-debug=[enable|disable]
|
||||
Enables or disables debugging.
|
||||
Default to enable.
|
||||
--my-gateway=[none|ethernet|mqtt]
|
||||
--my-config-file=<FILE> Config file path. [/etc/MySensorGateway.cfg]
|
||||
--my-gateway=[none|ethernet|serial|mqtt]
|
||||
Gateway type, set to none to disable gateway feature.
|
||||
Default to ethernet.
|
||||
--my-config-file=<FILE> Config file path. [/etc/MySensorGateway.cfg]
|
||||
--my-radio=[none|nrf24] Radio type, set to none to disable radio feature.
|
||||
Default to rf24.
|
||||
--my-rf24-channel=<0-125> RF channel for the sensor net, 0-125.
|
||||
--my-rf24-pa-level=[RF24_PA_MAX|RF24_PA_LOW]
|
||||
RF24 PA level.
|
||||
--my-controller-url-address=<URL>
|
||||
Controller or MQTT broker url.
|
||||
--my-controller-ip-address=<IP>
|
||||
@@ -51,11 +46,18 @@ MySensors options:
|
||||
Use commas instead of points. Example: 127,0,0,1
|
||||
--my-port=<PORT> The port to keep open on gateway mode.
|
||||
If gateway is set to mqtt, it sets the broker port.
|
||||
--my-serial-port=<PORT> Serial port. [/dev/ttyUSB0]
|
||||
--my-serial-baudrate=<BAUD> Serial baud rate. [115200]
|
||||
--my-mqtt-client-id=<ID> MQTT client id.
|
||||
--my-mqtt-publish-topic-prefix=<PREFIX>
|
||||
MQTT publish topic prefix.
|
||||
--my-mqtt-subscribe-topic-prefix=<PREFIX>
|
||||
MQTT subscribe topic prefix.
|
||||
--my-radio=[none|nrf24] Radio type, set to none to disable radio feature.
|
||||
Default to rf24.
|
||||
--my-rf24-channel=<0-125> RF channel for the sensor net, 0-125.
|
||||
--my-rf24-pa-level=[RF24_PA_MAX|RF24_PA_LOW]
|
||||
RF24 PA level.
|
||||
--my-rf24-irq-pin=<PIN> Pin number connected to nRF24L01 IRQ pin.
|
||||
For RaspberryPi use BCM numbering.
|
||||
--my-rx-message-buffer-size=<SIZE>
|
||||
@@ -251,6 +253,12 @@ for opt do
|
||||
--my-radio=*)
|
||||
radio_type=${optarg}
|
||||
;;
|
||||
--my-serial-port=*)
|
||||
CXXFLAGS="-DMY_LINUX_SERIAL_PORT=\\\"${optarg}\\\" $CXXFLAGS"
|
||||
;;
|
||||
--my-serial-baudrate=*)
|
||||
CXXFLAGS="-DMY_BAUD_RATE=${optarg} $CXXFLAGS"
|
||||
;;
|
||||
--my-rf24-channel=*)
|
||||
CXXFLAGS="-DMY_RF24_CHANNEL=${optarg} $CXXFLAGS"
|
||||
;;
|
||||
@@ -305,7 +313,7 @@ if [ -z "${CPUFLAGS}" ]; then
|
||||
CPUFLAGS=$(gcc_cpu_flags $SOC)
|
||||
fi
|
||||
|
||||
CXXFLAGS="$CPUFLAGS -Ofast -g -Wall -Wextra -DLINUX $CXXFLAGS"
|
||||
CXXFLAGS="$CPUFLAGS -Ofast -g -Wall -Wextra $CXXFLAGS"
|
||||
|
||||
if [[ $TYPE == "RPi2" || $TYPE == "RPi3" || $REV == "0010" ]]; then
|
||||
CXXFLAGS+="-D__RPI_BPLUS"
|
||||
@@ -317,6 +325,8 @@ fi
|
||||
|
||||
if [[ ${gateway_type} == "ethernet" ]]; then
|
||||
CXXFLAGS="-DMY_GATEWAY_LINUX $CXXFLAGS"
|
||||
elif [[ ${gateway_type} == "serial" ]]; then
|
||||
CXXFLAGS="-DMY_GATEWAY_SERIAL $CXXFLAGS"
|
||||
elif [[ ${gateway_type} == "mqtt" ]]; then
|
||||
LDFLAGS="-lmosquitto $LDFLAGS"
|
||||
CXXFLAGS="-DMY_GATEWAY_LINUX -DMY_GATEWAY_MQTT_CLIENT $CXXFLAGS"
|
||||
|
||||
@@ -30,12 +30,12 @@ static const size_t _length = 1024; // ATMega328 has 1024 bytes
|
||||
static uint8_t _config[_length];
|
||||
|
||||
bool CheckConfigFile() {
|
||||
struct stat fileInfo;
|
||||
struct stat fileInfo;
|
||||
|
||||
if (stat(CONFIG_FILE, &fileInfo) != 0) {
|
||||
//File does not exist. Create it.
|
||||
debug("Config file %s does not exist, creating new config file.\n", CONFIG_FILE);
|
||||
ofstream myFile(CONFIG_FILE, ios::out | ios::binary);
|
||||
std::ofstream myFile(CONFIG_FILE, std::ios::out | std::ios::binary);
|
||||
if (!myFile) {
|
||||
debug("Unable to create config file %s.\n", CONFIG_FILE);
|
||||
return false;
|
||||
@@ -47,7 +47,7 @@ bool CheckConfigFile() {
|
||||
return false;
|
||||
} else {
|
||||
//Read config into local memory.
|
||||
ifstream myFile(CONFIG_FILE, ios::in | ios::binary);
|
||||
std::ifstream myFile(CONFIG_FILE, std::ios::in | std::ios::binary);
|
||||
if (!myFile) {
|
||||
debug("Unable to open config to file %s for reading.\n", CONFIG_FILE);
|
||||
return false;
|
||||
@@ -68,6 +68,10 @@ void hwInit()
|
||||
if (!CheckConfigFile()) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#ifdef MY_GATEWAY_SERIAL
|
||||
MY_SERIALDEVICE.begin(MY_BAUD_RATE);
|
||||
#endif
|
||||
}
|
||||
|
||||
void hwReadConfigBlock(void* buf, void* addr, size_t length)
|
||||
@@ -86,7 +90,7 @@ void hwWriteConfigBlock(void* buf, void* addr, size_t length)
|
||||
if (length && offs + length <= _length) {
|
||||
memcpy(_config+offs, buf, length);
|
||||
|
||||
ofstream myFile(CONFIG_FILE, ios::out | ios::binary);
|
||||
std::ofstream myFile(CONFIG_FILE, std::ios::out | std::ios::binary);
|
||||
if (!myFile) {
|
||||
debug("Unable to write config to file %s.\n", CONFIG_FILE);
|
||||
return;
|
||||
|
||||
@@ -20,10 +20,12 @@
|
||||
#ifndef MyHwLinuxGeneric_h
|
||||
#define MyHwLinuxGeneric_h
|
||||
|
||||
#include "MyHw.h"
|
||||
#include <cstdlib>
|
||||
#include <pthread.h>
|
||||
#include "MyHw.h"
|
||||
#include "SerialPort.h"
|
||||
|
||||
SerialPort Serial = SerialPort(MY_LINUX_SERIAL_PORT);
|
||||
#define MY_SERIALDEVICE Serial
|
||||
|
||||
// Define these as macros (do nothing)
|
||||
@@ -35,8 +37,8 @@
|
||||
void hwInit();
|
||||
void hwReadConfigBlock(void* buf, void* adr, size_t length);
|
||||
void hwWriteConfigBlock(void* buf, void* adr, size_t length);
|
||||
void hwWriteConfig(int adr, uint8_t value);
|
||||
uint8_t hwReadConfig(int adr);
|
||||
void hwWriteConfig(int adr, uint8_t value);
|
||||
|
||||
#ifdef MY_RF24_IRQ_PIN
|
||||
static pthread_mutex_t hw_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
@@ -51,7 +51,7 @@ void _process() {
|
||||
transportProcess();
|
||||
#endif
|
||||
|
||||
#if defined(LINUX)
|
||||
#if defined(__linux__)
|
||||
// To avoid high cpu usage
|
||||
usleep(10000); // 10ms
|
||||
#endif
|
||||
@@ -65,7 +65,7 @@ void _infiniteLoop() {
|
||||
#if defined (MY_LEDS_BLINKING_FEATURE)
|
||||
ledsProcess();
|
||||
#endif
|
||||
#if defined(LINUX)
|
||||
#if defined(__linux__)
|
||||
exit(1);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
#include "MyConfig.h"
|
||||
#include "MyTransport.h"
|
||||
|
||||
#ifdef LINUX_ARCH_RASPBERRYPI
|
||||
#include "drivers/RF24/RF24_Linux.cpp"
|
||||
#ifdef __linux__
|
||||
#include "drivers/RF24/RF24_Linux.h"
|
||||
#else
|
||||
#include "drivers/RF24/RF24.h"
|
||||
#endif
|
||||
|
||||
+24
-27
@@ -1,18 +1,17 @@
|
||||
#ifndef Arduino_h
|
||||
#define Arduino_h
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std;
|
||||
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void yield(void);
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include "stdlib_noniso.h"
|
||||
|
||||
#define PI 3.1415926535897932384626433832795
|
||||
#define HALF_PI 1.5707963267948966192313216916398
|
||||
@@ -21,17 +20,11 @@ void yield(void);
|
||||
#define RAD_TO_DEG 57.295779513082320876798154814105
|
||||
#define EULER 2.718281828459045235360287471352
|
||||
|
||||
#ifndef __cplusplus
|
||||
#define min(a,b) ((a)<(b)?(a):(b))
|
||||
#define max(a,b) ((a)>(b)?(a):(b))
|
||||
#define abs(x) ((x)>0?(x):-(x))
|
||||
#define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))
|
||||
#endif
|
||||
|
||||
#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))
|
||||
#define radians(deg) ((deg)*DEG_TO_RAD)
|
||||
#define degrees(rad) ((rad)*RAD_TO_DEG)
|
||||
#define sq(x) ((x)*(x))
|
||||
#define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))
|
||||
|
||||
#define lowByte(w) ((uint8_t) ((w) & 0xff))
|
||||
#define highByte(w) ((uint8_t) ((w) >> 8))
|
||||
@@ -43,19 +36,23 @@ void yield(void);
|
||||
|
||||
#define bit(b) (1UL << (b))
|
||||
|
||||
#define GET_MACRO(_0, _1, _2, NAME, ...) NAME
|
||||
#define random(...) GET_MACRO(_0, ##__VA_ARGS__, randMinMax, randMax, rand)(__VA_ARGS__)
|
||||
|
||||
using std::string;
|
||||
using std::min;
|
||||
using std::max;
|
||||
using std::abs;
|
||||
|
||||
typedef bool boolean;
|
||||
typedef uint8_t byte;
|
||||
typedef string String;
|
||||
|
||||
char *itoa(int value, char* result, int base);
|
||||
char *ltoa(long value, char* result, int base);
|
||||
char *ultoa(long num, char *str, int radix);
|
||||
char *utoa(int num, char *str, int radix);
|
||||
char *dtostrf(float f, int width, int decimals, char *result);
|
||||
void yield(void);
|
||||
unsigned long millis(void);
|
||||
void delay(unsigned int millis);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
void randomSeed(unsigned long seed);
|
||||
long randMax(long howbig);
|
||||
long randMinMax(long howsmall, long howbig);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#ifndef client_h
|
||||
#define client_h
|
||||
|
||||
#include "Stream.h"
|
||||
#include "IPAddress.h"
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
class EthernetClient : public Client {
|
||||
|
||||
private:
|
||||
int _sock;
|
||||
int _sock; //!< @brief Network socket.
|
||||
|
||||
public:
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,238 @@
|
||||
/*
|
||||
Print.cpp - Base class that provides print() and println()
|
||||
Copyright (c) 2008 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
|
||||
|
||||
Modified 23 November 2006 by David A. Mellis
|
||||
Modified December 2014 by Ivan Grokhotkov
|
||||
Modified May 2015 by Michael C. Miller - esp8266 progmem support
|
||||
Modified August 2016 by Marcelo Aquino <marceloaqno@gmail.org> for MySensors use
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <cmath>
|
||||
#include "Print.h"
|
||||
|
||||
// Public Methods //////////////////////////////////////////////////////////////
|
||||
|
||||
size_t Print::write(const uint8_t *buffer, size_t size) {
|
||||
size_t n = 0;
|
||||
while(size--) {
|
||||
n += write(*buffer++);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::printf(const char *format, ...) {
|
||||
va_list arg;
|
||||
va_start(arg, format);
|
||||
char temp[64];
|
||||
char* buffer = temp;
|
||||
size_t len = vsnprintf(temp, sizeof(temp), format, arg);
|
||||
va_end(arg);
|
||||
if (len > sizeof(temp) - 1) {
|
||||
buffer = new char[len + 1];
|
||||
if (!buffer) {
|
||||
return 0;
|
||||
}
|
||||
va_start(arg, format);
|
||||
vsnprintf(buffer, len + 1, format, arg);
|
||||
va_end(arg);
|
||||
}
|
||||
len = write((const uint8_t*) buffer, len);
|
||||
if (buffer != temp) {
|
||||
delete[] buffer;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
size_t Print::print(const std::string &s) {
|
||||
return write(s.c_str(), s.length());
|
||||
}
|
||||
|
||||
size_t Print::print(const char str[]) {
|
||||
return write(str);
|
||||
}
|
||||
|
||||
size_t Print::print(char c) {
|
||||
return write(c);
|
||||
}
|
||||
|
||||
size_t Print::print(unsigned char b, int base) {
|
||||
return print((unsigned long) b, base);
|
||||
}
|
||||
|
||||
size_t Print::print(int n, int base) {
|
||||
return print((long) n, base);
|
||||
}
|
||||
|
||||
size_t Print::print(unsigned int n, int base) {
|
||||
return print((unsigned long) n, base);
|
||||
}
|
||||
|
||||
size_t Print::print(long n, int base) {
|
||||
if(base == 0) {
|
||||
return write(n);
|
||||
} else if(base == 10) {
|
||||
if(n < 0) {
|
||||
int t = print('-');
|
||||
n = -n;
|
||||
return printNumber(n, 10) + t;
|
||||
}
|
||||
return printNumber(n, 10);
|
||||
} else {
|
||||
return printNumber(n, base);
|
||||
}
|
||||
}
|
||||
|
||||
size_t Print::print(unsigned long n, int base) {
|
||||
if(base == 0)
|
||||
return write(n);
|
||||
else
|
||||
return printNumber(n, base);
|
||||
}
|
||||
|
||||
size_t Print::print(double n, int digits) {
|
||||
return printFloat(n, digits);
|
||||
}
|
||||
|
||||
size_t Print::println(void) {
|
||||
return print("\r\n");
|
||||
}
|
||||
|
||||
size_t Print::println(const std::string &s) {
|
||||
size_t n = print(s);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(const char c[]) {
|
||||
size_t n = print(c);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(char c) {
|
||||
size_t n = print(c);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(unsigned char b, int base) {
|
||||
size_t n = print(b, base);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(int num, int base) {
|
||||
size_t n = print(num, base);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(unsigned int num, int base) {
|
||||
size_t n = print(num, base);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(long num, int base) {
|
||||
size_t n = print(num, base);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(unsigned long num, int base) {
|
||||
size_t n = print(num, base);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(double num, int digits) {
|
||||
size_t n = print(num, digits);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
// Private Methods /////////////////////////////////////////////////////////////
|
||||
|
||||
size_t Print::printNumber(unsigned long n, uint8_t base) {
|
||||
char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte.
|
||||
char *str = &buf[sizeof(buf) - 1];
|
||||
|
||||
*str = '\0';
|
||||
|
||||
// prevent crash if called with base == 1
|
||||
if(base < 2)
|
||||
base = 10;
|
||||
|
||||
do {
|
||||
unsigned long m = n;
|
||||
n /= base;
|
||||
char c = m - base * n;
|
||||
*--str = c < 10 ? c + '0' : c + 'A' - 10;
|
||||
} while(n);
|
||||
|
||||
return write(str);
|
||||
}
|
||||
|
||||
size_t Print::printFloat(double number, uint8_t digits) {
|
||||
size_t n = 0;
|
||||
|
||||
if(std::isnan(number))
|
||||
return print("nan");
|
||||
if(std::isinf(number))
|
||||
return print("inf");
|
||||
if(number > 4294967040.0)
|
||||
return print("ovf"); // constant determined empirically
|
||||
if(number < -4294967040.0)
|
||||
return print("ovf"); // constant determined empirically
|
||||
|
||||
// Handle negative numbers
|
||||
if(number < 0.0) {
|
||||
n += print('-');
|
||||
number = -number;
|
||||
}
|
||||
|
||||
// Round correctly so that print(1.999, 2) prints as "2.00"
|
||||
double rounding = 0.5;
|
||||
for(uint8_t i = 0; i < digits; ++i)
|
||||
rounding /= 10.0;
|
||||
|
||||
number += rounding;
|
||||
|
||||
// Extract the integer part of the number and print it
|
||||
unsigned long int_part = (unsigned long) number;
|
||||
double remainder = number - (double) int_part;
|
||||
n += print(int_part);
|
||||
|
||||
// Print the decimal point, but only if there are digits beyond
|
||||
if(digits > 0) {
|
||||
n += print(".");
|
||||
}
|
||||
|
||||
// Extract digits from the remainder one at a time
|
||||
while(digits-- > 0) {
|
||||
remainder *= 10.0;
|
||||
int toPrint = int(remainder);
|
||||
n += print(toPrint);
|
||||
remainder -= toPrint;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
Print.h - Base class that provides print() and println()
|
||||
Copyright (c) 2008 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
|
||||
|
||||
Modified August 2016 by Marcelo Aquino <marceloaqno@gmail.org> for MySensors use
|
||||
*/
|
||||
|
||||
#ifndef Print_h
|
||||
#define Print_h
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <string.h>
|
||||
|
||||
#if !DOXYGEN
|
||||
#define DEC 10
|
||||
#define HEX 16
|
||||
#define OCT 8
|
||||
#define BIN 2
|
||||
|
||||
class Print {
|
||||
private:
|
||||
size_t printNumber(unsigned long n, uint8_t base);
|
||||
size_t printFloat(double number, uint8_t digits);
|
||||
|
||||
public:
|
||||
virtual size_t write(uint8_t) = 0;
|
||||
size_t write(const char *str) {
|
||||
if (str == NULL)
|
||||
return 0;
|
||||
return write((const uint8_t *) str, strlen(str));
|
||||
}
|
||||
virtual size_t write(const uint8_t *buffer, size_t size);
|
||||
size_t write(const char *buffer, size_t size) {
|
||||
return write((const uint8_t *) buffer, size);
|
||||
}
|
||||
|
||||
size_t printf(const char * format, ...) __attribute__ ((format (printf, 2, 3)));
|
||||
size_t print(const std::string &);
|
||||
size_t print(const char[]);
|
||||
size_t print(char);
|
||||
size_t print(unsigned char, int = DEC);
|
||||
size_t print(int, int = DEC);
|
||||
size_t print(unsigned int, int = DEC);
|
||||
size_t print(long, int = DEC);
|
||||
size_t print(unsigned long, int = DEC);
|
||||
size_t print(double, int = 2);
|
||||
|
||||
size_t println(const std::string &s);
|
||||
size_t println(const char[]);
|
||||
size_t println(char);
|
||||
size_t println(unsigned char, int = DEC);
|
||||
size_t println(int, int = DEC);
|
||||
size_t println(unsigned int, int = DEC);
|
||||
size_t println(long, int = DEC);
|
||||
size_t println(unsigned long, int = DEC);
|
||||
size_t println(double, int = 2);
|
||||
size_t println(void);
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Marcelo Aquino <marceloaqno@gmail.org>
|
||||
* Copyright (C) 2016 Marcelo Aquino
|
||||
* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <limits.h>
|
||||
#include <unistd.h>
|
||||
#include <termios.h>
|
||||
#include "SerialPort.h"
|
||||
|
||||
#define SERIAL_PORT "/dev/ttyAMA0"
|
||||
|
||||
SerialPort::SerialPort()
|
||||
{
|
||||
SerialPort(SERIAL_PORT);
|
||||
}
|
||||
|
||||
SerialPort::SerialPort(const char *port) : serialPort(std::string(port))
|
||||
{}
|
||||
|
||||
void SerialPort::begin(int bauds)
|
||||
{
|
||||
speed_t speed;
|
||||
struct termios options;
|
||||
|
||||
if ((sd = open(serialPort.c_str(), O_RDWR | O_NOCTTY | O_NDELAY)) == -1) {
|
||||
fprintf(stderr, "Unable to open the serial port %s - \n", serialPort.c_str());
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// nonblocking mode
|
||||
fcntl(sd, F_SETFL, FNDELAY);
|
||||
|
||||
switch (bauds) {
|
||||
case 50: speed = B50 ; break ;
|
||||
case 75: speed = B75 ; break ;
|
||||
case 110: speed = B110 ; break ;
|
||||
case 134: speed = B134 ; break ;
|
||||
case 150: speed = B150 ; break ;
|
||||
case 200: speed = B200 ; break ;
|
||||
case 300: speed = B300 ; break ;
|
||||
case 600: speed = B600 ; break ;
|
||||
case 1200: speed = B1200 ; break ;
|
||||
case 1800: speed = B1800 ; break ;
|
||||
case 2400: speed = B2400 ; break ;
|
||||
case 9600: speed = B9600 ; break ;
|
||||
case 19200: speed = B19200 ; break ;
|
||||
case 38400: speed = B38400 ; break ;
|
||||
case 57600: speed = B57600 ; break ;
|
||||
case 115200: speed = B115200 ; break ;
|
||||
default: speed = B115200 ; break ;
|
||||
}
|
||||
|
||||
// Get the current options of the port
|
||||
if (tcgetattr(sd, &options) < 0) {
|
||||
perror("Couldn't get term attributes");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// make raw
|
||||
cfmakeraw(&options);
|
||||
|
||||
// Set the baud rate
|
||||
cfsetispeed(&options, speed);
|
||||
cfsetospeed(&options, speed);
|
||||
|
||||
// turn on READ & ignore ctrl lines
|
||||
options.c_cflag |= (CLOCAL | CREAD);
|
||||
// 8N1
|
||||
options.c_cflag &= ~CSTOPB;
|
||||
|
||||
options.c_lflag &= ~ECHOE;
|
||||
|
||||
// Timer unused
|
||||
options.c_cc[VTIME]=0;
|
||||
// At least on character before satisfy reading
|
||||
options.c_cc[VMIN]=0;
|
||||
|
||||
// Set parameters
|
||||
if (tcsetattr(sd, TCSANOW, &options) < 0) {
|
||||
perror("Couldn't set term attributes");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// flush
|
||||
if (tcflush(sd, TCIOFLUSH) < 0) {
|
||||
perror("Couldn't flush serial");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
usleep(10000);
|
||||
}
|
||||
|
||||
int SerialPort::available()
|
||||
{
|
||||
int nbytes = 0;
|
||||
|
||||
if (ioctl(sd, FIONREAD, &nbytes) < 0) {
|
||||
fprintf(stderr, "Failed to get byte count on serial.\n");
|
||||
exit(-1);
|
||||
}
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
int SerialPort::read()
|
||||
{
|
||||
unsigned char c;
|
||||
|
||||
::read(sd, &c, 1);
|
||||
return c;
|
||||
}
|
||||
|
||||
size_t SerialPort::write(uint8_t b)
|
||||
{
|
||||
return ::write(sd, &b, 1);
|
||||
}
|
||||
|
||||
size_t SerialPort::write(const uint8_t *buffer, size_t size)
|
||||
{
|
||||
return ::write(sd, buffer, size);
|
||||
}
|
||||
|
||||
int SerialPort::peek()
|
||||
{
|
||||
FILE * f = fdopen(sd, "r+");
|
||||
int c = getc(f);
|
||||
if (c == EOF) return -1;
|
||||
ungetc(c, f);
|
||||
return c;
|
||||
}
|
||||
|
||||
void SerialPort::flush()
|
||||
{
|
||||
tcflush(sd, TCIFLUSH);
|
||||
}
|
||||
|
||||
void SerialPort::end()
|
||||
{
|
||||
close(sd);
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Marcelo Aquino <marceloaqno@gmail.org>
|
||||
* Copyright (C) 2016 Marcelo Aquino
|
||||
* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef SerialPort_h
|
||||
#define SerialPort_h
|
||||
|
||||
#include <string>
|
||||
#include "Stream.h"
|
||||
|
||||
/**
|
||||
* SerialPort Class
|
||||
* Class that provides the functionality of arduino Serial library
|
||||
*/
|
||||
class SerialPort : public Stream {
|
||||
|
||||
private:
|
||||
int sd; //!< @brief file descriptor number.
|
||||
std::string serialPort; //!< @brief tty name.
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief SerialPort constructor.
|
||||
*/
|
||||
SerialPort();
|
||||
/**
|
||||
* @brief SerialPort constructor.
|
||||
*/
|
||||
SerialPort(const char *port);
|
||||
/**
|
||||
* @brief Sets the data rate in bits per second (baud) for serial data transmission.
|
||||
*
|
||||
* @param serialSpeed serial port speed.
|
||||
*/
|
||||
void begin(int serialSpeed);
|
||||
/**
|
||||
* @brief Get the number of bytes available.
|
||||
*
|
||||
* Get the numberof bytes (characters) available for reading from
|
||||
* the serial port.
|
||||
*
|
||||
* @return number of bytes avalable to read.
|
||||
*/
|
||||
int available();
|
||||
/**
|
||||
* @brief Reads 1 byte of incoming serial data.
|
||||
*
|
||||
* @return first byte of incoming serial data available.
|
||||
*/
|
||||
int read();
|
||||
/**
|
||||
* @brief Writes a single byte to the serial port.
|
||||
*
|
||||
* @param b byte to write.
|
||||
* @return number of bytes written.
|
||||
*/
|
||||
size_t write(uint8_t b);
|
||||
/**
|
||||
* @brief Writes binary data to the serial port.
|
||||
*
|
||||
* @param buffer to write.
|
||||
* @param size of the buffer.
|
||||
* @return number of bytes written.
|
||||
*/
|
||||
size_t write(const uint8_t *buffer, size_t size);
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* Returns the next byte (character) of incoming serial data without removing it from
|
||||
* the internal serial buffer.
|
||||
*
|
||||
* @return -1 if no data else character in the buffer.
|
||||
*/
|
||||
int peek();
|
||||
/**
|
||||
* @brief Remove any data remaining on the serial buffer.
|
||||
*/
|
||||
void flush();
|
||||
/**
|
||||
* @brief Disables serial communication.
|
||||
*/
|
||||
void end();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -20,8 +20,10 @@
|
||||
#ifndef server_h
|
||||
#define server_h
|
||||
|
||||
#include "Print.h"
|
||||
|
||||
#if !DOXYGEN
|
||||
class Server {
|
||||
class Server : public Print {
|
||||
public:
|
||||
virtual void begin() =0;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,258 @@
|
||||
/*
|
||||
Stream.cpp - adds parsing methods to Stream class
|
||||
Copyright (c) 2008 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
|
||||
|
||||
Created July 2011
|
||||
parsing functions based on TextFinder library by Michael Margolis
|
||||
Modified August 2016 by Marcelo Aquino <marceloaqno@gmail.org> for MySensors use
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <Stream.h>
|
||||
|
||||
#define PARSE_TIMEOUT 1000 // default number of milli-seconds to wait
|
||||
#define NO_SKIP_CHAR 1 // a magic char not found in a valid ASCII numeric field
|
||||
|
||||
// private method to read stream with timeout
|
||||
int Stream::timedRead() {
|
||||
int c;
|
||||
_startMillis = millis();
|
||||
do {
|
||||
c = read();
|
||||
if(c >= 0)
|
||||
return c;
|
||||
yield();
|
||||
} while(millis() - _startMillis < _timeout);
|
||||
return -1; // -1 indicates timeout
|
||||
}
|
||||
|
||||
// private method to peek stream with timeout
|
||||
int Stream::timedPeek() {
|
||||
int c;
|
||||
_startMillis = millis();
|
||||
do {
|
||||
c = peek();
|
||||
if(c >= 0)
|
||||
return c;
|
||||
yield();
|
||||
} while(millis() - _startMillis < _timeout);
|
||||
return -1; // -1 indicates timeout
|
||||
}
|
||||
|
||||
// returns peek of the next digit in the stream or -1 if timeout
|
||||
// discards non-numeric characters
|
||||
int Stream::peekNextDigit() {
|
||||
int c;
|
||||
while(1) {
|
||||
c = timedPeek();
|
||||
if(c < 0)
|
||||
return c; // timeout
|
||||
if(c == '-')
|
||||
return c;
|
||||
if(c >= '0' && c <= '9')
|
||||
return c;
|
||||
read(); // discard non-numeric
|
||||
}
|
||||
}
|
||||
|
||||
// Public Methods
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
void Stream::setTimeout(unsigned long timeout) // sets the maximum number of milliseconds to wait
|
||||
{
|
||||
_timeout = timeout;
|
||||
}
|
||||
|
||||
// find returns true if the target string is found
|
||||
bool Stream::find(const char *target) {
|
||||
return findUntil(target, (char*) "");
|
||||
}
|
||||
|
||||
// reads data from the stream until the target string of given length is found
|
||||
// returns true if target string is found, false if timed out
|
||||
bool Stream::find(const char *target, size_t length) {
|
||||
return findUntil(target, length, NULL, 0);
|
||||
}
|
||||
|
||||
// as find but search ends if the terminator string is found
|
||||
bool Stream::findUntil(const char *target, const char *terminator) {
|
||||
return findUntil(target, strlen(target), terminator, strlen(terminator));
|
||||
}
|
||||
|
||||
// reads data from the stream until the target string of the given length is found
|
||||
// search terminated if the terminator string is found
|
||||
// returns true if target string is found, false if terminated or timed out
|
||||
bool Stream::findUntil(const char *target, size_t targetLen, const char *terminator, size_t termLen) {
|
||||
size_t index = 0; // maximum target string length is 64k bytes!
|
||||
size_t termIndex = 0;
|
||||
int c;
|
||||
|
||||
if(*target == 0)
|
||||
return true; // return true if target is a null string
|
||||
while((c = timedRead()) > 0) {
|
||||
|
||||
if(c != target[index])
|
||||
index = 0; // reset index if any char does not match
|
||||
|
||||
if(c == target[index]) {
|
||||
//////Serial.print("found "); Serial.write(c); Serial.print("index now"); Serial.println(index+1);
|
||||
if(++index >= targetLen) { // return true if all chars in the target match
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if(termLen > 0 && c == terminator[termIndex]) {
|
||||
if(++termIndex >= termLen)
|
||||
return false; // return false if terminate string found before target string
|
||||
} else
|
||||
termIndex = 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// returns the first valid (long) integer value from the current position.
|
||||
// initial characters that are not digits (or the minus sign) are skipped
|
||||
// function is terminated by the first character that is not a digit.
|
||||
long Stream::parseInt() {
|
||||
return parseInt(NO_SKIP_CHAR); // terminate on first non-digit character (or timeout)
|
||||
}
|
||||
|
||||
// as above but a given skipChar is ignored
|
||||
// this allows format characters (typically commas) in values to be ignored
|
||||
long Stream::parseInt(char skipChar) {
|
||||
boolean isNegative = false;
|
||||
long value = 0;
|
||||
int c;
|
||||
|
||||
c = peekNextDigit();
|
||||
// ignore non numeric leading characters
|
||||
if(c < 0)
|
||||
return 0; // zero returned if timeout
|
||||
|
||||
do {
|
||||
if(c == skipChar)
|
||||
; // ignore this charactor
|
||||
else if(c == '-')
|
||||
isNegative = true;
|
||||
else if(c >= '0' && c <= '9') // is c a digit?
|
||||
value = value * 10 + c - '0';
|
||||
read(); // consume the character we got with peek
|
||||
c = timedPeek();
|
||||
} while((c >= '0' && c <= '9') || c == skipChar);
|
||||
|
||||
if(isNegative)
|
||||
value = -value;
|
||||
return value;
|
||||
}
|
||||
|
||||
// as parseInt but returns a floating point value
|
||||
float Stream::parseFloat() {
|
||||
return parseFloat(NO_SKIP_CHAR);
|
||||
}
|
||||
|
||||
// as above but the given skipChar is ignored
|
||||
// this allows format characters (typically commas) in values to be ignored
|
||||
float Stream::parseFloat(char skipChar) {
|
||||
boolean isNegative = false;
|
||||
boolean isFraction = false;
|
||||
long value = 0;
|
||||
int c;
|
||||
float fraction = 1.0;
|
||||
|
||||
c = peekNextDigit();
|
||||
// ignore non numeric leading characters
|
||||
if(c < 0)
|
||||
return 0; // zero returned if timeout
|
||||
|
||||
do {
|
||||
if(c == skipChar)
|
||||
; // ignore
|
||||
else if(c == '-')
|
||||
isNegative = true;
|
||||
else if(c == '.')
|
||||
isFraction = true;
|
||||
else if(c >= '0' && c <= '9') { // is c a digit?
|
||||
value = value * 10 + c - '0';
|
||||
if(isFraction)
|
||||
fraction *= 0.1;
|
||||
}
|
||||
read(); // consume the character we got with peek
|
||||
c = timedPeek();
|
||||
} while((c >= '0' && c <= '9') || c == '.' || c == skipChar);
|
||||
|
||||
if(isNegative)
|
||||
value = -value;
|
||||
if(isFraction)
|
||||
return value * fraction;
|
||||
else
|
||||
return value;
|
||||
}
|
||||
|
||||
// read characters from stream into buffer
|
||||
// terminates if length characters have been read, or timeout (see setTimeout)
|
||||
// returns the number of characters placed in the buffer
|
||||
// the buffer is NOT null terminated.
|
||||
//
|
||||
size_t Stream::readBytes(char *buffer, size_t length) {
|
||||
size_t count = 0;
|
||||
while(count < length) {
|
||||
int c = timedRead();
|
||||
if(c < 0)
|
||||
break;
|
||||
*buffer++ = (char) c;
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
// as readBytes with terminator character
|
||||
// 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)
|
||||
|
||||
size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length) {
|
||||
if(length < 1)
|
||||
return 0;
|
||||
size_t index = 0;
|
||||
while(index < length) {
|
||||
int c = timedRead();
|
||||
if(c < 0 || c == terminator)
|
||||
break;
|
||||
*buffer++ = (char) c;
|
||||
index++;
|
||||
}
|
||||
return index; // return number of characters, not including null terminator
|
||||
}
|
||||
|
||||
std::string Stream::readString() {
|
||||
std::string ret;
|
||||
int c = timedRead();
|
||||
while(c >= 0) {
|
||||
ret += (char) c;
|
||||
c = timedRead();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string Stream::readStringUntil(char terminator) {
|
||||
std::string ret;
|
||||
int c = timedRead();
|
||||
while(c >= 0 && c != terminator) {
|
||||
ret += (char) c;
|
||||
c = timedRead();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
+112
-9
@@ -1,16 +1,119 @@
|
||||
/*
|
||||
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
|
||||
Modified August 2016 by Marcelo Aquino <marceloaqno@gmail.org> for MySensors use
|
||||
*/
|
||||
|
||||
#ifndef Stream_h
|
||||
#define Stream_h
|
||||
|
||||
#if !DOXYGEN
|
||||
class Stream {
|
||||
public:
|
||||
virtual size_t write(uint8_t) = 0;
|
||||
virtual size_t write(const uint8_t *buffer, size_t size) = 0;
|
||||
#include <inttypes.h>
|
||||
#include <string>
|
||||
#include "Print.h"
|
||||
|
||||
virtual int available() = 0;
|
||||
virtual int read() = 0;
|
||||
virtual int peek() = 0;
|
||||
virtual void flush() = 0;
|
||||
// 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)
|
||||
*/
|
||||
|
||||
#if !DOXYGEN
|
||||
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;
|
||||
virtual void flush() = 0;
|
||||
|
||||
Stream() {
|
||||
_timeout = 1000;
|
||||
}
|
||||
|
||||
// parsing methods
|
||||
|
||||
void setTimeout(unsigned long timeout); // sets maximum milliseconds to wait for stream data, default is 1 second
|
||||
|
||||
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
|
||||
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 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)
|
||||
|
||||
// Arduino String functions to be added here
|
||||
std::string readString();
|
||||
std::string readStringUntil(char terminator);
|
||||
|
||||
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
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
+26
-175
@@ -1,185 +1,12 @@
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <stdlib.h>
|
||||
#include "Arduino.h"
|
||||
|
||||
// For millis()
|
||||
static unsigned long millis_at_start = 0;
|
||||
|
||||
/**
|
||||
* C++ version 0.4 char* style "itoa":
|
||||
* Written by Lukás Chmela
|
||||
* Released under GPLv3.
|
||||
*/
|
||||
char *itoa(int value, char* result, int base) {
|
||||
// check that the base if valid
|
||||
if (base < 2 || base > 36) { *result = '\0'; return result; }
|
||||
|
||||
char* ptr = result, *ptr1 = result, tmp_char;
|
||||
int tmp_value;
|
||||
|
||||
do {
|
||||
tmp_value = value;
|
||||
value /= base;
|
||||
*ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)];
|
||||
} while ( value );
|
||||
|
||||
// Apply negative sign
|
||||
// Apply negative sign
|
||||
if (tmp_value < 0) *ptr++ = '-';
|
||||
*ptr-- = '\0';
|
||||
while(ptr1 < ptr) {
|
||||
tmp_char = *ptr;
|
||||
*ptr--= *ptr1;
|
||||
*ptr1++ = tmp_char;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* C++ version 0.4 char* style "itoa":
|
||||
* Written by Lukás Chmela
|
||||
* Released under GPLv3.
|
||||
*/
|
||||
char *ltoa(long value, char* result, int base) {
|
||||
// check that the base if valid
|
||||
if (base < 2 || base > 36) { *result = '\0'; return result; }
|
||||
|
||||
char* ptr = result, *ptr1 = result, tmp_char;
|
||||
long tmp_value;
|
||||
|
||||
do {
|
||||
tmp_value = value;
|
||||
value /= base;
|
||||
*ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)];
|
||||
} while ( value );
|
||||
|
||||
// Apply negative sign
|
||||
if (tmp_value < 0) *ptr++ = '-';
|
||||
*ptr-- = '\0';
|
||||
while(ptr1 < ptr) {
|
||||
tmp_char = *ptr;
|
||||
*ptr--= *ptr1;
|
||||
*ptr1++ = tmp_char;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
char *ultoa(long num, char *str, int radix)
|
||||
{
|
||||
unsigned long value;
|
||||
char *sp = str;
|
||||
char *sp2;
|
||||
|
||||
value = num;
|
||||
|
||||
/* Store sign at start of buffer for negative base-10 values */
|
||||
if (10 == radix && 0 > num) {
|
||||
*sp++ = '-';
|
||||
value = -num;
|
||||
}
|
||||
|
||||
sp2 = sp;
|
||||
|
||||
do {
|
||||
char rem = value % radix;
|
||||
value /= radix;
|
||||
if (10 > rem) {
|
||||
*sp++ = '0' + rem;
|
||||
} else {
|
||||
*sp++ = 'A' + rem - 10;
|
||||
}
|
||||
} while (0 < value);
|
||||
|
||||
/* Mark end of string */
|
||||
*sp-- = 0;
|
||||
|
||||
/* Reverse string contents (excluding sign) in place */
|
||||
while (sp2 < sp) {
|
||||
char tmp = *sp2;
|
||||
*sp2++ = *sp;
|
||||
*sp-- = tmp;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copyright (c) 2012, Peter A. Bigot <bigotp@acm.org>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of the software nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
char *utoa(int num, char *str, int radix)
|
||||
{
|
||||
unsigned int value;
|
||||
char *sp = str;
|
||||
char *sp2;
|
||||
|
||||
value = num;
|
||||
|
||||
/* Store sign at start of buffer for negative base-10 values */
|
||||
if (10 == radix && 0 > num) {
|
||||
*sp++ = '-';
|
||||
value = -num;
|
||||
}
|
||||
|
||||
sp2 = sp;
|
||||
|
||||
do {
|
||||
char rem = value % radix;
|
||||
value /= radix;
|
||||
if (10 > rem) {
|
||||
*sp++ = '0' + rem;
|
||||
} else {
|
||||
*sp++ = 'A' + rem - 10;
|
||||
}
|
||||
} while (0 < value);
|
||||
|
||||
/* Mark end of string */
|
||||
*sp-- = 0;
|
||||
|
||||
/* Reverse string contents (excluding sign) in place */
|
||||
while (sp2 < sp) {
|
||||
char tmp = *sp2;
|
||||
*sp2++ = *sp;
|
||||
*sp-- = tmp;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
char *dtostrf(float f, int width, int decimals, char *result)
|
||||
{
|
||||
sprintf(result,"%*.*f", width, decimals, f);
|
||||
return result;
|
||||
}
|
||||
void yield(void) {}
|
||||
|
||||
unsigned long millis(void)
|
||||
{
|
||||
@@ -202,3 +29,27 @@ void delay(unsigned int millis)
|
||||
sleeper.tv_nsec = (long)(millis % 1000) * 1000000;
|
||||
nanosleep(&sleeper, NULL);
|
||||
}
|
||||
|
||||
void randomSeed(unsigned long seed)
|
||||
{
|
||||
if (seed != 0) {
|
||||
srand(seed);
|
||||
}
|
||||
}
|
||||
|
||||
long randMax(long howbig)
|
||||
{
|
||||
if (howbig == 0) {
|
||||
return 0;
|
||||
}
|
||||
return rand() % howbig;
|
||||
}
|
||||
|
||||
long randMinMax(long howsmall, long howbig)
|
||||
{
|
||||
if (howsmall >= howbig) {
|
||||
return howsmall;
|
||||
}
|
||||
long diff = howbig - howsmall;
|
||||
return randMax(diff) + howsmall;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
noniso.cpp - replacements for non-ISO functions used by Arduino core
|
||||
Copyright © 2016 Ivan Grokhotkov
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
Modified August 2016 by Marcelo Aquino <marceloaqno@gmail.org> for MySensors use
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
#include "stdlib_noniso.h"
|
||||
|
||||
char* utoa(unsigned value, char* result, int base) {
|
||||
if(base < 2 || base > 16) {
|
||||
*result = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
char* out = result;
|
||||
unsigned quotient = value;
|
||||
|
||||
do {
|
||||
const unsigned tmp = quotient / base;
|
||||
*out = "0123456789abcdef"[quotient - (tmp * base)];
|
||||
++out;
|
||||
quotient = tmp;
|
||||
} while(quotient);
|
||||
|
||||
reverse(result, out);
|
||||
*out = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
char* itoa(int value, char* result, int base) {
|
||||
if(base < 2 || base > 16) {
|
||||
*result = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
char* out = result;
|
||||
int quotient = abs(value);
|
||||
|
||||
do {
|
||||
const int tmp = quotient / base;
|
||||
*out = "0123456789abcdef"[quotient - (tmp * base)];
|
||||
++out;
|
||||
quotient = tmp;
|
||||
} while(quotient);
|
||||
|
||||
// Apply negative sign
|
||||
if(value < 0)
|
||||
*out++ = '-';
|
||||
|
||||
reverse(result, out);
|
||||
*out = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
int atoi(const char* s) {
|
||||
return (int) atol(s);
|
||||
}
|
||||
|
||||
long atol(const char* s) {
|
||||
char * tmp;
|
||||
return strtol(s, &tmp, 10);
|
||||
}
|
||||
|
||||
double atof(const char* s) {
|
||||
char * tmp;
|
||||
return strtod(s, &tmp);
|
||||
}
|
||||
|
||||
void reverse(char* begin, char* end) {
|
||||
char *is = begin;
|
||||
char *ie = end - 1;
|
||||
while(is < ie) {
|
||||
char tmp = *ie;
|
||||
*ie = *is;
|
||||
*is = tmp;
|
||||
++is;
|
||||
--ie;
|
||||
}
|
||||
}
|
||||
|
||||
char* ltoa(long value, char* result, int base) {
|
||||
if(base < 2 || base > 16) {
|
||||
*result = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
char* out = result;
|
||||
long quotient = abs(value);
|
||||
|
||||
do {
|
||||
const long tmp = quotient / base;
|
||||
*out = "0123456789abcdef"[quotient - (tmp * base)];
|
||||
++out;
|
||||
quotient = tmp;
|
||||
} while(quotient);
|
||||
|
||||
// Apply negative sign
|
||||
if(value < 0)
|
||||
*out++ = '-';
|
||||
|
||||
reverse(result, out);
|
||||
*out = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
char* ultoa(unsigned long value, char* result, int base) {
|
||||
if(base < 2 || base > 16) {
|
||||
*result = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
char* out = result;
|
||||
unsigned long quotient = value;
|
||||
|
||||
do {
|
||||
const unsigned long tmp = quotient / base;
|
||||
*out = "0123456789abcdef"[quotient - (tmp * base)];
|
||||
++out;
|
||||
quotient = tmp;
|
||||
} while(quotient);
|
||||
|
||||
reverse(result, out);
|
||||
*out = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
char* dtostrf (double val, signed char width, unsigned char prec, char *s) {
|
||||
sprintf(s,"%*.*f", width, prec, val);
|
||||
return s;
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
stdlib_noniso.h - nonstandard (but usefull) conversion functions
|
||||
|
||||
Copyright (c) 2014 Ivan Grokhotkov. All rights reserved.
|
||||
This file is part of the esp8266 core for Arduino environment.
|
||||
|
||||
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 STDLIB_NONISO_H
|
||||
#define STDLIB_NONISO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
int atoi(const char *s);
|
||||
|
||||
long atol(const char* s);
|
||||
|
||||
double atof(const char* s);
|
||||
|
||||
char* itoa (int val, char *s, int radix);
|
||||
|
||||
char* ltoa (long val, char *s, int radix);
|
||||
|
||||
char* utoa (unsigned int val, char *s, int radix);
|
||||
|
||||
char* ultoa (unsigned long val, char *s, int radix);
|
||||
|
||||
char* dtostrf (double val, signed char width, unsigned char prec, char *s);
|
||||
|
||||
void reverse(char* begin, char* end);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user