Files @ 755225bf1731
Branch filter:

Location: protofusion-esp32-template/components/esp-osc/esp_osc.c - annotation

Ethan Zonca
Add discovery message TX. Add unused nonvolatile flash saving.
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
48d2337d76c2
755225bf1731
48d2337d76c2
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
33512a8a338c
#include <stdio.h>
#include <stdarg.h>
#include <esp_log.h>
#include "esp_osc.h"

#define TAG "esp-osc"

bool esp_osc_init(esp_osc_client_t *client, uint16_t buf_len, uint16_t port) {
  // free existing memory
  if (client->sbuf != NULL) {
    free(client->sbuf);
  }
  if (client->rbuf != NULL) {
    free(client->rbuf);
  }

  // allocate memory
  client->sbuf = malloc(buf_len);
  client->rbuf = malloc(buf_len);
  client->len = buf_len;

  // close existing socket
  if (client->socket != 0) {
    close(client->socket);
    client->socket = 0;
  }

  // create socket
  client->socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
  if (client->socket <= 0) {
    ESP_LOGE(TAG, "failed to create socket (%d)", errno);
    client->socket = 0;
    return false;
  }

  // bind socket if port is available
  if (port > 0) {
    struct sockaddr_in addr = {0};
    addr.sin_addr.s_addr = inet_addr("0.0.0.0");
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    if (bind(client->socket, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
      ESP_LOGE(TAG, "failed to bind socket (%d)", errno);
      return false;
    }
  }

  return true;
}

esp_osc_target_t esp_osc_target(const char *address, uint16_t port) {
  // prepare target
  esp_osc_target_t target = {0};
  target.addr.sin_addr.s_addr = inet_addr(address);
  target.addr.sin_family = AF_INET;
  target.addr.sin_port = htons(port);

  return target;
}

bool esp_osc_send(esp_osc_client_t *client, esp_osc_target_t *target, const char *topic, const char *format, ...) {
  // send message
  va_list args;
  va_start(args, format);
  bool ret = esp_osc_send_v(client, target, topic, format, args);
  va_end(args);

  return ret;
}

bool esp_osc_send_v(esp_osc_client_t *client, esp_osc_target_t *target, const char *topic, const char *format,
                    va_list args) {
  // prepare message
  uint32_t length = tosc_vwrite((char *)client->sbuf, client->len, topic, format, args);

  // send message
  if (sendto(client->socket, client->sbuf, length, 0, (struct sockaddr *)&target->addr, sizeof(target->addr)) < 0) {
    ESP_LOGE(TAG, "failed to send message (%d)", errno);
    return false;
  }
  else{
    // ESP_LOGI(TAG, "sent message OK");
  }

  return true;
}

bool esp_osc_receive(esp_osc_client_t *client, esp_osc_callback_t callback) {
  // prepare values
  esp_osc_value_t values[32];

  for (;;) {
    // receive message
    ssize_t ret = recvfrom(client->socket, client->rbuf, client->len, 0, NULL, NULL);
    if (ret < 0) {
      ESP_LOGE(TAG, "failed to receive message (%d)", errno);
      return false;
    } else if (ret > client->len) {
      ESP_LOGE(TAG, "discard too long message (%d)", ret);
      return false;
    }

    // check bundle
    if (tosc_isBundle(client->rbuf)) {
      ESP_LOGE(TAG, "discard unsupported bundle");
      return false;
    }

    // parse message
    tosc_message msg = {0};
    int res = tosc_parseMessage(&msg, client->rbuf, client->len);
    if (res < 0) {
      ESP_LOGE(TAG, "failed to parse message (%d)", res);
      return false;
    }

    // get format
    char *fmt = tosc_getFormat(&msg);

    // get size
    size_t size = strlen(fmt);
    if (size > sizeof(values)) {
      ESP_LOGE(TAG, "message has too many values (%d)", size);
      return false;
    }

    // parse values
    for (size_t i = 0; i < size; i++) {
      switch (fmt[i]) {
        case 'i':
          values[i].i = tosc_getNextInt32(&msg);
          break;
        case 'h':
          values[i].h = tosc_getNextInt64(&msg);
          break;
        case 'f':
          values[i].f = tosc_getNextFloat(&msg);
          break;
        case 'd':
          values[i].d = tosc_getNextDouble(&msg);
          break;
        case 's':
          values[i].s = tosc_getNextString(&msg);
          break;
        case 'b':
          tosc_getNextBlob(&msg, &values[i].b, &values[i].bl);
          break;
      }
    }

    // call callback
    if (!callback(tosc_getAddress(&msg), fmt, values)) {
      return false;
    }
  }

  return true;
}