Now works.
This commit is contained in:
parent
b43f8e027a
commit
42124a22e2
42
README.md
42
README.md
|
@ -1,6 +1,6 @@
|
||||||
# Overview
|
# Overview
|
||||||
|
|
||||||
Sound level monitoring via USB Benetech GM1356.
|
Performs sound level monitoring using a USB Benetech GM1356 sonometer.
|
||||||
|
|
||||||
Named after [Loud Howard](https://dilbert.com/strip/1995-04-21).
|
Named after [Loud Howard](https://dilbert.com/strip/1995-04-21).
|
||||||
|
|
||||||
|
@ -9,10 +9,39 @@ Big thanks to [Maciej Ciemborowicz](https://github.com/ciembor) for his work doc
|
||||||
# Requirements
|
# Requirements
|
||||||
- [hidapi](https://github.com/libusb/hidapi)
|
- [hidapi](https://github.com/libusb/hidapi)
|
||||||
- An OS which recognises the GM1356 as a USB device (ie. not OSX Big Sur).
|
- An OS which recognises the GM1356 as a USB device (ie. not OSX Big Sur).
|
||||||
|
- A GM1356 sonometer (obviously)
|
||||||
|
|
||||||
# Usage
|
# Usage
|
||||||
|
|
||||||
TBC
|
```text
|
||||||
|
bash$ ./howard -h
|
||||||
|
usage: howard [OPTIONS] outputmode1 [ outputmode2 ... ]
|
||||||
|
|
||||||
|
Reads maximum noise level from a Benestar GM1356 sonometer
|
||||||
|
over a given interval, and optionally stores result in an
|
||||||
|
influxdb database.
|
||||||
|
|
||||||
|
Valid output modes are:
|
||||||
|
short (single line to stdout)
|
||||||
|
long (multiple lines to stdout)
|
||||||
|
db (HTTP POST to influxdb, must also provide INFLUXDB OPTIONS - see below)
|
||||||
|
|
||||||
|
OPTIONS:
|
||||||
|
-c Run endlessly (also see -i and -w)
|
||||||
|
-h Show this usage text then exit.
|
||||||
|
-i secs Define time over which to get max decibels
|
||||||
|
-t Test mode - just probe for sononeter then exit
|
||||||
|
-T Influxdb test mode - just test influxdb connectivity then exit
|
||||||
|
-w secs Define period to wait between noise level checks
|
||||||
|
insert will just be written to stdout.
|
||||||
|
|
||||||
|
INFLUXDB OPTIONS:
|
||||||
|
-d dbname Define influxdb database name
|
||||||
|
-H hostname Define influxdb hostname
|
||||||
|
-p password Define influxdb password
|
||||||
|
-u username Define influxdb password
|
||||||
|
-y Actually write to influxdb. Without this,
|
||||||
|
```
|
||||||
|
|
||||||
# Screenshots
|
# Screenshots
|
||||||
|
|
||||||
|
@ -20,4 +49,11 @@ TBC
|
||||||
|
|
||||||
# Implementation Notes
|
# Implementation Notes
|
||||||
|
|
||||||
- The device seems to 'hang' periodically and cause all subsequent reads to timeout. To work around this, after two concurrent timeouts I send an `IOCTL_USBDEVFS_RESET`.
|
- The device seems to 'hang' periodically and cause all subsequent reads to timeout. To work around this, after two concurrent timeouts I send an `IOCTL_USBDEVFS_RESET`.
|
||||||
|
|
||||||
|
- I don't yet have configuration commands working, so the following need to be manually configured on the physical device:
|
||||||
|
- slow/fast exponential time averaging
|
||||||
|
- MAX mode
|
||||||
|
- dBA vs dBC units
|
||||||
|
|
||||||
|
|
||||||
|
|
120
howard.h
120
howard.h
|
@ -1,25 +1,115 @@
|
||||||
|
// booleans
|
||||||
|
#define TRUE (-1)
|
||||||
|
#define FALSE (0)
|
||||||
|
#define BADFD (-1)
|
||||||
|
|
||||||
|
// buffer lengths
|
||||||
|
#define BUFLEN 8196
|
||||||
|
#define BUFLENSMALL 255
|
||||||
|
|
||||||
|
// Benestar sound meter
|
||||||
|
#define MIC_VID "64bd"
|
||||||
|
#define MIC_PID "74e3"
|
||||||
|
|
||||||
|
// mic constants
|
||||||
|
#define FLAG_DBCMODE (0b00010000) // use dBc (not dBa)
|
||||||
|
#define FLAG_MAXMODE (0b00100000) // get max db over interval
|
||||||
|
// fast = 125ms exp time avg
|
||||||
|
// slow = 1000ms exp time avg
|
||||||
|
#define FLAG_FASTMODE (0b01000000)
|
||||||
|
// ranges supported by sonometer
|
||||||
|
#define FLAG_RANGE_30_130 (0b00000000)
|
||||||
|
#define FLAG_RANGE_30_80 (0b00000001)
|
||||||
|
#define FLAG_RANGE_50_100 (0b00000010)
|
||||||
|
#define FLAG_RANGE_60_110 (0b00000011)
|
||||||
|
#define FLAG_RANGE_80_130 (0b00000100)
|
||||||
|
|
||||||
|
// ANSI stuff
|
||||||
|
#define BOLD "\x1b[1m"
|
||||||
|
#define ITALIC "\x1b[3m"
|
||||||
|
#define STRIKE "\x1b[9m"
|
||||||
|
#define PLAIN "\x1b[0m"
|
||||||
|
#define UNDERLINE "\x1b[4m"
|
||||||
|
#define RED "\x1b[31m"
|
||||||
|
#define MAGENTA "\x1b[35m"
|
||||||
|
#define GREEN "\x1b[32m"
|
||||||
|
#define YELLOW "\x1b[33m"
|
||||||
|
#define BLUE "\x1b[34m"
|
||||||
|
#define CYAN "\x1b[36m"
|
||||||
|
#define GREY "\x1b[2;37m"
|
||||||
|
|
||||||
|
// Output modes
|
||||||
|
#define OM_SHORT (1) // Print to stdout in one line
|
||||||
|
#define OM_LONG (2) // Print to stdout over multiple lines
|
||||||
|
#define OM_DB (4) // Write to influxdb
|
||||||
|
|
||||||
|
|
||||||
|
// Control strings
|
||||||
|
#define CMD_CAPTURE (0xb3) // take a reading
|
||||||
|
#define CMD_CONFIGURE (0x56) // apply settings
|
||||||
|
#define RES_ACK (0xc4) // ack for command
|
||||||
|
|
||||||
|
// what to do
|
||||||
|
enum run_mode {
|
||||||
|
M_PROBE, // measure noise level
|
||||||
|
M_TEST, // just check for sononeter then exit
|
||||||
|
M_TESTDB // just check influxdb access then exit
|
||||||
|
};
|
||||||
|
|
||||||
|
// return codes for read_single_result()
|
||||||
|
enum read_status {
|
||||||
|
E_NOERROR=0, // all good
|
||||||
|
E_TIMEOUT=-1, // didn't receive all data in time
|
||||||
|
E_BADREAD=-2 // received too much or too little data
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int dirty;
|
||||||
|
time_t unixtime;
|
||||||
|
uint8_t flags;
|
||||||
|
double decibels;
|
||||||
|
int rangeidx;
|
||||||
|
char range[BUFLENSMALL];
|
||||||
|
char dbunits[BUFLENSMALL];
|
||||||
|
char checkmode[BUFLENSMALL];
|
||||||
|
char timenice[BUFLENSMALL];
|
||||||
|
} result_t;
|
||||||
enum influxcmdtype { I_READ, I_WRITE, I_PING };
|
enum influxcmdtype { I_READ, I_WRITE, I_PING };
|
||||||
|
|
||||||
char *getdevpath(int vid, int pid, char *retvar);
|
|
||||||
int resetusb(char *path);
|
// prototypes
|
||||||
|
int add_output_mode(char *m);
|
||||||
char *append(char *orig, char *new, int maxlen);
|
char *append(char *orig, char *new, int maxlen);
|
||||||
void colprintf( char *prefix, const char *col, char* format, va_list *args );
|
|
||||||
double getdecibels(uint8_t *buf);
|
|
||||||
void cleanup(void);
|
void cleanup(void);
|
||||||
void handle_signal(int signum);
|
void clear_results(result_t *data);
|
||||||
void info( char* format, ... );
|
void colprintf( char *prefix, const char *col, char* format, va_list *args );
|
||||||
void vinfo( char* format, ... );
|
int configure_mic(void);
|
||||||
|
struct hostent *dnslookup(char *hname);
|
||||||
void err( char* format, ... );
|
void err( char* format, ... );
|
||||||
void warn( char* format, ... );
|
double extract_decibels(uint8_t *buf);
|
||||||
|
void generate_commands(void);
|
||||||
|
char *getprocfspath(int vid, int pid, char *retvar);
|
||||||
|
void handle_signal(int signum);
|
||||||
int hextoint(char *hex);
|
int hextoint(char *hex);
|
||||||
int readresult(hid_device *dev, uint8_t *retbuf);
|
|
||||||
void dooutput(uint8_t *buf);
|
|
||||||
int tcpconnect(char *hname, int port);
|
|
||||||
int dohttp(char *hname, int port, char *header, char *body, char *retbuf);
|
|
||||||
struct hostent *resolve(char *hname);
|
|
||||||
int influx_init(char *hname, char *db, char *user, char *pass);
|
|
||||||
int influx_cmd(enum influxcmdtype cmdtype, char *cmd, char *retbuf);
|
int influx_cmd(enum influxcmdtype cmdtype, char *cmd, char *retbuf);
|
||||||
|
int influx_httppost(char *hname, int port, char *header, char *body, char *retbuf);
|
||||||
|
int influx_init(char *hname, char *db, char *user, char *pass);
|
||||||
int influx_insert(char *cmd, char *retbuf);
|
int influx_insert(char *cmd, char *retbuf);
|
||||||
int influx_query(char *cmd, char *retbuf);
|
|
||||||
int influx_ping(char *retbuf);
|
int influx_ping(char *retbuf);
|
||||||
|
int influx_query(char *cmd, char *retbuf);
|
||||||
int influx_write_decibels(double decibels);
|
int influx_write_decibels(double decibels);
|
||||||
|
void info( char* format, ... );
|
||||||
|
int init_influxdb(void);
|
||||||
|
int init_mic(void);
|
||||||
|
int mic_docmd(hid_device *dev, uint8_t *cmd, int cmdlen, uint8_t *buf);
|
||||||
|
int output_results(result_t *data);
|
||||||
|
int parse_results(uint8_t *buf, result_t *data);
|
||||||
|
void pr(char *col, char* format, ... );
|
||||||
|
enum read_status read_single_result(hid_device *dev, uint8_t *retbuf);
|
||||||
|
int resetusb(char *path);
|
||||||
|
int tcpconnect(char *hname, int port);
|
||||||
|
void usage(void);
|
||||||
|
int validateargs(void);
|
||||||
|
void vinfo( char* format, ... );
|
||||||
|
void warn( char* format, ... );
|
||||||
|
|
Loading…
Reference in New Issue