diff options
| -rw-r--r-- | .gitmodules | 0 | ||||
| -rw-r--r-- | Makefile | 6 | ||||
| -rw-r--r-- | motionMonitor/Component.cdef | 4 | ||||
| -rw-r--r-- | readme.md | 76 | ||||
| -rw-r--r-- | util/util.c | 366 | ||||
| -rw-r--r-- | util/util.h | 77 | 
6 files changed, 527 insertions, 2 deletions
| diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/.gitmodules diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..d15a379 --- /dev/null +++ b/Makefile @@ -0,0 +1,6 @@ +wp85: +	mkapp -t wp85 motionService.adef -b +clean: +	rm -r _build_* \ +	 *.update \ +	 *.app diff --git a/motionMonitor/Component.cdef b/motionMonitor/Component.cdef index 9627adf..ea17866 100644 --- a/motionMonitor/Component.cdef +++ b/motionMonitor/Component.cdef @@ -1,7 +1,7 @@  cflags:  {    -std=c99 -  -I$BRNKL_ROOT/apps/util +  -I$CURDIR/../util  }  requires: @@ -23,5 +23,5 @@ provides:  sources:  {    motionMonitor.c -  $BRNKL_ROOT/apps/util/util.c +  $CURDIR/../util/util.c  } @@ -0,0 +1,76 @@ +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 + +When cloning use ``git clone https://github.com/brnkl/motion-service.git``. + + +## Building +Compile the project using  + +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);``. As visualized in the image below. + + + + +`#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. + +## Bindings  +App.adef +``` +... +bindings: +{ +  myClientApp.myComponent.brnkl_motion -> motionService.brnkl_motion +} +... +``` +Component.cdef +``` +... +requires: +{ +  api: +  { +    brnkl_motion.api +  } +} +... +``` + +## Example  +For getting the current acceleration +```C +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); +   +``` + 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 <termios.h> + +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 <termios.h> + +#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 | 
