mirror of
https://github.com/erjiang/usbscale.git
synced 2025-09-17 13:12:39 -06:00
Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
9ed1cb55a2 | ||
|
23888abc52 | ||
|
97e48ded31 | ||
|
3ffb1693cb | ||
|
699c278010 |
17
.github/workflows/build.yml
vendored
Normal file
17
.github/workflows/build.yml
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
name: Build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "master" ]
|
||||
pull_request:
|
||||
branches: [ "master" ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Install dependencies
|
||||
run: sudo apt-get update && sudo apt-get install -y build-essential libusb-1.0-0-dev
|
||||
- name: Build
|
||||
run: make
|
@ -10,4 +10,4 @@ SUBSYSTEM=="usb", ATTR{idVendor}=="0b67", ATTR{idProduct}=="555e", MODE="0776"
|
||||
SUBSYSTEM=="usb", ATTR{idVendor}=="0922", ATTR{idProduct}=="8003", MODE="0776"
|
||||
SUBSYSTEM=="usb", ATTR{idVendor}=="0922", ATTR{idProduct}=="8004", MODE="0776"
|
||||
SUBSYSTEM=="usb", ATTR{idVendor}=="0922", ATTR{idProduct}=="8009", MODE="0776"
|
||||
SUBSYSTEM=="usb", ATTR{idVendor}=="08df", ATTR{idProduct}=="0200", MODE="0776"
|
||||
SUBSYSTEM=="usb", ATTR{idVendor}=="0d8f", ATTR{idProduct}=="0200", MODE="0776"
|
||||
|
@ -24,6 +24,9 @@ error messages will be sent to `stderr`. An exit code of 0 means that a scale
|
||||
was found and a weight was successfully read. Any other error code indicates
|
||||
that a weight reading was unavailable.
|
||||
|
||||
Use the `-h`/`--human` flag to format ounce measurements as pounds and
|
||||
ounces, e.g. `1 lbs 4 oz` instead of `20 oz`.
|
||||
|
||||
## Zeroing the scale
|
||||
|
||||
There is somewhat-experimental support for sending a tare command to the scale.
|
||||
|
40
usbscale.c
40
usbscale.c
@ -73,7 +73,7 @@ static libusb_device* find_nth_scale(libusb_device**, int);
|
||||
// it, printing out the result to the screen. It also returns a 1 if the
|
||||
// program should read again (i.e. continue looping).
|
||||
//
|
||||
static int print_scale_data(unsigned char*);
|
||||
static int print_scale_data(unsigned char*, bool);
|
||||
|
||||
//
|
||||
// take device and fetch bEndpointAddress for the first endpoint
|
||||
@ -107,13 +107,14 @@ const char* UNITS[13] = {
|
||||
};
|
||||
|
||||
// Setup argument parsing
|
||||
const char *argp_program_version = "usbscale 0.2";
|
||||
const char *argp_program_version = "usbscale 0.3";
|
||||
const char *argp_program_bug_address = "<https://www.github.com/erjiang/usbscale/issues>";
|
||||
static char doc[] = "Read weight from a USB scale\n"
|
||||
"The `zero' command will request the scale to reset to zero (not supported by all scales).\n";
|
||||
static char args_doc[] = "[zero]";
|
||||
static struct argp_option options[] = {
|
||||
{ "index", 'i', "INDEX", 0, "Index of scale to read (default: 1)" },
|
||||
{ "human", 'h', 0, 0, "Print weight in lbs and oz when units are oz" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
@ -121,6 +122,7 @@ static struct argp_option options[] = {
|
||||
struct arguments {
|
||||
int index;
|
||||
bool tare;
|
||||
bool human;
|
||||
};
|
||||
|
||||
static error_t parse_opt(int key, char *arg, struct argp_state *state) {
|
||||
@ -133,6 +135,9 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) {
|
||||
argp_usage(state);
|
||||
}
|
||||
break;
|
||||
case 'h':
|
||||
arguments->human = true;
|
||||
break;
|
||||
case ARGP_KEY_ARG:
|
||||
if (strcmp(arg, "zero") == 0) {
|
||||
arguments->tare = true;
|
||||
@ -162,6 +167,7 @@ int main(int argc, char **argv)
|
||||
// By default, get the first scale's weight
|
||||
arguments.index = 1;
|
||||
arguments.tare = false;
|
||||
arguments.human = false;
|
||||
argp_parse(&argp, argc, argv, 0, 0, &arguments);
|
||||
|
||||
libusb_device **devs;
|
||||
@ -314,7 +320,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
#endif
|
||||
if (weigh_count < 1) {
|
||||
scale_result = print_scale_data(data);
|
||||
scale_result = print_scale_data(data, arguments.human);
|
||||
if(scale_result != 1)
|
||||
break;
|
||||
}
|
||||
@ -351,14 +357,15 @@ int main(int argc, char **argv)
|
||||
// ----------------
|
||||
//
|
||||
// **print_scale_data** takes the 6 bytes of binary data sent by the scale and
|
||||
// interprets and prints it out.
|
||||
// interprets and prints it out. If `human` is true and the units are ounces,
|
||||
// it will output the weight as pounds and ounces.
|
||||
//
|
||||
// **Returns:** `0` if weight data was successfully read, `1` if the data
|
||||
// indicates that more data needs to be read (i.e. keep looping), and `-1` if
|
||||
// the scale data indicates that some error occurred and that the program
|
||||
// should terminate.
|
||||
//
|
||||
static int print_scale_data(unsigned char* dat) {
|
||||
static int print_scale_data(unsigned char* dat, bool human) {
|
||||
|
||||
//
|
||||
// We keep around `lastStatus` so that we're not constantly printing the
|
||||
@ -376,8 +383,10 @@ static int print_scale_data(unsigned char* dat) {
|
||||
uint8_t unit = dat[2];
|
||||
// According to the docs, scaling applied to the data as a base ten exponent
|
||||
int8_t expt = dat[3];
|
||||
// convert to machine order at all times
|
||||
double weight = (double) le16toh(dat[5] << 8 | dat[4]);
|
||||
// combine the little-endian weight bytes without relying on system
|
||||
// endianness. dat[4] is the low byte and dat[5] is the high byte.
|
||||
uint16_t raw_weight = (uint16_t)dat[4] | ((uint16_t)dat[5] << 8);
|
||||
double weight = (double)raw_weight;
|
||||
// since the expt is signed, we do not need no trickery
|
||||
weight = weight * pow(10, expt);
|
||||
|
||||
@ -412,7 +421,13 @@ static int print_scale_data(unsigned char* dat) {
|
||||
// the `UNITS` lookup table for unit names.
|
||||
//
|
||||
case 0x04:
|
||||
printf("%g %s\n", weight, UNITS[unit]);
|
||||
if (human && unit == 11) {
|
||||
int lbs = (int)floor(weight / 16.0);
|
||||
double oz = weight - (lbs * 16.0);
|
||||
printf("%d lbs %g oz\n", lbs, oz);
|
||||
} else {
|
||||
printf("%g %s\n", weight, UNITS[unit]);
|
||||
}
|
||||
return 0;
|
||||
case 0x05:
|
||||
if(status != lastStatus)
|
||||
@ -463,8 +478,8 @@ static libusb_device* find_nth_scale(libusb_device **devs, int index)
|
||||
uint16_t last_device_address = 0;
|
||||
|
||||
//
|
||||
// Loop through each USB device, and for each device, loop through the
|
||||
// scales list to see if it's one of our listed scales.
|
||||
// Loop through each USB device and check if it's one of the
|
||||
// supported scales listed in scales.h.
|
||||
//
|
||||
while ((dev = devs[i++]) != NULL) {
|
||||
|
||||
@ -474,9 +489,7 @@ static libusb_device* find_nth_scale(libusb_device **devs, int index)
|
||||
fprintf(stderr, "failed to get device descriptor");
|
||||
return NULL;
|
||||
}
|
||||
int i;
|
||||
for (i = 0; i < NSCALES; i++) {
|
||||
if (is_scale(desc.idVendor, desc.idProduct)) {
|
||||
if (is_scale(desc.idVendor, desc.idProduct)) {
|
||||
|
||||
// Skip this device if it's the same as the last one.
|
||||
uint16_t this_device_address = (libusb_get_bus_number(dev) << 8) + libusb_get_device_address(dev);
|
||||
@ -520,7 +533,6 @@ static libusb_device* find_nth_scale(libusb_device **devs, int index)
|
||||
if (curr_index == index) {
|
||||
return dev;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
|
Loading…
x
Reference in New Issue
Block a user