From e87047652645d30ce7f13f3b731b8db6a7338238 Mon Sep 17 00:00:00 2001 From: dragonprevost Date: Tue, 13 Nov 2018 10:49:54 -0800 Subject: added header --- readme.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/readme.md b/readme.md index e69de29..12f338a 100644 --- a/readme.md +++ b/readme.md @@ -0,0 +1,2 @@ +Impact Monitor +====== -- cgit v1.2.3 From 71bfb918c22028176dfba996eed81127eefefe61 Mon Sep 17 00:00:00 2001 From: dragonprevost Date: Tue, 13 Nov 2018 11:01:51 -0800 Subject: added project description --- readme.md | 1 + 1 file changed, 1 insertion(+) diff --git a/readme.md b/readme.md index 12f338a..b6cf700 100644 --- a/readme.md +++ b/readme.md @@ -1,2 +1,3 @@ Impact Monitor ====== +This application is designed to operate on a [MongOH Red](https://mangoh.io/mangoh-red-new) WP85 board. Using *general input output* this project uses pthreads to probes a bmi160 chip intermitantly in order to detect a significant impact. -- cgit v1.2.3 From 7211e981440c24418904fe3c86a5bdd337ef45fd Mon Sep 17 00:00:00 2001 From: dragonprevost Date: Tue, 13 Nov 2018 11:19:07 -0800 Subject: added make file --- Makefile | 2 ++ readme.md | 12 ++++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..15acc73 --- /dev/null +++ b/Makefile @@ -0,0 +1,2 @@ +wp85: + mkapp -t -b motionService.adef diff --git a/readme.md b/readme.md index b6cf700..df3089c 100644 --- a/readme.md +++ b/readme.md @@ -1,3 +1,11 @@ -Impact Monitor +Motion Service ====== -This application is designed to operate on a [MongOH Red](https://mangoh.io/mangoh-red-new) WP85 board. Using *general input output* this project uses pthreads to probes a bmi160 chip intermitantly in order to detect a significant impact. +This application is designed to operate on a [MongOH Red](https://mangoh.io/mangoh-red-new) WP85 board. Using **general input output** this project uses pthreads to probes a bmi160 chip intermittently in order to detect a significant impact. + +##Prerequisits +Throw in some prereq + +##Getting Started +Compile the project using +```make wp85``` + -- cgit v1.2.3 From 232df147ba604648efd8cdbb4b22f9b1d7d4818e Mon Sep 17 00:00:00 2001 From: dragonprevost Date: Tue, 13 Nov 2018 11:20:29 -0800 Subject: fixed readme formatting --- readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index df3089c..875b55f 100644 --- a/readme.md +++ b/readme.md @@ -2,10 +2,10 @@ Motion Service ====== This application is designed to operate on a [MongOH Red](https://mangoh.io/mangoh-red-new) WP85 board. Using **general input output** this project uses pthreads to probes a bmi160 chip intermittently in order to detect a significant impact. -##Prerequisits +## Prerequisits Throw in some prereq -##Getting Started +## Getting Started Compile the project using ```make wp85``` -- cgit v1.2.3 From 94ba948f63c8b3b43ed858c601bb3ddf2e59bd35 Mon Sep 17 00:00:00 2001 From: dragonprevost Date: Tue, 13 Nov 2018 11:29:57 -0800 Subject: readme formatting --- readme.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/readme.md b/readme.md index 875b55f..85bb459 100644 --- a/readme.md +++ b/readme.md @@ -1,11 +1,13 @@ -Motion Service +MangOH Motion Service ====== -This application is designed to operate on a [MongOH Red](https://mangoh.io/mangoh-red-new) WP85 board. Using **general input output** this project uses pthreads to probes a bmi160 chip intermittently in order to detect a significant impact. +This application is designed to operate on a [MongOH Red](https://mangoh.io/mangoh-red-new) WP85 board. Using **general input output** this project uses pthreads to probe the onboard bmi160 chip intermittently in order to detect a significant motion on the board. -## Prerequisits +## Prerequisites Throw in some prereq ## Getting Started Compile the project using -```make wp85``` +``make wp85`` + +## Setting -- cgit v1.2.3 From 94ba7c621dffcc373c2ced094badc96042853525 Mon Sep 17 00:00:00 2001 From: dragonprevost Date: Tue, 13 Nov 2018 11:55:14 -0800 Subject: adding settings to readme --- readme.md | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/readme.md b/readme.md index 85bb459..9b96aad 100644 --- a/readme.md +++ b/readme.md @@ -3,11 +3,23 @@ MangOH Motion Service This application is designed to operate on a [MongOH Red](https://mangoh.io/mangoh-red-new) WP85 board. Using **general input output** this project uses pthreads to probe the onboard bmi160 chip intermittently in order to detect a significant motion on the board. ## Prerequisites -Throw in some prereq -## Getting Started +When cloning use ``git clone --recurse-submodule https://github.com/brnkl/motion-service.git`` +to include the util module. + + +## Building Compile the project using -``make wp85`` +wp85: ``make wp85`` + +## Setting Variables +To change the sensitivity of the application you must edit the `motionMonitor/motionMonitor.c` file. +The Accelerometer measures acceleration in 3 dimensions, X, Y, and Z. These dimensions of acceleration are recorded and the magnitude of their resulting vector is calculated using ``double impactMagnitude = sqrt(x * x + y * y + z * z);`` +`#define DEFAULT_THRESHOLD_MS2 17` determines the magnitude of the resulting vector that will trigger the application to detect a sudden impact. + +If adjusting the value of `DEFAUTL_THRESHOLD_MS2` keep in mind that gravity implies a motionless magnitude of -9.8m/s^2 + +As visualized with the red vector here. +![Magnitude](https://www.intmath.com/vectors/img/235-3D-vector.png) -## Setting -- cgit v1.2.3 From f5725d13ef13953ffdb1c430e64b7c382aeb8285 Mon Sep 17 00:00:00 2001 From: dragonprevost Date: Tue, 13 Nov 2018 11:58:07 -0800 Subject: image formatting --- readme.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/readme.md b/readme.md index 9b96aad..5f592bd 100644 --- a/readme.md +++ b/readme.md @@ -13,13 +13,14 @@ Compile the project using wp85: ``make wp85`` ## Setting Variables -To change the sensitivity of the application you must edit the `motionMonitor/motionMonitor.c` file. +To change the sensitivity of impact detection you must edit the `motionMonitor/motionMonitor.c` file. The Accelerometer measures acceleration in 3 dimensions, X, Y, and Z. These dimensions of acceleration are recorded and the magnitude of their resulting vector is calculated using ``double impactMagnitude = sqrt(x * x + y * y + z * z);`` + +![Magnitude](https://www.intmath.com/vectors/img/235-3D-vector.png) + + `#define DEFAULT_THRESHOLD_MS2 17` determines the magnitude of the resulting vector that will trigger the application to detect a sudden impact. If adjusting the value of `DEFAUTL_THRESHOLD_MS2` keep in mind that gravity implies a motionless magnitude of -9.8m/s^2 As visualized with the red vector here. -![Magnitude](https://www.intmath.com/vectors/img/235-3D-vector.png) - - -- cgit v1.2.3 From 93b7465821b72332a5f917496e637a6453bafc67 Mon Sep 17 00:00:00 2001 From: dragonprevost Date: Tue, 13 Nov 2018 12:00:44 -0800 Subject: moved vector imafe --- readme.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/readme.md b/readme.md index 5f592bd..a0b6898 100644 --- a/readme.md +++ b/readme.md @@ -14,7 +14,7 @@ wp85: ``make wp85`` ## Setting Variables To change the sensitivity of impact detection you must edit the `motionMonitor/motionMonitor.c` file. -The Accelerometer measures acceleration in 3 dimensions, X, Y, and Z. These dimensions of acceleration are recorded and the magnitude of their resulting vector is calculated using ``double impactMagnitude = sqrt(x * x + y * y + z * z);`` +The Accelerometer measures acceleration in 3 dimensions, X, Y, and Z. These dimensions of acceleration are recorded and the magnitude of their resulting vector is calculated using ``double impactMagnitude = sqrt(x * x + y * y + z * z);``. As visualized in the image below. ![Magnitude](https://www.intmath.com/vectors/img/235-3D-vector.png) @@ -23,4 +23,3 @@ The Accelerometer measures acceleration in 3 dimensions, X, Y, and Z. These dime If adjusting the value of `DEFAUTL_THRESHOLD_MS2` keep in mind that gravity implies a motionless magnitude of -9.8m/s^2 -As visualized with the red vector here. -- cgit v1.2.3 From b4c985b4fa6ccf24b2474bb28e98ee9cd12e4f37 Mon Sep 17 00:00:00 2001 From: dragonprevost Date: Tue, 13 Nov 2018 12:34:58 -0800 Subject: added clean to makefile --- Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Makefile b/Makefile index 15acc73..5f264a2 100644 --- a/Makefile +++ b/Makefile @@ -1,2 +1,4 @@ wp85: mkapp -t -b motionService.adef +clean: + rm -r _build_* -- cgit v1.2.3 From 902423bd25ae3a9019220d2fb751e5854ff45cd6 Mon Sep 17 00:00:00 2001 From: dragonprevost Date: Tue, 13 Nov 2018 12:35:41 -0800 Subject: added bindinds and example headers to readme --- readme.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/readme.md b/readme.md index a0b6898..4cffa17 100644 --- a/readme.md +++ b/readme.md @@ -10,6 +10,7 @@ to include the util module. ## Building Compile the project using + wp85: ``make wp85`` ## Setting Variables @@ -21,5 +22,10 @@ The Accelerometer measures acceleration in 3 dimensions, X, Y, and Z. These dime `#define DEFAULT_THRESHOLD_MS2 17` determines the magnitude of the resulting vector that will trigger the application to detect a sudden impact. -If adjusting the value of `DEFAUTL_THRESHOLD_MS2` keep in mind that gravity implies a motionless magnitude of -9.8m/s^2 +If adjusting the value of `DEFAUTL_THRESHOLD_MS2` keep in mind that gravity implies a motionless magnitude of -9.8m/s^2. + +## Bindings + +## Example + -- cgit v1.2.3 From 854ce50239de16051fcfbb2b428792d91f53f988 Mon Sep 17 00:00:00 2001 From: dragonprevost Date: Tue, 13 Nov 2018 12:50:37 -0800 Subject: added content to bindings --- readme.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/readme.md b/readme.md index 4cffa17..2b48970 100644 --- a/readme.md +++ b/readme.md @@ -25,6 +25,25 @@ The Accelerometer measures acceleration in 3 dimensions, X, Y, and Z. These dime If adjusting the value of `DEFAUTL_THRESHOLD_MS2` keep in mind that gravity implies a motionless magnitude of -9.8m/s^2. ## Bindings +``` +... +bindings: +{ + myClientApp.myComponent.brnkl_motion -> motionService.brnkl_motion +} +... +``` +``` +... +requires: +{ + api: + { + brnkl_motion.api + } +} +... +``` ## Example -- cgit v1.2.3 From 2c9f4355b1669c7f656585be7e083cbd4036d963 Mon Sep 17 00:00:00 2001 From: dragonprevost Date: Tue, 13 Nov 2018 14:36:05 -0800 Subject: added to bindings --- readme.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 2b48970..2b5a6a2 100644 --- a/readme.md +++ b/readme.md @@ -25,6 +25,7 @@ The Accelerometer measures acceleration in 3 dimensions, X, Y, and Z. These dime If adjusting the value of `DEFAUTL_THRESHOLD_MS2` keep in mind that gravity implies a motionless magnitude of -9.8m/s^2. ## Bindings +App.adef ``` ... bindings: @@ -33,6 +34,7 @@ bindings: } ... ``` +Component.cdef ``` ... requires: @@ -45,6 +47,8 @@ requires: ... ``` -## Example + +## Example + -- cgit v1.2.3 From e4454a200dba88b65110bb81f40e413fb891ea36 Mon Sep 17 00:00:00 2001 From: dragonprevost Date: Tue, 13 Nov 2018 14:54:45 -0800 Subject: adjusted mkapp function to include target --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 5f264a2..84cd21e 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ wp85: - mkapp -t -b motionService.adef + mkapp -t wp85 motionService.adef -b clean: rm -r _build_* -- cgit v1.2.3 From a30c1a3af414f743c1ad40e66d6a3c7ada1064a1 Mon Sep 17 00:00:00 2001 From: dragonprevost Date: Tue, 13 Nov 2018 14:59:04 -0800 Subject: added util to repo --- .gitmodules | 3 + brnkl-util | 1 + util/README.md | 72 ++++++++++++ util/util.c | 366 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ util/util.h | 77 ++++++++++++ 5 files changed, 519 insertions(+) create mode 100644 .gitmodules create mode 160000 brnkl-util create mode 100644 util/README.md create mode 100644 util/util.c create mode 100644 util/util.h diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..4359c25 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "brnkl-util"] + path = brnkl-util + url = https://github.com/brnkl/brnkl-util.git diff --git a/brnkl-util b/brnkl-util new file mode 160000 index 0000000..40b51b2 --- /dev/null +++ b/brnkl-util @@ -0,0 +1 @@ +Subproject commit 40b51b270579af9772190ed9681438416a62ce75 diff --git a/util/README.md b/util/README.md new file mode 100644 index 0000000..bda72c8 --- /dev/null +++ b/util/README.md @@ -0,0 +1,72 @@ +# brnkl-util + +Small collection of helper functions required by some of our open source code + +## File I/O + +Functions to handle boilerplate when reading and writing from files. + +```c +le_result_t ioutil_readIntFromFile(const char* path, int* value); +le_result_t ioutil_readDoubleFromFile(const char* filePath, double* value); +le_result_t ioutil_writeToFile(const char* path, + void* value, + size_t size, + size_t count); + +le_result_t ioutil_appendToFile(const char* path, + void* value, + size_t size, + size_t count); + +``` + +## General + +Collection of unsorted helper functions + +```c +uint64_t GetCurrentTimestamp(void); +time_t util_getMTime(char* path); +int util_getUnixDatetime(); +le_result_t util_flattenRes(le_result_t* res, int nRes); +bool util_fileExists(const char* path); +bool util_alreadyMounted(const char* devPath); +void* util_find(Functional* f); +void util_listDir(const char* dir, char* dest, size_t size); +``` + +## GPIO (Linux SysFS) + +Provides API calls for all functionality supported by the Linux SysFS GPIO interface + +```c +le_result_t gpio_exportPin(char* pin); +le_result_t gpio_unexportPin(char* pin); +void getGpioPath(char* outputStr, char* pin, char* subDir); +le_result_t gpio_setDirection(char* pin, char* direction); +le_result_t gpio_setInput(char* pin); +le_result_t gpio_setOutput(char* pin); +le_result_t gpio_setActiveState(char* pin, bool isActiveLow); +le_result_t gpio_isActive(char* pin, bool* isActive); +le_result_t gpio_setValue(char* pin, bool state); +le_result_t gpio_setLow(char* pin); +le_result_t gpio_setHigh(char* pin); +le_result_t gpio_setPull(char* pin, char* pull); +le_result_t gpio_pullDown(char* pin); +le_result_t gpio_pullUp(char* pin); +``` + +## Serial + +Handler boilerplate for reading and writing to a serial port + +```c +int fd_openSerial(const char* device, int baud); +speed_t fd_convertBaud(int baud); +int fd_puts(const int fd, const char* s); +int fd_getChar(const int fd); +void fd_flush(const int fd); +int fd_dataAvail(int fd, int* data); +void fd_flushInput(const int fd); +``` diff --git a/util/util.c b/util/util.c new file mode 100644 index 0000000..3042c22 --- /dev/null +++ b/util/util.c @@ -0,0 +1,366 @@ +#include "util.h" +#include "legato.h" +#include + +le_result_t readFromFile(const char* path, + void* value, + int (*scanCallback)(FILE* f, void* val)) { + FILE* f = fopen(path, "r"); + if (f == NULL) { + LE_WARN("Couldn't open '%s' - %m", path); + return LE_IO_ERROR; + } + int numScanned = scanCallback(f, value); + if (numScanned != 1) + return LE_FORMAT_ERROR; + fclose(f); + return LE_OK; +} + +int scanIntCallback(FILE* f, void* value) { + int* val = value; + return fscanf(f, "%d", val); +} + +int scanDoubleCallback(FILE* f, void* value) { + double* val = value; + return fscanf(f, "%lf", val); +} + +le_result_t ioutil_readIntFromFile(const char* path, int* value) { + return readFromFile(path, value, scanIntCallback); +} + +le_result_t ioutil_readDoubleFromFile(const char* path, double* value) { + return readFromFile(path, value, scanDoubleCallback); +} + +le_result_t writeToFile(const char* path, + void* value, + size_t size, + size_t count, + const char* openMode) { + FILE* f = fopen(path, openMode); + if (f == NULL) { + LE_WARN("Failed to open %s for writing", path); + return LE_IO_ERROR; + } + fwrite(value, size, count, f); + fflush(f); + fclose(f); + return LE_OK; +} + +le_result_t ioutil_writeToFile(const char* path, + void* value, + size_t size, + size_t count) { + return writeToFile(path, value, size, count, "w"); +} + +le_result_t ioutil_appendToFile(const char* path, + void* value, + size_t size, + size_t count) { + return writeToFile(path, value, size, count, "a"); +} + +le_result_t util_flattenRes(le_result_t* res, int nRes) { + for (int i = 0; i < nRes; i++) { + if (res[i] != LE_OK) + return res[i]; + } + return LE_OK; +} + +int util_getUnixDatetime() { + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec; +} + +/** + * Get the last modified datetime + * of the file at path + */ +time_t util_getMTime(char* path) { + struct stat st; + if (stat(path, &st) != 0) + return -1; + else + return st.st_mtime; +} + +bool util_fileExists(const char* path) { + struct stat st; + return stat(path, &st) == 0; +} + +bool util_alreadyMounted(const char* devPath) { + char content[2048]; + FILE* f = fopen("/proc/mounts", "r"); + if (f == NULL) { + return false; + } + fread(content, sizeof(char), sizeof(content), f); + // if this ref is non-null, we found a match + return strstr(content, devPath) != NULL; +} + +uint64_t GetCurrentTimestamp(void) { + struct timeval tv; + gettimeofday(&tv, NULL); + uint64_t utcMilliSec = + (uint64_t)(tv.tv_sec) * 1000 + (uint64_t)(tv.tv_usec) / 1000; + return utcMilliSec; +} + +// TODO verify this is working +le_result_t gpio_exportPin(char* pin) { + int len = strlen(pin); + return ioutil_writeToFile("/sys/class/gpio/export", &pin, sizeof(char), len); +} + +le_result_t gpio_unexportPin(char* pin) { + int len = strlen(pin); + return ioutil_writeToFile("/sys/class/gpio/unexport", &pin, sizeof(char), + len); +} + +void getGpioPath(char* outputStr, char* pin, char* subDir) { + sprintf(outputStr, "/sys/class/gpio/gpio%s/%s", pin, subDir); +} + +le_result_t gpio_setDirection(char* pin, char* direction) { + char path[100]; + getGpioPath(path, pin, "direction"); + return ioutil_writeToFile(path, direction, sizeof(char), strlen(direction)); +} + +le_result_t gpio_setPull(char* pin, char* pull) { + char path[100]; + getGpioPath(path, pin, "pull"); + return ioutil_writeToFile(path, pull, sizeof(char), strlen(pull)); +} + +le_result_t gpio_pullDown(char* pin) { + return gpio_setPull(pin, "down"); +} + +le_result_t gpio_pullUp(char* pin) { + return gpio_setPull(pin, "up"); +} + +le_result_t gpio_setInput(char* pin) { + return gpio_setDirection(pin, "in"); +} + +le_result_t gpio_setOutput(char* pin) { + return gpio_setDirection(pin, "out"); +} + +le_result_t gpio_setActiveState(char* pin, bool isActiveLow) { + // Any non zero value toggles the existing value + // so we must read the existing value first + char path[100]; + int isActiveLowSet; + getGpioPath(path, pin, "active_low"); + le_result_t readRes = ioutil_readIntFromFile(path, &isActiveLowSet); + le_result_t writeRes = LE_OK; + if (isActiveLow != isActiveLowSet) { + writeRes = ioutil_writeToFile(path, "1", sizeof(char), 1); + } + return readRes == LE_OK && writeRes == LE_OK ? LE_OK : LE_FAULT; +} + +le_result_t gpio_isActive(char* pin, bool* isActive) { + char path[50]; + getGpioPath(path, pin, "value"); + int val; + le_result_t readRes = ioutil_readIntFromFile(path, &val); + *isActive = val; + return readRes; +} + +le_result_t gpio_setValue(char* pin, bool state) { + char path[50]; + getGpioPath(path, pin, "value"); + char* strState = state ? "1" : "0"; + return ioutil_writeToFile(path, &strState, sizeof(char), strlen(strState)); +} + +le_result_t gpio_setLow(char* pin) { + return gpio_setValue(pin, LOW); +} + +le_result_t gpio_setHigh(char* pin) { + return gpio_setValue(pin, HIGH); +} + +void* util_find(Functional* f) { + f->args.i = 0; + while (f->args.i < f->n) { + if (f->callback(&f->args)) { + return f->derefCallback(f->args.i, f->args.arr); + } + f->args.i++; + } + return NULL; +} + +void util_listDir(const char* dir, char* dest, size_t size) { + struct dirent* de; + char toConcat[1024]; + DIR* dr = opendir(dir); + if (dr == NULL) + return; + while ((de = readdir(dr)) != NULL) { + if (de->d_name[0] != '.') { + snprintf(toConcat, size, "%s,", de->d_name); + strncat(dest, toConcat, size); + } + } + closedir(dr); +} + +/** + * Convert an integer baud rate to a speed_t + */ +speed_t fd_convertBaud(int baud) { + speed_t b; + switch (baud) { + case 50: + b = B50; + break; + case 75: + b = B75; + break; + case 110: + b = B110; + break; + case 134: + b = B134; + break; + case 150: + b = B150; + break; + case 200: + b = B200; + break; + case 300: + b = B300; + break; + case 600: + b = B600; + break; + case 1200: + b = B1200; + break; + case 1800: + b = B1800; + break; + case 2400: + b = B2400; + break; + case 9600: + b = B9600; + break; + case 19200: + b = B19200; + break; + case 38400: + b = B38400; + break; + case 57600: + b = B57600; + break; + case 115200: + b = B115200; + break; + case 230400: + b = B230400; + break; + case 921600: + b = B921600; + break; + default: + b = -2; + } + return b; +} + +/** + * Open a serial connection on device + * + * Lifted from here + * https://github.com/WiringPi/WiringPi/blob/master/wiringPi/wiringSerial.c + */ +int fd_openSerial(const char* device, int baud) { + struct termios options; + speed_t binaryBaud = fd_convertBaud(baud); + int status, fd; + if ((fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK)) == -1) + return -1; + fcntl(fd, F_SETFL, O_RDWR); + tcgetattr(fd, &options); + cfmakeraw(&options); + cfsetispeed(&options, binaryBaud); + cfsetospeed(&options, binaryBaud); + + options.c_cflag |= (CLOCAL | CREAD); + options.c_cflag &= ~PARENB; + options.c_cflag &= ~CSTOPB; + options.c_cflag &= ~CSIZE; + options.c_cflag |= CS8; + options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); + options.c_oflag &= ~OPOST; + + options.c_cc[VMIN] = 0; + options.c_cc[VTIME] = 10; // Ten seconds (100 deciseconds) + + tcsetattr(fd, TCSANOW | TCSAFLUSH, &options); + + ioctl(fd, TIOCMGET, &status); + + status |= TIOCM_DTR; + status |= TIOCM_RTS; + + ioctl(fd, TIOCMSET, &status); + usleep(10000); // 10mS + return fd; +} + +int fd_puts(const int fd, const char* s) { + return write(fd, s, strlen(s)); +} + +int fd_getChar(const int fd) { + uint8_t x; + + if (read(fd, &x, 1) != 1) + return -1; + + return ((int)x) & 0xFF; +} + +void fd_flush(const int fd) { + // tcflush(fd, TCIOFLUSH); + tcdrain(fd); +} + +void fd_flushInput(const int fd) { + tcflush(fd, TCIFLUSH); +} + +int fd_dataAvail(int fd, int* data) { + return ioctl(fd, FIONREAD, data); +} + +double util_avgDouble(double* readings, int nReadings) { + double sum = 0; + for (int i = 0; i < nReadings; i++) { + sum += readings[i]; + } + + return sum / nReadings; +} diff --git a/util/util.h b/util/util.h new file mode 100644 index 0000000..06ef2fb --- /dev/null +++ b/util/util.h @@ -0,0 +1,77 @@ +#ifndef UTIL_H +#define UTIL_H + +#include "legato.h" +#include + +#define HIGH 1 +#define LOW 0 + +typedef struct { + int i; + void* arr; + void* ctxp; +} FunctionalArgs; + +typedef struct { + int n; // number of elements in array + bool (*callback)(FunctionalArgs* args); // callback applied to arr[i] + void* (*derefCallback)(int i, void* j); // callback used to deference arr[i] + FunctionalArgs args; +} Functional; + +// ioutil +le_result_t readFromFile(const char* path, + void* value, + int (*scanCallback)(FILE* f, void* val)); +int scanDoubleCallback(FILE* f, void* value); +le_result_t ioutil_readIntFromFile(const char* path, int* value); +le_result_t ioutil_readDoubleFromFile(const char* filePath, double* value); +le_result_t ioutil_writeToFile(const char* path, + void* value, + size_t size, + size_t count); + +le_result_t ioutil_appendToFile(const char* path, + void* value, + size_t size, + size_t count); + +// TODO fix this name (no PascalCase) +uint64_t GetCurrentTimestamp(void); +time_t util_getMTime(char* path); +int util_getUnixDatetime(); +le_result_t util_flattenRes(le_result_t* res, int nRes); +bool util_fileExists(const char* path); +bool util_alreadyMounted(const char* devPath); +double util_avgDouble(double* readings, int nReadings); + +// TODO verify this is working +le_result_t gpio_exportPin(char* pin); +le_result_t gpio_unexportPin(char* pin); +void getGpioPath(char* outputStr, char* pin, char* subDir); +le_result_t gpio_setDirection(char* pin, char* direction); +le_result_t gpio_setInput(char* pin); +le_result_t gpio_setOutput(char* pin); +le_result_t gpio_setActiveState(char* pin, bool isActiveLow); +le_result_t gpio_isActive(char* pin, bool* isActive); +le_result_t gpio_setValue(char* pin, bool state); +le_result_t gpio_setLow(char* pin); +le_result_t gpio_setHigh(char* pin); +le_result_t gpio_setPull(char* pin, char* pull); +le_result_t gpio_pullDown(char* pin); +le_result_t gpio_pullUp(char* pin); + +void* util_find(Functional* f); + +void util_listDir(const char* dir, char* dest, size_t size); + +int fd_openSerial(const char* device, int baud); +speed_t fd_convertBaud(int baud); +int fd_puts(const int fd, const char* s); +int fd_getChar(const int fd); +void fd_flush(const int fd); +int fd_dataAvail(int fd, int* data); +void fd_flushInput(const int fd); + +#endif -- cgit v1.2.3 From aabe2dba92a9bcc7f2ed2d2361e94c30c9499dc0 Mon Sep 17 00:00:00 2001 From: dragonprevost Date: Tue, 13 Nov 2018 14:59:39 -0800 Subject: removed brnkl-util for name change --- .gitmodules | 3 --- brnkl-util | 1 - 2 files changed, 4 deletions(-) delete mode 160000 brnkl-util diff --git a/.gitmodules b/.gitmodules index 4359c25..e69de29 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +0,0 @@ -[submodule "brnkl-util"] - path = brnkl-util - url = https://github.com/brnkl/brnkl-util.git diff --git a/brnkl-util b/brnkl-util deleted file mode 160000 index 40b51b2..0000000 --- a/brnkl-util +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 40b51b270579af9772190ed9681438416a62ce75 -- cgit v1.2.3 From 6d322af7d89bfaeca7d561280505e285e07c29a7 Mon Sep 17 00:00:00 2001 From: dragonprevost Date: Tue, 13 Nov 2018 15:02:08 -0800 Subject: deleted util to resolve conflict when pushing --- util/README.md | 72 ------------ util/util.c | 366 --------------------------------------------------------- util/util.h | 77 ------------ 3 files changed, 515 deletions(-) delete mode 100644 util/README.md delete mode 100644 util/util.c delete mode 100644 util/util.h diff --git a/util/README.md b/util/README.md deleted file mode 100644 index bda72c8..0000000 --- a/util/README.md +++ /dev/null @@ -1,72 +0,0 @@ -# brnkl-util - -Small collection of helper functions required by some of our open source code - -## File I/O - -Functions to handle boilerplate when reading and writing from files. - -```c -le_result_t ioutil_readIntFromFile(const char* path, int* value); -le_result_t ioutil_readDoubleFromFile(const char* filePath, double* value); -le_result_t ioutil_writeToFile(const char* path, - void* value, - size_t size, - size_t count); - -le_result_t ioutil_appendToFile(const char* path, - void* value, - size_t size, - size_t count); - -``` - -## General - -Collection of unsorted helper functions - -```c -uint64_t GetCurrentTimestamp(void); -time_t util_getMTime(char* path); -int util_getUnixDatetime(); -le_result_t util_flattenRes(le_result_t* res, int nRes); -bool util_fileExists(const char* path); -bool util_alreadyMounted(const char* devPath); -void* util_find(Functional* f); -void util_listDir(const char* dir, char* dest, size_t size); -``` - -## GPIO (Linux SysFS) - -Provides API calls for all functionality supported by the Linux SysFS GPIO interface - -```c -le_result_t gpio_exportPin(char* pin); -le_result_t gpio_unexportPin(char* pin); -void getGpioPath(char* outputStr, char* pin, char* subDir); -le_result_t gpio_setDirection(char* pin, char* direction); -le_result_t gpio_setInput(char* pin); -le_result_t gpio_setOutput(char* pin); -le_result_t gpio_setActiveState(char* pin, bool isActiveLow); -le_result_t gpio_isActive(char* pin, bool* isActive); -le_result_t gpio_setValue(char* pin, bool state); -le_result_t gpio_setLow(char* pin); -le_result_t gpio_setHigh(char* pin); -le_result_t gpio_setPull(char* pin, char* pull); -le_result_t gpio_pullDown(char* pin); -le_result_t gpio_pullUp(char* pin); -``` - -## Serial - -Handler boilerplate for reading and writing to a serial port - -```c -int fd_openSerial(const char* device, int baud); -speed_t fd_convertBaud(int baud); -int fd_puts(const int fd, const char* s); -int fd_getChar(const int fd); -void fd_flush(const int fd); -int fd_dataAvail(int fd, int* data); -void fd_flushInput(const int fd); -``` diff --git a/util/util.c b/util/util.c deleted file mode 100644 index 3042c22..0000000 --- a/util/util.c +++ /dev/null @@ -1,366 +0,0 @@ -#include "util.h" -#include "legato.h" -#include - -le_result_t readFromFile(const char* path, - void* value, - int (*scanCallback)(FILE* f, void* val)) { - FILE* f = fopen(path, "r"); - if (f == NULL) { - LE_WARN("Couldn't open '%s' - %m", path); - return LE_IO_ERROR; - } - int numScanned = scanCallback(f, value); - if (numScanned != 1) - return LE_FORMAT_ERROR; - fclose(f); - return LE_OK; -} - -int scanIntCallback(FILE* f, void* value) { - int* val = value; - return fscanf(f, "%d", val); -} - -int scanDoubleCallback(FILE* f, void* value) { - double* val = value; - return fscanf(f, "%lf", val); -} - -le_result_t ioutil_readIntFromFile(const char* path, int* value) { - return readFromFile(path, value, scanIntCallback); -} - -le_result_t ioutil_readDoubleFromFile(const char* path, double* value) { - return readFromFile(path, value, scanDoubleCallback); -} - -le_result_t writeToFile(const char* path, - void* value, - size_t size, - size_t count, - const char* openMode) { - FILE* f = fopen(path, openMode); - if (f == NULL) { - LE_WARN("Failed to open %s for writing", path); - return LE_IO_ERROR; - } - fwrite(value, size, count, f); - fflush(f); - fclose(f); - return LE_OK; -} - -le_result_t ioutil_writeToFile(const char* path, - void* value, - size_t size, - size_t count) { - return writeToFile(path, value, size, count, "w"); -} - -le_result_t ioutil_appendToFile(const char* path, - void* value, - size_t size, - size_t count) { - return writeToFile(path, value, size, count, "a"); -} - -le_result_t util_flattenRes(le_result_t* res, int nRes) { - for (int i = 0; i < nRes; i++) { - if (res[i] != LE_OK) - return res[i]; - } - return LE_OK; -} - -int util_getUnixDatetime() { - struct timeval tv; - gettimeofday(&tv, NULL); - return tv.tv_sec; -} - -/** - * Get the last modified datetime - * of the file at path - */ -time_t util_getMTime(char* path) { - struct stat st; - if (stat(path, &st) != 0) - return -1; - else - return st.st_mtime; -} - -bool util_fileExists(const char* path) { - struct stat st; - return stat(path, &st) == 0; -} - -bool util_alreadyMounted(const char* devPath) { - char content[2048]; - FILE* f = fopen("/proc/mounts", "r"); - if (f == NULL) { - return false; - } - fread(content, sizeof(char), sizeof(content), f); - // if this ref is non-null, we found a match - return strstr(content, devPath) != NULL; -} - -uint64_t GetCurrentTimestamp(void) { - struct timeval tv; - gettimeofday(&tv, NULL); - uint64_t utcMilliSec = - (uint64_t)(tv.tv_sec) * 1000 + (uint64_t)(tv.tv_usec) / 1000; - return utcMilliSec; -} - -// TODO verify this is working -le_result_t gpio_exportPin(char* pin) { - int len = strlen(pin); - return ioutil_writeToFile("/sys/class/gpio/export", &pin, sizeof(char), len); -} - -le_result_t gpio_unexportPin(char* pin) { - int len = strlen(pin); - return ioutil_writeToFile("/sys/class/gpio/unexport", &pin, sizeof(char), - len); -} - -void getGpioPath(char* outputStr, char* pin, char* subDir) { - sprintf(outputStr, "/sys/class/gpio/gpio%s/%s", pin, subDir); -} - -le_result_t gpio_setDirection(char* pin, char* direction) { - char path[100]; - getGpioPath(path, pin, "direction"); - return ioutil_writeToFile(path, direction, sizeof(char), strlen(direction)); -} - -le_result_t gpio_setPull(char* pin, char* pull) { - char path[100]; - getGpioPath(path, pin, "pull"); - return ioutil_writeToFile(path, pull, sizeof(char), strlen(pull)); -} - -le_result_t gpio_pullDown(char* pin) { - return gpio_setPull(pin, "down"); -} - -le_result_t gpio_pullUp(char* pin) { - return gpio_setPull(pin, "up"); -} - -le_result_t gpio_setInput(char* pin) { - return gpio_setDirection(pin, "in"); -} - -le_result_t gpio_setOutput(char* pin) { - return gpio_setDirection(pin, "out"); -} - -le_result_t gpio_setActiveState(char* pin, bool isActiveLow) { - // Any non zero value toggles the existing value - // so we must read the existing value first - char path[100]; - int isActiveLowSet; - getGpioPath(path, pin, "active_low"); - le_result_t readRes = ioutil_readIntFromFile(path, &isActiveLowSet); - le_result_t writeRes = LE_OK; - if (isActiveLow != isActiveLowSet) { - writeRes = ioutil_writeToFile(path, "1", sizeof(char), 1); - } - return readRes == LE_OK && writeRes == LE_OK ? LE_OK : LE_FAULT; -} - -le_result_t gpio_isActive(char* pin, bool* isActive) { - char path[50]; - getGpioPath(path, pin, "value"); - int val; - le_result_t readRes = ioutil_readIntFromFile(path, &val); - *isActive = val; - return readRes; -} - -le_result_t gpio_setValue(char* pin, bool state) { - char path[50]; - getGpioPath(path, pin, "value"); - char* strState = state ? "1" : "0"; - return ioutil_writeToFile(path, &strState, sizeof(char), strlen(strState)); -} - -le_result_t gpio_setLow(char* pin) { - return gpio_setValue(pin, LOW); -} - -le_result_t gpio_setHigh(char* pin) { - return gpio_setValue(pin, HIGH); -} - -void* util_find(Functional* f) { - f->args.i = 0; - while (f->args.i < f->n) { - if (f->callback(&f->args)) { - return f->derefCallback(f->args.i, f->args.arr); - } - f->args.i++; - } - return NULL; -} - -void util_listDir(const char* dir, char* dest, size_t size) { - struct dirent* de; - char toConcat[1024]; - DIR* dr = opendir(dir); - if (dr == NULL) - return; - while ((de = readdir(dr)) != NULL) { - if (de->d_name[0] != '.') { - snprintf(toConcat, size, "%s,", de->d_name); - strncat(dest, toConcat, size); - } - } - closedir(dr); -} - -/** - * Convert an integer baud rate to a speed_t - */ -speed_t fd_convertBaud(int baud) { - speed_t b; - switch (baud) { - case 50: - b = B50; - break; - case 75: - b = B75; - break; - case 110: - b = B110; - break; - case 134: - b = B134; - break; - case 150: - b = B150; - break; - case 200: - b = B200; - break; - case 300: - b = B300; - break; - case 600: - b = B600; - break; - case 1200: - b = B1200; - break; - case 1800: - b = B1800; - break; - case 2400: - b = B2400; - break; - case 9600: - b = B9600; - break; - case 19200: - b = B19200; - break; - case 38400: - b = B38400; - break; - case 57600: - b = B57600; - break; - case 115200: - b = B115200; - break; - case 230400: - b = B230400; - break; - case 921600: - b = B921600; - break; - default: - b = -2; - } - return b; -} - -/** - * Open a serial connection on device - * - * Lifted from here - * https://github.com/WiringPi/WiringPi/blob/master/wiringPi/wiringSerial.c - */ -int fd_openSerial(const char* device, int baud) { - struct termios options; - speed_t binaryBaud = fd_convertBaud(baud); - int status, fd; - if ((fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK)) == -1) - return -1; - fcntl(fd, F_SETFL, O_RDWR); - tcgetattr(fd, &options); - cfmakeraw(&options); - cfsetispeed(&options, binaryBaud); - cfsetospeed(&options, binaryBaud); - - options.c_cflag |= (CLOCAL | CREAD); - options.c_cflag &= ~PARENB; - options.c_cflag &= ~CSTOPB; - options.c_cflag &= ~CSIZE; - options.c_cflag |= CS8; - options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); - options.c_oflag &= ~OPOST; - - options.c_cc[VMIN] = 0; - options.c_cc[VTIME] = 10; // Ten seconds (100 deciseconds) - - tcsetattr(fd, TCSANOW | TCSAFLUSH, &options); - - ioctl(fd, TIOCMGET, &status); - - status |= TIOCM_DTR; - status |= TIOCM_RTS; - - ioctl(fd, TIOCMSET, &status); - usleep(10000); // 10mS - return fd; -} - -int fd_puts(const int fd, const char* s) { - return write(fd, s, strlen(s)); -} - -int fd_getChar(const int fd) { - uint8_t x; - - if (read(fd, &x, 1) != 1) - return -1; - - return ((int)x) & 0xFF; -} - -void fd_flush(const int fd) { - // tcflush(fd, TCIOFLUSH); - tcdrain(fd); -} - -void fd_flushInput(const int fd) { - tcflush(fd, TCIFLUSH); -} - -int fd_dataAvail(int fd, int* data) { - return ioctl(fd, FIONREAD, data); -} - -double util_avgDouble(double* readings, int nReadings) { - double sum = 0; - for (int i = 0; i < nReadings; i++) { - sum += readings[i]; - } - - return sum / nReadings; -} diff --git a/util/util.h b/util/util.h deleted file mode 100644 index 06ef2fb..0000000 --- a/util/util.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef UTIL_H -#define UTIL_H - -#include "legato.h" -#include - -#define HIGH 1 -#define LOW 0 - -typedef struct { - int i; - void* arr; - void* ctxp; -} FunctionalArgs; - -typedef struct { - int n; // number of elements in array - bool (*callback)(FunctionalArgs* args); // callback applied to arr[i] - void* (*derefCallback)(int i, void* j); // callback used to deference arr[i] - FunctionalArgs args; -} Functional; - -// ioutil -le_result_t readFromFile(const char* path, - void* value, - int (*scanCallback)(FILE* f, void* val)); -int scanDoubleCallback(FILE* f, void* value); -le_result_t ioutil_readIntFromFile(const char* path, int* value); -le_result_t ioutil_readDoubleFromFile(const char* filePath, double* value); -le_result_t ioutil_writeToFile(const char* path, - void* value, - size_t size, - size_t count); - -le_result_t ioutil_appendToFile(const char* path, - void* value, - size_t size, - size_t count); - -// TODO fix this name (no PascalCase) -uint64_t GetCurrentTimestamp(void); -time_t util_getMTime(char* path); -int util_getUnixDatetime(); -le_result_t util_flattenRes(le_result_t* res, int nRes); -bool util_fileExists(const char* path); -bool util_alreadyMounted(const char* devPath); -double util_avgDouble(double* readings, int nReadings); - -// TODO verify this is working -le_result_t gpio_exportPin(char* pin); -le_result_t gpio_unexportPin(char* pin); -void getGpioPath(char* outputStr, char* pin, char* subDir); -le_result_t gpio_setDirection(char* pin, char* direction); -le_result_t gpio_setInput(char* pin); -le_result_t gpio_setOutput(char* pin); -le_result_t gpio_setActiveState(char* pin, bool isActiveLow); -le_result_t gpio_isActive(char* pin, bool* isActive); -le_result_t gpio_setValue(char* pin, bool state); -le_result_t gpio_setLow(char* pin); -le_result_t gpio_setHigh(char* pin); -le_result_t gpio_setPull(char* pin, char* pull); -le_result_t gpio_pullDown(char* pin); -le_result_t gpio_pullUp(char* pin); - -void* util_find(Functional* f); - -void util_listDir(const char* dir, char* dest, size_t size); - -int fd_openSerial(const char* device, int baud); -speed_t fd_convertBaud(int baud); -int fd_puts(const int fd, const char* s); -int fd_getChar(const int fd); -void fd_flush(const int fd); -int fd_dataAvail(int fd, int* data); -void fd_flushInput(const int fd); - -#endif -- cgit v1.2.3 From 583f64ae92ff64816e84c5160088b004540ed2b5 Mon Sep 17 00:00:00 2001 From: dragonprevost Date: Tue, 13 Nov 2018 15:03:07 -0800 Subject: added brnkl-util submodule --- .gitmodules | 3 +++ brnkl-util | 1 + 2 files changed, 4 insertions(+) create mode 160000 brnkl-util diff --git a/.gitmodules b/.gitmodules index e69de29..4359c25 100644 --- a/.gitmodules +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "brnkl-util"] + path = brnkl-util + url = https://github.com/brnkl/brnkl-util.git diff --git a/brnkl-util b/brnkl-util new file mode 160000 index 0000000..40b51b2 --- /dev/null +++ b/brnkl-util @@ -0,0 +1 @@ +Subproject commit 40b51b270579af9772190ed9681438416a62ce75 -- cgit v1.2.3 From 3175a3d7a672169f41916bb1364150a1df5d2f5c Mon Sep 17 00:00:00 2001 From: dragonprevost Date: Tue, 13 Nov 2018 15:49:06 -0800 Subject: Configured Componenet.cdef for submoduled util --- motionMonitor/Component.cdef | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/motionMonitor/Component.cdef b/motionMonitor/Component.cdef index 9627adf..2b48eb5 100644 --- a/motionMonitor/Component.cdef +++ b/motionMonitor/Component.cdef @@ -1,7 +1,7 @@ cflags: { -std=c99 - -I$BRNKL_ROOT/apps/util + -I$CURDIR/../brnkl-util } requires: @@ -23,5 +23,5 @@ provides: sources: { motionMonitor.c - $BRNKL_ROOT/apps/util/util.c + $CURDIR/../brnkl-util/util.c } -- cgit v1.2.3 From 3502be51ab41acce71bbf844016dee480e527e82 Mon Sep 17 00:00:00 2001 From: dragonprevost Date: Tue, 13 Nov 2018 15:51:17 -0800 Subject: update clean in makefile --- Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 84cd21e..d15a379 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,6 @@ wp85: mkapp -t wp85 motionService.adef -b clean: - rm -r _build_* + rm -r _build_* \ + *.update \ + *.app -- cgit v1.2.3 From 700032615ecbeb3aef2ade0a7990b3abbcdc6cb7 Mon Sep 17 00:00:00 2001 From: dragonprevost Date: Tue, 13 Nov 2018 16:06:23 -0800 Subject: removed util submodule --- .gitmodules | 3 --- brnkl-util | 1 - 2 files changed, 4 deletions(-) delete mode 160000 brnkl-util diff --git a/.gitmodules b/.gitmodules index 4359c25..e69de29 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +0,0 @@ -[submodule "brnkl-util"] - path = brnkl-util - url = https://github.com/brnkl/brnkl-util.git diff --git a/brnkl-util b/brnkl-util deleted file mode 160000 index 40b51b2..0000000 --- a/brnkl-util +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 40b51b270579af9772190ed9681438416a62ce75 -- cgit v1.2.3 From 98d4719824f3cc2ed99f855bbdada129784245bf Mon Sep 17 00:00:00 2001 From: dragonprevost Date: Tue, 13 Nov 2018 16:06:47 -0800 Subject: added util to new folder --- util/util.c | 366 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ util/util.h | 77 +++++++++++++ 2 files changed, 443 insertions(+) create mode 100644 util/util.c create mode 100644 util/util.h diff --git a/util/util.c b/util/util.c new file mode 100644 index 0000000..3042c22 --- /dev/null +++ b/util/util.c @@ -0,0 +1,366 @@ +#include "util.h" +#include "legato.h" +#include + +le_result_t readFromFile(const char* path, + void* value, + int (*scanCallback)(FILE* f, void* val)) { + FILE* f = fopen(path, "r"); + if (f == NULL) { + LE_WARN("Couldn't open '%s' - %m", path); + return LE_IO_ERROR; + } + int numScanned = scanCallback(f, value); + if (numScanned != 1) + return LE_FORMAT_ERROR; + fclose(f); + return LE_OK; +} + +int scanIntCallback(FILE* f, void* value) { + int* val = value; + return fscanf(f, "%d", val); +} + +int scanDoubleCallback(FILE* f, void* value) { + double* val = value; + return fscanf(f, "%lf", val); +} + +le_result_t ioutil_readIntFromFile(const char* path, int* value) { + return readFromFile(path, value, scanIntCallback); +} + +le_result_t ioutil_readDoubleFromFile(const char* path, double* value) { + return readFromFile(path, value, scanDoubleCallback); +} + +le_result_t writeToFile(const char* path, + void* value, + size_t size, + size_t count, + const char* openMode) { + FILE* f = fopen(path, openMode); + if (f == NULL) { + LE_WARN("Failed to open %s for writing", path); + return LE_IO_ERROR; + } + fwrite(value, size, count, f); + fflush(f); + fclose(f); + return LE_OK; +} + +le_result_t ioutil_writeToFile(const char* path, + void* value, + size_t size, + size_t count) { + return writeToFile(path, value, size, count, "w"); +} + +le_result_t ioutil_appendToFile(const char* path, + void* value, + size_t size, + size_t count) { + return writeToFile(path, value, size, count, "a"); +} + +le_result_t util_flattenRes(le_result_t* res, int nRes) { + for (int i = 0; i < nRes; i++) { + if (res[i] != LE_OK) + return res[i]; + } + return LE_OK; +} + +int util_getUnixDatetime() { + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec; +} + +/** + * Get the last modified datetime + * of the file at path + */ +time_t util_getMTime(char* path) { + struct stat st; + if (stat(path, &st) != 0) + return -1; + else + return st.st_mtime; +} + +bool util_fileExists(const char* path) { + struct stat st; + return stat(path, &st) == 0; +} + +bool util_alreadyMounted(const char* devPath) { + char content[2048]; + FILE* f = fopen("/proc/mounts", "r"); + if (f == NULL) { + return false; + } + fread(content, sizeof(char), sizeof(content), f); + // if this ref is non-null, we found a match + return strstr(content, devPath) != NULL; +} + +uint64_t GetCurrentTimestamp(void) { + struct timeval tv; + gettimeofday(&tv, NULL); + uint64_t utcMilliSec = + (uint64_t)(tv.tv_sec) * 1000 + (uint64_t)(tv.tv_usec) / 1000; + return utcMilliSec; +} + +// TODO verify this is working +le_result_t gpio_exportPin(char* pin) { + int len = strlen(pin); + return ioutil_writeToFile("/sys/class/gpio/export", &pin, sizeof(char), len); +} + +le_result_t gpio_unexportPin(char* pin) { + int len = strlen(pin); + return ioutil_writeToFile("/sys/class/gpio/unexport", &pin, sizeof(char), + len); +} + +void getGpioPath(char* outputStr, char* pin, char* subDir) { + sprintf(outputStr, "/sys/class/gpio/gpio%s/%s", pin, subDir); +} + +le_result_t gpio_setDirection(char* pin, char* direction) { + char path[100]; + getGpioPath(path, pin, "direction"); + return ioutil_writeToFile(path, direction, sizeof(char), strlen(direction)); +} + +le_result_t gpio_setPull(char* pin, char* pull) { + char path[100]; + getGpioPath(path, pin, "pull"); + return ioutil_writeToFile(path, pull, sizeof(char), strlen(pull)); +} + +le_result_t gpio_pullDown(char* pin) { + return gpio_setPull(pin, "down"); +} + +le_result_t gpio_pullUp(char* pin) { + return gpio_setPull(pin, "up"); +} + +le_result_t gpio_setInput(char* pin) { + return gpio_setDirection(pin, "in"); +} + +le_result_t gpio_setOutput(char* pin) { + return gpio_setDirection(pin, "out"); +} + +le_result_t gpio_setActiveState(char* pin, bool isActiveLow) { + // Any non zero value toggles the existing value + // so we must read the existing value first + char path[100]; + int isActiveLowSet; + getGpioPath(path, pin, "active_low"); + le_result_t readRes = ioutil_readIntFromFile(path, &isActiveLowSet); + le_result_t writeRes = LE_OK; + if (isActiveLow != isActiveLowSet) { + writeRes = ioutil_writeToFile(path, "1", sizeof(char), 1); + } + return readRes == LE_OK && writeRes == LE_OK ? LE_OK : LE_FAULT; +} + +le_result_t gpio_isActive(char* pin, bool* isActive) { + char path[50]; + getGpioPath(path, pin, "value"); + int val; + le_result_t readRes = ioutil_readIntFromFile(path, &val); + *isActive = val; + return readRes; +} + +le_result_t gpio_setValue(char* pin, bool state) { + char path[50]; + getGpioPath(path, pin, "value"); + char* strState = state ? "1" : "0"; + return ioutil_writeToFile(path, &strState, sizeof(char), strlen(strState)); +} + +le_result_t gpio_setLow(char* pin) { + return gpio_setValue(pin, LOW); +} + +le_result_t gpio_setHigh(char* pin) { + return gpio_setValue(pin, HIGH); +} + +void* util_find(Functional* f) { + f->args.i = 0; + while (f->args.i < f->n) { + if (f->callback(&f->args)) { + return f->derefCallback(f->args.i, f->args.arr); + } + f->args.i++; + } + return NULL; +} + +void util_listDir(const char* dir, char* dest, size_t size) { + struct dirent* de; + char toConcat[1024]; + DIR* dr = opendir(dir); + if (dr == NULL) + return; + while ((de = readdir(dr)) != NULL) { + if (de->d_name[0] != '.') { + snprintf(toConcat, size, "%s,", de->d_name); + strncat(dest, toConcat, size); + } + } + closedir(dr); +} + +/** + * Convert an integer baud rate to a speed_t + */ +speed_t fd_convertBaud(int baud) { + speed_t b; + switch (baud) { + case 50: + b = B50; + break; + case 75: + b = B75; + break; + case 110: + b = B110; + break; + case 134: + b = B134; + break; + case 150: + b = B150; + break; + case 200: + b = B200; + break; + case 300: + b = B300; + break; + case 600: + b = B600; + break; + case 1200: + b = B1200; + break; + case 1800: + b = B1800; + break; + case 2400: + b = B2400; + break; + case 9600: + b = B9600; + break; + case 19200: + b = B19200; + break; + case 38400: + b = B38400; + break; + case 57600: + b = B57600; + break; + case 115200: + b = B115200; + break; + case 230400: + b = B230400; + break; + case 921600: + b = B921600; + break; + default: + b = -2; + } + return b; +} + +/** + * Open a serial connection on device + * + * Lifted from here + * https://github.com/WiringPi/WiringPi/blob/master/wiringPi/wiringSerial.c + */ +int fd_openSerial(const char* device, int baud) { + struct termios options; + speed_t binaryBaud = fd_convertBaud(baud); + int status, fd; + if ((fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK)) == -1) + return -1; + fcntl(fd, F_SETFL, O_RDWR); + tcgetattr(fd, &options); + cfmakeraw(&options); + cfsetispeed(&options, binaryBaud); + cfsetospeed(&options, binaryBaud); + + options.c_cflag |= (CLOCAL | CREAD); + options.c_cflag &= ~PARENB; + options.c_cflag &= ~CSTOPB; + options.c_cflag &= ~CSIZE; + options.c_cflag |= CS8; + options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); + options.c_oflag &= ~OPOST; + + options.c_cc[VMIN] = 0; + options.c_cc[VTIME] = 10; // Ten seconds (100 deciseconds) + + tcsetattr(fd, TCSANOW | TCSAFLUSH, &options); + + ioctl(fd, TIOCMGET, &status); + + status |= TIOCM_DTR; + status |= TIOCM_RTS; + + ioctl(fd, TIOCMSET, &status); + usleep(10000); // 10mS + return fd; +} + +int fd_puts(const int fd, const char* s) { + return write(fd, s, strlen(s)); +} + +int fd_getChar(const int fd) { + uint8_t x; + + if (read(fd, &x, 1) != 1) + return -1; + + return ((int)x) & 0xFF; +} + +void fd_flush(const int fd) { + // tcflush(fd, TCIOFLUSH); + tcdrain(fd); +} + +void fd_flushInput(const int fd) { + tcflush(fd, TCIFLUSH); +} + +int fd_dataAvail(int fd, int* data) { + return ioctl(fd, FIONREAD, data); +} + +double util_avgDouble(double* readings, int nReadings) { + double sum = 0; + for (int i = 0; i < nReadings; i++) { + sum += readings[i]; + } + + return sum / nReadings; +} diff --git a/util/util.h b/util/util.h new file mode 100644 index 0000000..06ef2fb --- /dev/null +++ b/util/util.h @@ -0,0 +1,77 @@ +#ifndef UTIL_H +#define UTIL_H + +#include "legato.h" +#include + +#define HIGH 1 +#define LOW 0 + +typedef struct { + int i; + void* arr; + void* ctxp; +} FunctionalArgs; + +typedef struct { + int n; // number of elements in array + bool (*callback)(FunctionalArgs* args); // callback applied to arr[i] + void* (*derefCallback)(int i, void* j); // callback used to deference arr[i] + FunctionalArgs args; +} Functional; + +// ioutil +le_result_t readFromFile(const char* path, + void* value, + int (*scanCallback)(FILE* f, void* val)); +int scanDoubleCallback(FILE* f, void* value); +le_result_t ioutil_readIntFromFile(const char* path, int* value); +le_result_t ioutil_readDoubleFromFile(const char* filePath, double* value); +le_result_t ioutil_writeToFile(const char* path, + void* value, + size_t size, + size_t count); + +le_result_t ioutil_appendToFile(const char* path, + void* value, + size_t size, + size_t count); + +// TODO fix this name (no PascalCase) +uint64_t GetCurrentTimestamp(void); +time_t util_getMTime(char* path); +int util_getUnixDatetime(); +le_result_t util_flattenRes(le_result_t* res, int nRes); +bool util_fileExists(const char* path); +bool util_alreadyMounted(const char* devPath); +double util_avgDouble(double* readings, int nReadings); + +// TODO verify this is working +le_result_t gpio_exportPin(char* pin); +le_result_t gpio_unexportPin(char* pin); +void getGpioPath(char* outputStr, char* pin, char* subDir); +le_result_t gpio_setDirection(char* pin, char* direction); +le_result_t gpio_setInput(char* pin); +le_result_t gpio_setOutput(char* pin); +le_result_t gpio_setActiveState(char* pin, bool isActiveLow); +le_result_t gpio_isActive(char* pin, bool* isActive); +le_result_t gpio_setValue(char* pin, bool state); +le_result_t gpio_setLow(char* pin); +le_result_t gpio_setHigh(char* pin); +le_result_t gpio_setPull(char* pin, char* pull); +le_result_t gpio_pullDown(char* pin); +le_result_t gpio_pullUp(char* pin); + +void* util_find(Functional* f); + +void util_listDir(const char* dir, char* dest, size_t size); + +int fd_openSerial(const char* device, int baud); +speed_t fd_convertBaud(int baud); +int fd_puts(const int fd, const char* s); +int fd_getChar(const int fd); +void fd_flush(const int fd); +int fd_dataAvail(int fd, int* data); +void fd_flushInput(const int fd); + +#endif -- cgit v1.2.3 From eb1ef7ea452002e441034416de9a23c93ee2f627 Mon Sep 17 00:00:00 2001 From: dragonprevost Date: Tue, 13 Nov 2018 16:08:14 -0800 Subject: adjusted Component.cdef for new util folder --- motionMonitor/Component.cdef | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/motionMonitor/Component.cdef b/motionMonitor/Component.cdef index 2b48eb5..ea17866 100644 --- a/motionMonitor/Component.cdef +++ b/motionMonitor/Component.cdef @@ -1,7 +1,7 @@ cflags: { -std=c99 - -I$CURDIR/../brnkl-util + -I$CURDIR/../util } requires: @@ -23,5 +23,5 @@ provides: sources: { motionMonitor.c - $CURDIR/../brnkl-util/util.c + $CURDIR/../util/util.c } -- cgit v1.2.3 From 86b44a139649d1bc63f69dde18f27abcacb94177 Mon Sep 17 00:00:00 2001 From: dragonprevost Date: Tue, 13 Nov 2018 16:11:27 -0800 Subject: fixed submodule in readme clone --- readme.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/readme.md b/readme.md index 2b5a6a2..64b1b05 100644 --- a/readme.md +++ b/readme.md @@ -4,8 +4,7 @@ This application is designed to operate on a [MongOH Red](https://mangoh.io/mang ## Prerequisites -When cloning use ``git clone --recurse-submodule https://github.com/brnkl/motion-service.git`` -to include the util module. +When cloning use ``git clone https://github.com/brnkl/motion-service.git``. ## Building -- cgit v1.2.3 From caf251e70652039b5f64eb9a3b594674f1da5646 Mon Sep 17 00:00:00 2001 From: dragonprevost Date: Tue, 13 Nov 2018 19:38:14 -0800 Subject: added rough example to readme --- readme.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/readme.md b/readme.md index 64b1b05..08eac0b 100644 --- a/readme.md +++ b/readme.md @@ -48,6 +48,32 @@ requires: ## Example +For getting a list of impact information you may follow this example. +``` +double x_arr [array_size]; +double y_arr [array_size]; +double z_arr [array_size]; +uint64 timestamps[array_size]; + +// Fills arrays with x, y, and z acceleration that have been recorded at each impact. + +le_result_t result = getSuddenImpact(x_arr, y_arr, z_arr, timestamps); + +for (int i = 0; i < array_size; i++) + LE_INFO("X: %d - Y: %d - Z: %d - time: %ul", x_arr[i], + y_arr[i], + z_arr[i], + timestamps[i]); +``` +For receiving the current acceleration only + +``` +double x_val; +double y_val; +double z_val; +le_result_t result = getCurrentAcceleration(x_val, y_val, z_val); +LE_INFO("Current Acceleration: X: %d - Y: %d - Z: %d"); +``` -- cgit v1.2.3 From 7ba91139470e24608d255ec0156444e26133d935 Mon Sep 17 00:00:00 2001 From: dragonprevost Date: Tue, 13 Nov 2018 19:40:11 -0800 Subject: gramard check in readme --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 08eac0b..62b7a4e 100644 --- a/readme.md +++ b/readme.md @@ -47,7 +47,7 @@ requires: ``` -## Example +## Examples For getting a list of impact information you may follow this example. ``` double x_arr [array_size]; -- cgit v1.2.3 From 27dec638c20271b1b8aff084385d11e74bad39c8 Mon Sep 17 00:00:00 2001 From: dragonprevost Date: Thu, 15 Nov 2018 12:24:59 -0800 Subject: added examples to readme --- readme.md | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/readme.md b/readme.md index 2b48970..83dc5a5 100644 --- a/readme.md +++ b/readme.md @@ -46,5 +46,38 @@ requires: ``` ## Example +For getting the current acceleration +``` +struct Acceleration{ + double x; + double y; + double z; +}; + +struct Acceleration v = value; +le_result_t result = brnkl_motion_getCurrentAccleration(&v->x, &v->y, &v->z); +``` +To get a list of all recent impacts. +``` +double xAcc[N_MAX_IMPACT_VALUES], yAcc[N_MAX_IMPACT_VALUES], zAcc[N_MAX_IMPACT_VALUES]; + uint64_t timestamps[N_MAX_IMPACT_VALUES]; + size_t xSize = N_MAX_IMPACT_VALUES, ySize = N_MAX_IMPACT_VALUES, + zSize = N_MAX_IMPACT_VALUES, timestampsSize = N_MAX_IMPACT_VALUES; + le_result_t r = brnkl_motion_getSuddenImpact( + xAcc, &xSize, yAcc, &ySize, zAcc, &zSize, timestamps, ×tampsSize); + if (r != LE_OK) + return r; + // NOTE this assumes that xSize == ySize == zSize == timestampsSize + // TODO could even assert/log this + int j = 0; + for (int i = 0; i < xSize; i++) { + recordRes[j++] = + le_avdata_RecordFloat(ref, "impactx", xAcc[i], timestamps[i]); + recordRes[j++] = + le_avdata_RecordFloat(ref, "impacty", yAcc[i], timestamps[i]); + recordRes[j++] = + le_avdata_RecordFloat(ref, "impactz", zAcc[i], timestamps[i]); + } +``` -- cgit v1.2.3 From 241513bec363481319dd71b6ad3d2040d0c00f8b Mon Sep 17 00:00:00 2001 From: dragonprevost Date: Thu, 15 Nov 2018 12:45:32 -0800 Subject: fixed readme formatting --- readme.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/readme.md b/readme.md index c102175..d5e6942 100644 --- a/readme.md +++ b/readme.md @@ -82,7 +82,7 @@ double xAcc[N_MAX_IMPACT_VALUES], yAcc[N_MAX_IMPACT_VALUES], zAcc[N_MAX_IMPACT_V recordRes[j++] = le_avdata_RecordFloat(ref, "impactz", zAcc[i], timestamps[i]); } -======= +``` ## Examples For getting a list of impact information you may follow this example. @@ -113,5 +113,4 @@ le_result_t result = getCurrentAcceleration(x_val, y_val, z_val); LE_INFO("Current Acceleration: X: %d - Y: %d - Z: %d"); ->>>>>>> 7ba91139470e24608d255ec0156444e26133d935 ``` -- cgit v1.2.3 From f595007692362b15bb8bfdac6ae073a56f3709a0 Mon Sep 17 00:00:00 2001 From: dragonprevost Date: Thu, 15 Nov 2018 12:47:57 -0800 Subject: adjusted example for returning list of impacts --- readme.md | 49 +++++-------------------------------------------- 1 file changed, 5 insertions(+), 44 deletions(-) diff --git a/readme.md b/readme.md index d5e6942..1075fd1 100644 --- a/readme.md +++ b/readme.md @@ -63,54 +63,15 @@ le_result_t result = brnkl_motion_getCurrentAccleration(&v->x, &v->y, &v->z); To get a list of all recent impacts. ``` -double xAcc[N_MAX_IMPACT_VALUES], yAcc[N_MAX_IMPACT_VALUES], zAcc[N_MAX_IMPACT_VALUES]; + double xAcc[N_MAX_IMPACT_VALUES], yAcc[N_MAX_IMPACT_VALUES], zAcc[N_MAX_IMPACT_VALUES]; + uint64_t timestamps[N_MAX_IMPACT_VALUES]; + size_t xSize = N_MAX_IMPACT_VALUES, ySize = N_MAX_IMPACT_VALUES, zSize = N_MAX_IMPACT_VALUES, timestampsSize = N_MAX_IMPACT_VALUES; + le_result_t r = brnkl_motion_getSuddenImpact( xAcc, &xSize, yAcc, &ySize, zAcc, &zSize, timestamps, ×tampsSize); - if (r != LE_OK) - return r; - // NOTE this assumes that xSize == ySize == zSize == timestampsSize - // TODO could even assert/log this - int j = 0; - for (int i = 0; i < xSize; i++) { - recordRes[j++] = - le_avdata_RecordFloat(ref, "impactx", xAcc[i], timestamps[i]); - recordRes[j++] = - le_avdata_RecordFloat(ref, "impacty", yAcc[i], timestamps[i]); - recordRes[j++] = - le_avdata_RecordFloat(ref, "impactz", zAcc[i], timestamps[i]); - } -``` - -## Examples -For getting a list of impact information you may follow this example. -``` -double x_arr [array_size]; -double y_arr [array_size]; -double z_arr [array_size]; -uint64 timestamps[array_size]; - -// Fills arrays with x, y, and z acceleration that have been recorded at each impact. - -le_result_t result = getSuddenImpact(x_arr, y_arr, z_arr, timestamps); - -for (int i = 0; i < array_size; i++) - LE_INFO("X: %d - Y: %d - Z: %d - time: %ul", x_arr[i], - y_arr[i], - z_arr[i], - timestamps[i]); -``` -For receiving the current acceleration only - + ``` -double x_val; -double y_val; -double z_val; -le_result_t result = getCurrentAcceleration(x_val, y_val, z_val); - -LE_INFO("Current Acceleration: X: %d - Y: %d - Z: %d"); - -``` -- cgit v1.2.3 From 0de7d02a3d9293253f27b1f868db5789ec932fd9 Mon Sep 17 00:00:00 2001 From: Nicholas Van Doorn Date: Thu, 15 Nov 2018 13:09:19 -0800 Subject: Update readme.md Co-Authored-By: dragonprevost --- readme.md | 1 - 1 file changed, 1 deletion(-) diff --git a/readme.md b/readme.md index 1075fd1..d9f83da 100644 --- a/readme.md +++ b/readme.md @@ -46,7 +46,6 @@ requires: ... ``` -<<<<<<< HEAD ## Example For getting the current acceleration ``` -- cgit v1.2.3 From 4e379259292be2709834ee0d75e212f80b14e1b0 Mon Sep 17 00:00:00 2001 From: Nicholas Van Doorn Date: Thu, 15 Nov 2018 13:09:33 -0800 Subject: Update readme.md Co-Authored-By: dragonprevost --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index d9f83da..3aa0175 100644 --- a/readme.md +++ b/readme.md @@ -48,7 +48,7 @@ requires: ## Example For getting the current acceleration -``` +```C struct Acceleration{ double x; double y; -- cgit v1.2.3