diff --git a/howard.c b/howard.c index a27b0dc..bd1880f 100644 --- a/howard.c +++ b/howard.c @@ -4,9 +4,20 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include #include "howard.h" -#define MAX_STR 255 +#define TRUE (-1) +#define FALSE (0) + +#define BUFLEN 8196 +#define BUFLENSMALL 255 // Benestar sound meter //#define MIC_VID (0x1630) @@ -25,13 +36,17 @@ const char *rangestr[] = { "80-130", }; +char influxhost[BUFLENSMALL]; +char influxdb[BUFLENSMALL]; +char influxuser[BUFLENSMALL]; +char influxpass[BUFLENSMALL]; + #define FLAG_DBCMODE (0x10) #define FLAG_FASTMODE (0x40) #define E_TIMEOUT -1 #define E_BADREAD -2 - // ANSI stuff #define BOLD "\x1b[1m" #define ITALIC "\x1b[3m" @@ -112,23 +127,181 @@ void showlevel(uint8_t *buf) { char *longformat = "%12s: %ld\n"; char *strformat = "%12s: %s\n"; char *dbformat = "%12s: %4.2f %s\n"; - decibels = buf[0] << 8 | buf[1]; - flags = buf[2]; - rangeidx = buf[2] & 0xf; - now = time(NULL); + decibels = buf[0] << 8 | buf[1]; + flags = buf[2]; + rangeidx = buf[2] & 0xf; + now = time(NULL); - printf(longformat, "Time", now); - printf(dbformat, "Level", (double)decibels/10.0, flags & FLAG_DBCMODE ? "dBC" : "dBA"); - printf(strformat, "Mode", flags & FLAG_FASTMODE ? "Fast" : "Slow"); - printf(strformat, "Range", rangeidx > 0x4 ? "unknown" : rangestr[rangeidx]); + printf(longformat, "Time", now); + printf(dbformat, "Level", (double)decibels/10.0, flags & FLAG_DBCMODE ? "dBC" : "dBA"); + printf(strformat, "Mode", flags & FLAG_FASTMODE ? "Fast" : "Slow"); + printf(strformat, "Range", rangeidx > 0x4 ? "unknown" : rangestr[rangeidx]); +} + +int tcpconnect(char *hname, int port) { + int sockfd; + struct sockaddr_in servaddr; + struct hostent *hptr; + + hptr = resolve(hname); + if (!hptr) return TRUE; + + sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (sockfd < 0) { + perror("socket()"); + return -1; + } + servaddr.sin_family = hptr->h_addrtype; + servaddr.sin_port = htons(8086); + memcpy(&servaddr.sin_addr, hptr->h_addr_list[0], hptr->h_length); + bzero(servaddr.sin_zero, sizeof(servaddr.sin_zero)); + if (connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr))) { + printf("errno is %d\n", errno); + perror("tcpconnect()"); + return -1; + } + return sockfd; +} + +int dohttp(char *hname, int port, char *header, char *body, char *retbuf) { + char response[BUFLEN]; + char *p,*dp,retcode_str[BUFLENSMALL]; + ssize_t n; + int sockfd,retcode_int = -1; + + sockfd = tcpconnect(hname,port); + if (sockfd < 0) { + err("TCP connect to %s:%d failed", hname, port); + return TRUE; + } + + if (write(sockfd, header, strlen(header)) < 0) { + err("POST failed during header send"); + close(sockfd); + return -1; + } + + if (write(sockfd, body, strlen(body)) < 0) { + err("POST failed during body send"); + close(sockfd); + return -1; + } + + // get response + n = read(sockfd, response, sizeof(response)); + if (n < 0) { + err("POST failed during response read"); + close(sockfd); + return -1; + } + response[n] = 0; // NUL-terminate + close(sockfd); + + if (retbuf) strncpy(retbuf, response, BUFLEN); + + // HTTP/1.x 204 + retcode_int = -1; + + p = strstr(response, "HTTP/1"); + if (p) { + p += 9; // should now be at start of return code + dp = retcode_str; + for ( ; + (p + 3 < (response + strlen(response))) && *p && isdigit(*p); + p++,dp++) { + *dp = *p; + } + *dp = 0; + retcode_int = atoi(retcode_str); + } else { + retcode_int = -1; + } + return retcode_int; +} + +struct hostent *resolve(char *hname) { + struct hostent *hptr; + hptr = gethostbyname(hname); + if (hptr == NULL) { + err("Failed to resolve %s (%s)",hname,hstrerror(h_errno)); + return NULL; + } + if (hptr->h_addrtype != AF_INET) { + err("No IN records for %s.",hname); + return NULL; + } + if (hptr->h_addr_list == NULL) { + err("No A records for %s.",hname); + return NULL; + } + return hptr; +} + +int influx_init(char *hname, char *db, char *user, char *pass) { + strncpy(influxhost, hname, BUFLENSMALL); + strncpy(influxdb, db, BUFLENSMALL); + strncpy(influxuser, user, BUFLENSMALL); + strncpy(influxpass, pass, BUFLENSMALL); + return FALSE; +} + +int influx_cmd(enum influxcmdtype cmdtype, char *cmd, char *retbuf) { + char header[BUFLEN]; + char newcmd[BUFLEN+2]; + int rc = -1; + + if (cmdtype == I_WRITE) { + snprintf(header, BUFLEN, "POST /write?db=%s&u=%s&p=%s HTTP/1.1\r\nHost: influx:8086\r\nContent-Length: %ld\r\n\r\n", influxdb, influxuser, influxpass, strlen(cmd)); + snprintf(newcmd,BUFLEN,"%s",cmd); + } else if (cmdtype == I_READ) { + snprintf(header, BUFLEN, "GET /query?db=%s&u=%s&p=%s HTTP/1.1\r\nHost: influx:8086\r\nContent-Length: %ld\r\n\r\n", influxdb, influxuser, influxpass, strlen(cmd)+2); + snprintf(newcmd,BUFLEN,"q=%s",cmd); + } else if (cmdtype == I_PING) { + snprintf(header, BUFLEN, "GET /ping HTTP/1.1\r\nHost: influx:8086\r\n\r\n"); + strncpy(newcmd,"",BUFLEN); + } else { + err("Invalid influx command type (%d)", cmdtype); + return TRUE; + } + + rc = dohttp(influxhost, 8086, header, newcmd, retbuf); + if (rc != 204) { + err("Influx write to %s/%s failed (HTTP %d)",influxhost,influxdb,rc); + return TRUE; + } + return FALSE; +} + +int influx_insert(char *cmd, char *retbuf) { + return influx_cmd(I_WRITE, cmd, retbuf); +} + +int influx_query(char *cmd, char *retbuf ) { + return influx_cmd(I_READ, cmd, retbuf); +} + +int influx_ping(char *retbuf) { + int rv; + rv = influx_cmd(I_PING, "", retbuf); + if (!rv) { + info("Ping success:\n%s\n", retbuf); + } + return rv; +} + +int influx_write_decibels(double decibels) { + char cmd[BUFLEN]; + snprintf(cmd, BUFLEN, "volume decibels=%0.1f\n", decibels); + influx_insert(cmd, NULL); + return 0; } int main(int argc, char *argv[]) { //unsigned char buf[65]; - //wchar_t wstr[MAX_STR]; //hid_device *handle; uint8_t capture_cmd[8] = { CMD_CAPTURE }; uint8_t buf[8]; + char retbuf[BUFLEN]; int res; int i; enum mode_enum { M_PROBE, M_TEST } mode = M_PROBE; @@ -136,11 +309,18 @@ int main(int argc, char *argv[]) { // handle args for (i=1; i