Last active
May 5, 2024 04:13
-
-
Save tresf/898ab2d4d259aef2d4f7 to your computer and use it in GitHub Desktop.
Read weight from a USB scale
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<!-- | |
Author: A. Tres Finocchiaro, tres.finocchiaro@gmail.com | |
License: LGPL 2.1 | |
Depends: QZ Tray 2.0.0-alpha1+ | |
--> | |
<!-- Note: jquery is not needed in alpha2 --> | |
<script type="text/javascript" src="js/dependencies/jquery-1.11.3.min.js"></script> | |
<!-- Note: rsvp can be overriden via qz.setPromiseType(...) TODO: Get usage from @bberenz --> | |
<script type="text/javascript" src="js/dependencies/rsvp-3.1.0.min.js"></script> | |
<script type="text/javascript" src="js/qz-tray.js"></script> | |
<script> | |
// Scale manufacturers | |
var mt = { | |
vendor: '0x0EB8', | |
product: '0xF000', | |
device: '0x00', | |
endpoint: '0x81', | |
}; | |
var dymo = { | |
vendor: '0x0922', | |
product: '0x8009', | |
device: '0x00', | |
endpoint: '0x82', | |
}; | |
// FIXME: Verify with physical scale | |
var stamps = { | |
vendor: '0x1446', // or '0x6A73' | |
product: '0xF000', | |
device: '0x00', | |
endpoint: '0x81', | |
}; | |
var scale = mt; | |
var err = function(e) { console.error(e); } | |
var release = function() { | |
qz.usb.releaseDevice(scale.vendor, scale.product).catch(function(e) { | |
console.error(e); | |
}); | |
} | |
qz.websocket.connect().then(function() { | |
return qz.usb.claimDevice(scale.vendor, scale.product, scale.device); | |
}).catch(err).then(function() { | |
return qz.usb.readData(scale.vendor, scale.product, scale.endpoint, '8'); | |
}).then(function(data) { | |
// Get status | |
var status = parseInt(data[1], 16); | |
switch(status) { | |
case 1: // fault | |
case 5: // underweight | |
case 6: // overweight | |
case 7: // calibrate | |
case 8: // re-zero | |
status = 'error'; break; | |
case 3: | |
status = 'busy'; break; | |
case 2: // stable at zero | |
case 4: // stable non-zero | |
default: | |
status = 'stable'; | |
} | |
// Get precision | |
var precision = parseInt(data[3], 16); | |
precision = precision ^ -256; // unsigned to signed | |
// Get weight | |
data.splice(0,4); | |
data.reverse(); | |
weight = parseInt(data.join(''), 16); | |
// Apply precision | |
weight *= Math.pow(10, precision); | |
weigth = weight.toFixed(Math.abs(precision)); | |
// Get units | |
var units = parseInt(data[2], 16); | |
switch(units) { | |
case 3: | |
units = 'kg'; break; | |
case 11: // ounces | |
units = 'oz'; break; | |
case 12: | |
default: | |
units = 'lbs'; | |
} | |
alert(status + ": " + weight + units); | |
}).then(release).catch(release); | |
</script> | |
</html> |
@bberenz Done, and done, thanks.
FYI, I don't think GitHub sends notices on Gists, so I'm attempting to tag you instead. 👍
Anyone have a recommendation for a USB scale that this would work with? Would this also work with a Bluetooth scale?
@ProPixelMedia this proof of concept is now part of QZ Tray. https://github.com/qzind/tray/blob/master/js/qz-tray.js
With regards to HID communications, all scales use the same protocol. Bluetooth might use the HID protocol or it may use a serial protocol. Serial protocols differ.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
In trying to find an explanation for the previous readings that come through, I happened on information that the scale precision is also sent through the raw data, at index 3 as an unsigned byte. Converting to signed yields a negative number such that
weight * 10^[signed_value]
yeilds the correct weight.