diff --git a/.travis.yml b/.travis.yml index eebf441..1b624c1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,19 +1,18 @@ -language: erlang # We are creating ARM emulation on travis, so no need for language features - -env: GUEST_DEPENDENCIES="git g++ make sudo autoconf automake m4" +language: cpp +compiler: gcc before_install: - - git submodule update --init --recursive + - git submodule update --init --recursive > /dev/null + - sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test - sudo apt-get update -qq - - sudo apt-get install -qq -y qemu-user-static binfmt-support sbuild - - wget https://launchpad.net/ubuntu/+archive/primary/+files/debootstrap_1.0.59ubuntu0.2_all.deb - - sudo dpkg -i debootstrap_1.0.59ubuntu0.2_all.deb install: - - "bash -ex ./testing/travis-install.sh" + - sudo apt-get install -qq autoconf automake m4 gcc-4.9 g++-4.9 > /dev/null + - sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.9 90 + - "bash -ex ./install-wiringpi.sh" script: - - "bash -ex ./testing/travis-test.sh" + - "bash -ex ./build.sh" branches: only: diff --git a/Makefile.am b/Makefile.am index 293103c..d54e486 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,11 +1,11 @@ bin_PROGRAMS = openstratos -openstratos_SOURCES = openstratos.cpp camera/Camera.cpp gps/GPS.cpp serial/Serial.cpp battery/Battery.cpp +openstratos_SOURCES = openstratos.cpp camera/Camera.cpp gps/GPS.cpp serial/Serial.cpp battery/Battery.cpp temperature/Temperature.cpp openstratos_LDADD = -lwiringPi openstratos_CPPFLAGS = -std=c++11 -Wno-unused-result EXTRA_PROGRAMS = openstratosRoot utesting -openstratosRoot_SOURCES = openstratos-root.cpp camera/Camera.cpp gps/GPS.cpp serial/Serial.cpp battery/Battery.cpp +openstratosRoot_SOURCES = openstratos-root.cpp camera/Camera.cpp gps/GPS.cpp serial/Serial.cpp battery/Battery.cpp temperature/Temperature.cpp openstratosRoot_CPPFLAGS = -std=c++11 -Wno-unused-result -utesting_SOURCES = testing/testing.cpp camera/Camera.cpp gps/GPS.cpp serial/Serial.cpp battery/Battery.cpp +utesting_SOURCES = testing/testing.cpp camera/Camera.cpp gps/GPS.cpp serial/Serial.cpp battery/Battery.cpp temperature/Temperature.cpp utesting_CPPFLAGS = -std=c++11 -Itesting/bandit -Wno-unused-result -DOS_TESTING diff --git a/build.sh b/build.sh index c43f4cb..91822e5 100755 --- a/build.sh +++ b/build.sh @@ -6,4 +6,6 @@ automake --add-missing autoconf ./configure make utesting + +printf "\n\n----- Starting unit tests -----\n\n" ./utesting \ No newline at end of file diff --git a/camera/Camera.cpp b/camera/Camera.cpp index 2d5fb63..a3b3382 100644 --- a/camera/Camera.cpp +++ b/camera/Camera.cpp @@ -33,6 +33,7 @@ void Camera::record(int time) #ifndef RASPIVID command = ""; #endif + system(command.c_str()); this->recording = true; diff --git a/camera/Camera.hpp b/camera/Camera.hpp index 44543fe..1104923 100644 --- a/camera/Camera.hpp +++ b/camera/Camera.hpp @@ -12,6 +12,7 @@ bool recording = false; public: + Camera(Camera& copy) = delete; static Camera& get_instance(); void record(int time); diff --git a/config.hpp b/config.hpp index 680ac49..c7d1012 100644 --- a/config.hpp +++ b/config.hpp @@ -46,9 +46,6 @@ /* Define to 1 if you have the header file. */ #define HAVE_UNISTD_H 1 -/* Define to 1 if the system has the type `_Bool'. */ -/* #undef HAVE__BOOL */ - /* Name of package */ #define PACKAGE "openstratos" diff --git a/configure.ac b/configure.ac index bad25da..4fdff76 100644 --- a/configure.ac +++ b/configure.ac @@ -25,7 +25,6 @@ AC_LANG([C++]) AX_CXX_COMPILE_STDCXX_11() # Checks for typedefs, structures, and compiler characteristics. -AC_CHECK_HEADER_STDBOOL AC_C_INLINE AC_TYPE_SIZE_T diff --git a/constants.hpp b/constants.hpp index 4a3e4ac..81bfc81 100644 --- a/constants.hpp +++ b/constants.hpp @@ -6,6 +6,9 @@ #define ERR_INT 2 #define ERR_PWD 3 + #define TEMP_VIN 5 + #define TEMP_R 500 + #define BAT_MAX 8.4 #define BAT_MIN 7.4 #define BAT_R1 3300 diff --git a/gps/GPS.cpp b/gps/GPS.cpp index 8dd7ae9..d14420f 100644 --- a/gps/GPS.cpp +++ b/gps/GPS.cpp @@ -7,6 +7,7 @@ #include #include +using namespace std; using namespace os; GPS& GPS::get_instance() @@ -22,8 +23,7 @@ GPS::~GPS() void GPS::initialize(const string& serial_URL) { - Serial serial(serial_URL, 9600, "\r\n", bind(&GPS::parse, this, placeholders::_1)); - this->serial = serial; + this->serial.initialize(serial_URL, 9600, "\r\n", bind(&GPS::parse, this, placeholders::_1)); #ifndef OS_TESTING this->serial.send_frame("$PMTK220,100*2F"); diff --git a/gps/GPS.hpp b/gps/GPS.hpp index 2e4828e..e771f98 100644 --- a/gps/GPS.hpp +++ b/gps/GPS.hpp @@ -38,6 +38,7 @@ void parse_RMC(const string& frame); public: + GPS(GPS& copy) = delete; static GPS& get_instance(); tm* get_time() {return &this->time;} diff --git a/install-wiringpi.sh b/install-wiringpi.sh new file mode 100644 index 0000000..9026a01 --- /dev/null +++ b/install-wiringpi.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +printf "Installing WiringPi\n" +git clone https://github.com/OpenStratos/WiringPi.git > /dev/null +cd WiringPi +./build > /dev/null +cd .. \ No newline at end of file diff --git a/serial/Serial.cpp b/serial/Serial.cpp index 366f6a2..a777018 100644 --- a/serial/Serial.cpp +++ b/serial/Serial.cpp @@ -5,20 +5,23 @@ #include #include #include +#include +using namespace std; using namespace os; -Serial::Serial(const string& url, int baud, const string endl, function) +void Serial::initialize(const string& url, int baud, const string endl, function) { this->listener = listener; this->endl = endl; #ifndef OS_TESTING this->fd = serialOpen(url.c_str(), baud); - this->open = true; - - thread t(&Serial::serial_thread, this); - t.detach(); #endif + + this->open = true; + this->stopped = false; + thread t(&Serial::serial_thread, this); + t.detach(); } Serial::~Serial() @@ -33,39 +36,41 @@ void Serial::serial_thread() while(this->open) { - this_thread::sleep_for(chrono::milliseconds(5)); - int available = serialDataAvail(this->fd); + #ifndef OS_TESTING + int available = serialDataAvail(this->fd); - if (available > 0) - { - for (int i = 0; i < available; i++) + if (available > 0) { - char c = serialGetchar(this->fd); - frame += c; - - if (c == this->endl[endl_pos]) ++endl_pos; - if (endl_pos == this->endl.length()) + for (int i = 0; i < available; i++) { - frame = frame.substr(0, frame.length()-endl.length()); + char c = serialGetchar(this->fd); + frame += c; - if (this->is_valid(frame)) this->listener(frame); - // TODO decide what to do in case of non valid frame + if (c == this->endl[endl_pos]) ++endl_pos; + if (endl_pos == this->endl.length()) + { + frame = frame.substr(0, frame.length()-endl.length()); - frame = ""; - endl_pos = 0; - this_thread::sleep_for(chrono::milliseconds(50)); + if (this->is_valid(frame)) this->listener(frame); + // TODO decide what to do in case of non valid frame + + frame = ""; + endl_pos = 0; + this_thread::sleep_for(chrono::milliseconds(50)); + } } } - } - else if (available == 0) - { - this_thread::sleep_for(chrono::milliseconds(25)); - } - else if (available < 0) - { - // TODO log error - } + else if (available == 0) + { + this_thread::sleep_for(chrono::milliseconds(25)); + } + else if (available < 0) + { + // TODO log error + } + #endif } + this->stopped = true; } uint_fast8_t Serial::send_frame(string frame) @@ -84,7 +89,11 @@ uint_fast8_t Serial::send_frame(string frame) void Serial::close() { this->open = false; - serialClose(this->fd); + while( ! this->stopped); + + #ifndef OS_TESTING + serialClose(this->fd); + #endif } bool Serial::is_valid(string frame) diff --git a/serial/Serial.hpp b/serial/Serial.hpp index 5dc747a..475c11d 100644 --- a/serial/Serial.hpp +++ b/serial/Serial.hpp @@ -4,6 +4,7 @@ #include #include #include + #include using namespace std; namespace os { @@ -12,18 +13,20 @@ private: int fd; function listener; - bool open; + atomic_bool open; + atomic_bool stopped; string endl; void serial_thread(); public: - Serial(const string& serial_URL, int baud, const string endl, function); Serial() = default; + Serial(Serial& copy) = delete; ~Serial(); uint_fast8_t send_frame(string frame); void close(); bool is_valid(string frame); + void initialize(const string& serial_URL, int baud, const string endl, function); }; } #endif diff --git a/temperature/Temperature.cpp b/temperature/Temperature.cpp new file mode 100644 index 0000000..23cdca9 --- /dev/null +++ b/temperature/Temperature.cpp @@ -0,0 +1,69 @@ +#include "Temperature.hpp" +#include "../constants.hpp" +#include +#include +#include +#include + +using namespace std; +using namespace os; + +Temperature::~Temperature() +{ + if (this->reading) + this->stop_reading(); +} + +Temperature::Temperature(const int address) +{ + this->reading = false; + this->stopped = true; + #ifndef OS_TESTING + int fh = wiringPiI2CSetup(address); + if (fh != -1) + { + this->address = address; + this->filehandle = fh; + } + else + { + // TODO Log error + //printf("An error ocurred initializing I2C Temperature module\n"); + } + #endif +} + +void Temperature::start_reading() +{ + if ( ! this->reading) + { + this->reading = true; + this->stopped = false; + thread t(&Temperature::read_temperature, this); + t.detach(); + } +} + +void Temperature::stop_reading() +{ + this->reading = false; + while( ! this->stopped); +} + +void Temperature::read_temperature() +{ + while (this->reading) + { + #ifndef OS_TESTING + int value = wiringPiI2CRead(this->filehandle); + #else + int value = 16000; + #endif + + float voltage = value * 5 / 32768; // 2^15 + this->temperature = r_to_c(TEMP_R * (TEMP_VIN / voltage - 1)); + + this_thread::sleep_for(chrono::milliseconds(50)); + } + this->stopped = true; +} diff --git a/temperature/Temperature.hpp b/temperature/Temperature.hpp new file mode 100644 index 0000000..bdf0559 --- /dev/null +++ b/temperature/Temperature.hpp @@ -0,0 +1,35 @@ +#ifndef TEMPERATURE_H + #define TEMPERATURE_H + + #include + using namespace std; + + namespace os { + class Temperature + { + private: + int address; + int filehandle; + float temperature; + atomic_bool reading; + atomic_bool stopped; + + void read_temperature(); + public: + Temperature(const int address); + ~Temperature(); + Temperature(Temperature& copy) = delete; + + int get_temperature() {return this->temperature;} + void start_reading(); + void stop_reading(); + bool is_reading() {return this->reading;} + }; + } + + inline float r_to_c(float r) + { + float value = r - 1000; + return (value / 3.91 + value * value / 100000); + } +#endif diff --git a/testing/gps_test.cpp b/testing/gps_test.cpp index 9f00ab7..edbd80d 100644 --- a/testing/gps_test.cpp +++ b/testing/gps_test.cpp @@ -1,5 +1,9 @@ describe("GPS", [](){ + before_each([&](){ + GPS::get_instance().initialize(""); + }); + it("Knots to m/s conversion test", [&](){ AssertThat(kt_to_mps(150), Is().EqualToWithDelta(77.1666667, 0.005)); AssertThat(kt_to_mps(75), Is().EqualToWithDelta(38.58333, 0.005)); diff --git a/testing/serial_test.cpp b/testing/serial_test.cpp index ec194f5..bf761d0 100644 --- a/testing/serial_test.cpp +++ b/testing/serial_test.cpp @@ -5,10 +5,13 @@ describe("Serial", [](){ string valid2 = "$PMTK226,3,30*4"; string not_valid = "$REPORT,0,23,185213184,1421782514,1,4140.7276,-0404.8853,73,52,43*14"; - Serial serial("", 9600, "\n", NULL); + Serial serial; + serial.initialize("", 9600, "\n", NULL); AssertThat(serial.is_valid(valid), Equals(true)); AssertThat(serial.is_valid(valid2), Equals(true)); AssertThat(serial.is_valid(not_valid), Equals(false)); + + serial.close(); }); }); diff --git a/testing/temperature_test.cpp b/testing/temperature_test.cpp new file mode 100644 index 0000000..81b9028 --- /dev/null +++ b/testing/temperature_test.cpp @@ -0,0 +1,30 @@ +describe("Temperature", [&](){ + + it("read & stop test", [&]() { + Temperature temp(20); + temp.start_reading(); + AssertThat(temp.is_reading(), Equals(true)); + + this_thread::sleep_for(chrono::milliseconds(100)); + + temp.stop_reading(); + AssertThat(temp.is_reading(), Equals(false)); + }); + + it("resistor to temperature conversion test", [&]() { + + AssertThat(r_to_c(1155.4), Is().EqualToWithDelta(40, 0.05)); + AssertThat(r_to_c(1116.9), Is().EqualToWithDelta(30, 0.05)); + AssertThat(r_to_c(1077.9), Is().EqualToWithDelta(20, 0.05)); + AssertThat(r_to_c(1039), Is().EqualToWithDelta(10, 0.05)); + AssertThat(r_to_c(1000), Is().EqualToWithDelta(0, 0.05)); + AssertThat(r_to_c(960.9), Is().EqualToWithDelta(-10, 0.05)); + AssertThat(r_to_c(921.6), Is().EqualToWithDelta(-20, 0.05)); + AssertThat(r_to_c(882.2), Is().EqualToWithDelta(-30, 0.05)); + AssertThat(r_to_c(842.7), Is().EqualToWithDelta(-40, 0.05)); + AssertThat(r_to_c(803.1), Is().EqualToWithDelta(-50, 0.05)); + AssertThat(r_to_c(763.3), Is().EqualToWithDelta(-60, 0.05)); + AssertThat(r_to_c(723.3), Is().EqualToWithDelta(-70, 0.05)); + AssertThat(r_to_c(683.3), Is().EqualToWithDelta(-80, 0.05)); + }); +}); diff --git a/testing/testing.cpp b/testing/testing.cpp index de96164..762eddf 100644 --- a/testing/testing.cpp +++ b/testing/testing.cpp @@ -3,8 +3,10 @@ #include #include #include +#include #include #include + using namespace bandit; using namespace os; using namespace std; @@ -19,7 +21,8 @@ go_bandit([](){ #include "core_test.cpp" #include "camera_test.cpp" - #include "gps_test.cpp" #include "serial_test.cpp" + #include "gps_test.cpp" + #include "temperature_test.cpp" #include "battery_test.cpp" }); diff --git a/testing/travis-install.sh b/testing/travis-install.sh deleted file mode 100644 index 9bb3574..0000000 --- a/testing/travis-install.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash - -# Create chrooted environment -sudo mkdir /tmp/arm-chroot -sudo debootstrap --foreign --no-check-gpg --include=fakeroot,build-essential \ - --arch=armhf jessie /tmp/arm-chroot http://archive.raspbian.org/raspbian > /dev/null -sudo cp /usr/bin/qemu-arm-static /tmp/arm-chroot/usr/bin/ -sudo chroot /tmp/arm-chroot ./debootstrap/debootstrap --second-stage > /dev/null - -sudo sbuild-createchroot --arch=armhf --foreign --setup-only jessie /tmp/arm-chroot \ - http://archive.raspbian.org/raspbian > /dev/null - -sudo mount --bind /dev/pts /tmp/arm-chroot/dev/pts - -# Installing guest dependencies -sudo chroot /tmp/arm-chroot apt-get update -sudo chroot /tmp/arm-chroot apt-get --allow-unauthenticated install \ - -qq -y ${GUEST_DEPENDENCIES} > /dev/null - -# Create build dir and copy travis build files to the chroot environment -sudo mkdir -p /tmp/arm-chroot/${TRAVIS_BUILD_DIR} -sudo rsync -av ${TRAVIS_BUILD_DIR}/ /tmp/arm-chroot/${TRAVIS_BUILD_DIR}/ > /dev/null - -chmod a+x /tmp/arm-chroot/${TRAVIS_BUILD_DIR}/testing/travis-test.sh -chmod a+x /tmp/arm-chroot/${TRAVIS_BUILD_DIR}/build.sh \ No newline at end of file diff --git a/testing/travis-test.sh b/testing/travis-test.sh deleted file mode 100644 index 0e0c68d..0000000 --- a/testing/travis-test.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash - -if [ -e "/.chroot_is_done" ]; then - - printf "\n\n" - printf "|------------------------------------------------------------|\n\n" - printf "Environment: $(uname -a)\n\n" - printf "|------------------------------------------------------------|\n\n" - - # Installing WiringPi - printf "Installing WiringPi\n" - git clone https://github.com/OpenStratos/WiringPi.git > /dev/null - cd WiringPi - ./build > /dev/null - cd .. - - # Start build - ./build.sh -else - sudo touch /tmp/arm-chroot/.chroot_is_done - sudo chroot /tmp/arm-chroot bash -c "cd ${TRAVIS_BUILD_DIR} && ./testing/travis-test.sh" -fi \ No newline at end of file