-
-
Thanks for the suggestions I have JS-OTP (One Time Password) loading now without the error or memory warning by editing out the ES6 default values. I cut and pasted the GIT hub code into the right hand IDE panel and uploaded it from there. I also removed any browser objects as the code was designed to work in browser.
But I hit a new issue with HMAC. (HMAC stands for Keyed-Hashing for Message Authentication) The hash features used by JS-OTP and TinyOTP expect a .hmac method on the hash object. The built in crypto libs do not have this feature.
I don't think I can implement HMAC so I am looking for an OTP implementation that is not using HMAC.
I will update here when I make progress.
-
I think I have found the issue the OTPAuth is too large when loaded with the crypto.js lib.
var crypto = require("crypto"); var otp = require("https://raw.githubusercontent.com/hectorm/otpauth/master/dist/otpauth.min.js");
Gives the following error
____ _ | __|___ ___ ___ _ _|_|___ ___ | __|_ -| . | _| | | | | . | |____|___| _|_| |___|_|_|_|___| |_| espruino.com 2v03 (c) 2018 G.Williams >Uncaught SyntaxError: Got UNFINISHED STRING expected EOF at line 1 col 98 ...aster/dist/otpauth.min.js","(function(){/*\n otpauth v4.0.0 ... ^ Execution Interrupted New interpreter error: LOW_MEMORY,MEMORY >Uncaught Error: Module https://raw.githubusercontent.com/hectorm/otpauth/master/dist/otpauth.min.js not found at line 3 col 81 ...master/dist/otpauth.min.js"); ^ >
I will look for a different OTP lib
-
Hi I am trying to generate time based single sign on tokens on my Pixl and puckjs. these can then be sent to a PC or phone over BT via the keyboard HID.
My research so far says that I need the crypto.js lib from modules and OTPAuth from npm as it has no dependencies
So far I am only getting erros. I think I do not have my requires working I will post more after I get better results
-
IT WORKS!
To use:
- Upload code via webIDE
- Disconnect the IDE
- Calibrate the mag sensor by rotating puck in all directions until no red flashes (only green)
- Press button to stop calibrating
- Connect by BLE from a laptop or phone
- run music software
- rotate for volume
- press for pause/play
- Turn over and rotate for next/prev track
Let me know your results.
Current things to improve are next/prev un- pauses, the is no power saving mode, and tidy up my code and create some low level functions for calibrate and power management.Code:
var Vec3 = require('Vec3'); var vMin = new Vec3(); var vMax = new Vec3(); var vAve = new Vec3(); var vZero = new Vec3(); var calibrating = false; var calibrated = false; var count = 0; var h = 0; var oldh = 0; var r = 0; var controls = require("ble_hid_controls"); var nrf = NRF.setServices(undefined, { hid : controls.report }); /* // use this for power managment // call a function if button is held down for 4 seconds function b4Seconds(callback) { setWatch(function(e) { if (calibrating) {return;} console.log("Button down"); t4s = setTimeout(function() { callback(); },4000); setWatch(function(e) { clearTimeout(t4s); console.log("Button up"); }, BTN, { repeat: false, edge: 'falling', debounce: 50 }); }, BTN, { repeat: true, edge: 'rising', debounce: 50 }); } */ function calibrate () { if (calibrated) { //console.log('re-calibrating...'); } else { //console.log('calibrating...'); } calibrated = false; calibrating = true; var xyz = Puck.mag(); var sMax = 0; var sMin = 0; count = 0; vMin = new Vec3(xyz); vMax = new Vec3(xyz); Puck.magOn(10); Puck.on('mag', function(xyz) { if (calibrated) {return;} var vMag = new Vec3(xyz); vMin = vMin.min(vMag); vMax = vMax.max(vMag); if ((sMax != vMax.mag()) || (sMin != vMin.mag())) { sMin = vMin.mag(); sMax = vMax.mag(); count++; //console.log('new min or max: ',count); // flash the red LED when calibrating digitalPulse(LED1,1,100); } else { // flash the green LED when not calibrating digitalPulse(LED2,1,10); } }); //press the buton to stop calibrating setWatch(function(e) { Puck.magOn(5); calibrating = false; //console.log("calibarion completed"); //console.log('max: ',vMax); //console.log('min: ',vMin); // calculate the average of vMin and vMax to get the nuteral position vAve = new Vec3((vMin.x + vMax.x)/2,(vMin.y + vMax.y)/2,(vMin.z + vMax.z)/2); // console.log('ave: ',vAve); // get the zero position when the end calibrate button was pressed vZero = new Vec3(Puck.mag()).sub(vAve); // console.log('zero:',vZero); calibrated = true; }, BTN, { repeat: false, edge: 'rising', debounce: 50 }); } function calibratedMag() { var comQueue = []; var coms = false; // use the button for play/pause setWatch(function(e) { if(calibrating) {return;} comQueue.push('S'); digitalPulse(LED1,1,10); digitalPulse(LED2,1,10); digitalPulse(LED3,1,10); }, BTN, { repeat: true, edge: 'rising', debounce: 50 }); Puck.magOn(10); Puck.on('mag', function(xyz) { if(calibrating) {return;} if ((comQueue.length > 0) && (coms == false)){ coms = true; //console.log(comQueue,coms); var comand = comQueue.pop(); if (comand == 'U') { digitalPulse(LED1,1,3); try { controls.volumeUp(function(){ controls.volumeUp(function(){ coms = false; });}); } catch (e) {coms = false;} } if (comand == 'D') { digitalPulse(LED3,1,3); try { controls.volumeDown(function(){ controls.volumeDown(function(){ coms = false; });}); } catch (e) {coms = false;} } if (comand == 'N') { digitalPulse(LED2,1,3); try { controls.next(function(){ coms = false; }); } catch (e) {coms = false;} } if (comand == 'P') { digitalPulse(LED2,1,3); try { controls.prev(function(){ coms = false; }); } catch (e) {coms = false;} } if (comand == 'S') { try { controls.playpause(function(){ coms = false; }); } catch (e) {coms = false;} } } // correct mag reading using calibration data var vMag = new Vec3(xyz).sub(vAve); //console.log('mag: ',vMag); h = (Math.atan2(vMag.y, vMag.x) * 180) / Math.PI; if (h > 360) { h = h - 360; } if (h < 0) { h = h + 360; } r = Math.round(h - oldh); if ((r > 300)) {r = r - 360;} if ((r < -300)) {r = r + 360;} if (Math.abs(r) >4) { if (vMag.z > 0) { if (r>0) { comQueue.push('U'); //try { controls.volumeUp();} catch (e) { } } else { comQueue.push('D'); } } else { if (r>0) { comQueue.push('P'); } else { comQueue.push('N'); } } //console.log('-------------'); if (!calibrated) {console.log('uncalibrated!');} //console.log('heading: ',Math.round(h)); //console.log('rotate: ',r); if (vMag.z > 0) { //console.log('upwards'); } else { //console.log('downwards'); } } oldh = h; }); } //calibrate by holding button down for 4 seconds calibrate() calibratedMag();
Reset to remove stop code
- Upload code via webIDE
-
-
-
-
I have calculated the average of the min max and subtracted this from the raw. The calibration data now looks good. Now i can see when the puck is upside down as the z axis changes it sign. I am also calculating the heading and correcting for negative numbers .
Can you test on your device and see if the puck now works as a digital compass.
You will have to calibrate by holding down the button for 5 seconds then rotating the puck in all directions until the is only green flashes no blue. then press to go back to calibrated readings.
var Vec3 = require('Vec3'); var vMin = new Vec3(); var vMax = new Vec3(); var vAve = new Vec3(); var vZero = new Vec3(); var calibrating = false; var calibrated = false; var count = 0; var h = 0; var oldh = 0; // call a function if button is held down for 4 seconds function b4Seconds(callback) { setWatch(function(e) { if (calibrating) {return;} console.log("Button down"); t4s = setTimeout(function() { callback(); },4000); setWatch(function(e) { clearTimeout(t4s); console.log("Button up"); }, BTN, { repeat: false, edge: 'falling', debounce: 50 }); }, BTN, { repeat: true, edge: 'rising', debounce: 50 }); } function calibrate () { if (calibrated) { console.log('re-calibrating...'); } else { console.log('calibrating...'); } calibrated = false; calibrating = true; var xyz = Puck.mag(); var sMax = 0; var sMin = 0; count = 0; vMin = new Vec3(xyz); vMax = new Vec3(xyz); Puck.magOn(10); Puck.on('mag', function(xyz) { if (calibrated) {return;} var vMag = new Vec3(xyz); vMin = vMin.min(vMag); vMax = vMax.max(vMag); if ((sMax != vMax.mag()) || (sMin != vMin.mag())) { sMin = vMin.mag(); sMax = vMax.mag(); count++; console.log('new min or max: ',count); // flash the blue LED when calibrating digitalWrite(LED3, count % 2 == 0); } else { // flash the green LED when not calibrating digitalWrite(LED2, Math.random()>0.5); digitalWrite(LED3, false); } }); //press the buton to stop calibrating setWatch(function(e) { Puck.magOn(5); calibrating = false; console.log("calibarion completed"); console.log('max: ',vMax); console.log('min: ',vMin); digitalWrite(LED3, false); digitalWrite(LED2, false); // calculate the average of vMin and vMax to get the nuteral position vAve = new Vec3((vMin.x + vMax.x)/2,(vMin.y + vMax.y)/2,(vMin.z + vMax.z)/2); console.log('ave: ',vAve); // get the zero position when the end calibrate button was pressed vZero = new Vec3(Puck.mag()).sub(vAve); console.log('zero:',vZero); calibrated = true; }, BTN, { repeat: false, edge: 'rising', debounce: 50 }); } function calibratedMag() { Puck.magOn(); Puck.on('mag', function(xyz) { if(calibrating) {return;} var vMag = new Vec3(xyz).sub(vAve); //console.log('mag: ',vMag); h = (Math.atan2(vMag.y, vMag.x) * 180) / Math.PI; if (h > 360) { h = h - 360; } if (h < 0) { h = h + 360; } if (Math.abs(Math.round(oldh) - Math.round(h)) >4) { console.log('--------------------'); if (!calibrated) {console.log('uncalibrated!');} console.log('heading: ',Math.round(h)); console.log('rotate: ', Math.round(oldh - h)); if (vMag.z > 0) { console.log('upwards'); } else { console.log('downwards'); } } oldh = h; }); } //calibrate by holding button down for 4 seconds b4Seconds(calibrate); calibratedMag();
The out
-------------------- heading: 140 rotate: -20 downwards -------------------- heading: 209 rotate: -69 downwards -------------------- heading: 201 rotate: 9 upwards -------------------- heading: 186 rotate: 13 upwards -------------------- heading: 161 rotate: 25 upwards -------------------- heading: 128 rotate: 29 upwards -------------------- heading: 114 rotate: 14 upwards -------------------- heading: 103 rotate: 11 upwards --------------------
put after calibration
-
Thanks for your test. Your calibration numbers are both similar which is good but are also very different to my numbers.
You are right I will need to add some sort of sleep mode where the puck reduces or stops its mag sensor scanning to save power.
next step is to calculate the average of the min and max and use to re-base the sensor.
-
I have made some progress.
The following code calculates the min and max value for the mag x,y,z axis using Vec3 module. Can you test and show what you get on your puck. The to do at the end of the code shows my next steps.
To use hold down the button for 5 seconds then rotate the puck in all directions until you only see green flashes (no blue). Then press the button to end calibration. The min and max values are then logged on your debug screen.
var Vec3 = require('Vec3'); var vMin = new Vec3(); var vMax = new Vec3(); var calibrating = false; var count = 0; // call a function if button is held down for 4 seconds function b4Seconds(callback) { setWatch(function(e) { console.log("Button down"); t4s = setTimeout(function() { callback(); },4000); setWatch(function(e) { clearTimeout(t4s); console.log("Button up"); }, BTN, { repeat: false, edge: 'falling', debounce: 50 }); }, BTN, { repeat: true, edge: 'rising', debounce: 50 }); } function calibrate () { console.log('calibrating...'); calibrating = true; var xyz = Puck.mag(); var sMax = 0; var sMin = 0; count = 0; vMin = new Vec3(xyz); vMax = new Vec3(xyz); Puck.magOn(10); Puck.on('mag', function(xyz) { var vMag = new Vec3(xyz); vMin = vMin.min(vMag); vMax = vMax.max(vMag); if ((sMax != vMax.mag()) || (sMin != vMin.mag())) { sMin = vMin.mag(); sMax = vMax.mag(); count++; console.log('new min or max: ',count); // flash the blue LED when calibrating digitalWrite(LED3, count % 2 == 0); } else { // flash the green LED when not calibrating digitalWrite(LED2, Math.random()>0.5); digitalWrite(LED3, false); } }); //press the buton to stop calibrating setWatch(function(e) { Puck.magOff(); calibrating = false; console.log("calibarion completed"); console.log('max: ',vMax); console.log('min: ',vMin); digitalWrite(LED3, false); digitalWrite(LED2, false); // TO DO // get the zero position when the end calibrate button was pressed // calculate the average of vMin and vMax to get the nuteral position // calculate the spread of vMin, vMax to scale future readings // use the above to find out if the puck is rotating clockwise or anti // use the above to find out if the puck is upside down // send BT HID key presses }, BTN, { repeat: false, edge: 'rising', debounce: 50 }); } //calibrate by holding button down for 4 seconds b4Seconds(calibrate);
| |_ ___ ___ _ ||___ ___
| |_ -| . | _| | | | | . |
||_| || |_|||_|_||_| espruino.com
2v03 (c) 2018 G.Williams
Button down
calibrating...
new min or max: 1
new min or max: 2
new min or max: 3
new min or max: 4
new min or max: 5
new min or max: 6
Button up
new min or max: 7
new min or max: 8
new min or max: 9
new min or max: 10
new min or max: 11
new min or max: 12
new min or max: 13
new min or max: 14
new min or max: 15
new min or max: 16
new min or max: 17
new min or max: 18
new min or max: 19
new min or max: 20
new min or max: 21
new min or max: 22
new min or max: 23
new min or max: 24
new min or max: 25
new min or max: 26
new min or max: 27
new min or max: 28
new min or max: 29
new min or max: 30
new min or max: 31
new min or max: 32
new min or max: 33
new min or max: 34
new min or max: 35
new min or max: 36
new min or max: 37
new min or max: 38
Button down
calibarion completed
max: Vec3: { "x": 794, "y": 527, "z": 124 }
min: Vec3: { "x": 104, "y": -179, "z": -857 }
Button up -
Thanks for all the good advice.
I think I need to lean some vector math!
my next steps are:
Use Vec3.js to calibrate my mag sensor and surroundings.
by adding a hold down the button for 4 seconds to calibrate feature:
To calibrate rotate the puck in all directions while sampling the mag data at a high rate, save the min and max value of each x,y,z axis.
Press button to exit calibrate
Take the average of the min/max for x,y,z and store these as JSON to a file in flash mem.
Sample at a lower rate and subtract the average x,y,z from each reading
use vector maths to calculate which way up the puck is and any clockwise or anticlockwise rotation steps.
Then I need to work out how to send HID command via BT
I will post an update as soon as I have made progress or if I have more problems. With some debug output this time.
-
Hi, I have a few puckjs and am looking at how make them into useful household devices. I am currently trying to build a simple to use HID BLE media remote control
Features
- Turn the puck clockwise to raise the volume
- Tune the puck anticlockwise to turn down the volume
- Tune the puck on its back (black side facing up) then turn to change the channel or track
Click to pause and resume (or Mute /UnMute)
console.log('Compass heading test'); Puck.magOn(); Puck.on('mag', function(c) { console.log('Raw mag data: ',c); var xGa = c.x * 0.48828125; var yGa = c.y * 0.48828125; var d = 0; if (xGa == 0) { if ( yGa <= 0) { d = 90; } else { d = 0; } } else { console.log('Corrected X,YL ',xGa,yGa); d = Math.atan(yGa/xGa)*(180/Math.PI); } if (d > 360) { d = d - 360; } if (d < 0) { d = d + 360; } console.log('Direction: ', d); });
My first attempt is to convert mag x, y, z reading to a compass heading to then take changes to measure left and right rotation. I have completely failed to get this to work any idea what I am doing wrong?
- Turn the puck clockwise to raise the volume
My Bangle arrive a few days ago and it buzzes but not beep from the API I think I am also missing a piezo. I am very happy with the other features and have lots of app ideas!!