simg / Royal Mail Dymo USB Scale Connector

// ==UserScript==
// @name     Royal Mail Dymo USB Scale Connector
// @version  1
// @grant    none
// @match    https://business.parcel.royalmail.com/orders/
// @require  http://code.jquery.com/jquery-latest.js
// @license MIT
// ==/UserScript==
/* globals $ */

/* References
 * http://steventsnyder.com/reading-a-dymo-usb-scale-using-python/
 * https://blog.scottlogic.com/2019/04/03/upcoming-webhid-api.html
 *
*/


(function() {
    'use strict';

    $( document ).ready(() => {
        console.log('initialising dymo');

        if (!navigator.hid) {
            console.log('Browser does not support webHID. Please enable Experimental Web Platform features');
            return;
        }

        setInterval(addDymoButton, 200);


    });

    function addDymoButton() {
        if ($('.package-weight #btnDymo').length > 0) {
            return;
        }
        $('.package-weight label[for=packageWeight] span:first').append(`
            <span id="btnDymo">D</span>
            <style>
                #btnDymo { display:inline-block; width:15px; height:15px; text-align:center; cursor:pointer; vertical-align:bottom; border:1px solid #900; background-color:#fbb; }
            </style>
        `);
        $('#btnDymo').click(async () => toggleDymo());
    }

    let dymoEnabled;

    async function toggleDymo() {
        try {
            if (dymoEnabled) {
                dymoEnabled = false;
            } else {
                await connectToDymo();
            }
        } catch (error) {
            console.log("error connecting to dymo", error);
        } finally {
            updateDymoStatus();
        }
    }

    function updateDymoStatus() {
        if (dymoEnabled) {
            $('#btnDymo').css({'background-color':'#bfb', 'border-color':'#090'});
        } else {
            $('#btnDymo').css({'background-color':'#fbb', 'border-color':'#900'});
        }
    }

    async function connectToDymo() {

        /* These should work, but don't although it doesn't really seem to matter ...
        navigator.hid.addEventListener('connect', (event) => {
            console.log("deviceConnected", event);
        });

        navigator.hid.addEventListener('disconnect', (event) => {
            console.log("deviceDisConnected", event);
        });*/


        let devices = await navigator.hid.getDevices();

        let device = devices.find(d => d.vendorId === 0x0922);

        if (!device) {
            //don't already have permission so ask for it.
            devices = await navigator.hid.requestDevice({ filters: [{ vendorId: 0x0922 }] });
            device = devices[0];
        }

        if (device.opened === false) {
            await device.open(); // Begin a session
        }

        //$('#btnDymo').css({'background-color':'#bfb', 'border-color':'#090'});
        dymoEnabled = true;

        device.addEventListener('inputreport', event => {
            const i0 = event.data.getUint8(0),
                    i1 = event.data.getUint8(1),
                    i2 = event.data.getUint8(2),
                    i3 = event.data.getUint8(3),
                    i4 = event.data.getUint8(4);

            //console.log("i", i0, i1, i2, i3, i4);
            const weight = i3 + (i4*256);
            if (dymoEnabled) {
                $('#packageWeight').val(weight);
            }
        });
    }
})();