Add support for serial gateway to Rpi

This commit is contained in:
Marcelo Aquino
2016-08-21 21:01:26 -03:00
parent cb8c98431e
commit 412e41967f
20 changed files with 1241 additions and 239 deletions
+5 -5
View File
@@ -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
View File
@@ -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"
Vendored
+18 -8
View File
@@ -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"
+8 -4
View File
@@ -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;
+4 -2
View File
@@ -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;
+2 -2
View File
@@ -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
}
+2 -2
View File
@@ -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
View File
@@ -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
+1
View File
@@ -21,6 +21,7 @@
#ifndef client_h
#define client_h
#include "Stream.h"
#include "IPAddress.h"
+1 -1
View File
@@ -50,7 +50,7 @@
class EthernetClient : public Client {
private:
int _sock;
int _sock; //!< @brief Network socket.
public:
/**
+238
View File
@@ -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;
}
+76
View File
@@ -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
+159
View File
@@ -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);
}
+100
View File
@@ -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
+3 -1
View File
@@ -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;
};
+258
View File
@@ -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
View File
@@ -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
View File
@@ -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;
}
+147
View File
@@ -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;
}
+52
View File
@@ -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