From f28c141f22738ced0c3b0a797ff8fbbb07ceaf07 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 7 Nov 2019 20:24:57 +0000 Subject: [PATCH] Add HID apps --- apps.json | 22 ++++++++++ apps/hid-keyboard-icon.js | 1 + apps/hid-keyboard.js | 86 ++++++++++++++++++++++++++++++++++++++ apps/hid-keyboard.json | 5 +++ apps/hid-keyboard.png | Bin 0 -> 506 bytes apps/hid-music-icon.js | 1 + apps/hid-music.js | 85 +++++++++++++++++++++++++++++++++++++ apps/hid-music.json | 5 +++ apps/hid-music.png | Bin 0 -> 632 bytes apps/settings-init.js | 39 ++++++++++++++--- 10 files changed, 239 insertions(+), 5 deletions(-) create mode 100644 apps/hid-keyboard-icon.js create mode 100644 apps/hid-keyboard.js create mode 100644 apps/hid-keyboard.json create mode 100644 apps/hid-keyboard.png create mode 100644 apps/hid-music-icon.js create mode 100644 apps/hid-music.js create mode 100644 apps/hid-music.json create mode 100644 apps/hid-music.png diff --git a/apps.json b/apps.json index 976c3c8ad..2e977475e 100644 --- a/apps.json +++ b/apps.json @@ -162,6 +162,28 @@ {"name":"*swatch","url":"stopwatch-icon.js","evaluate":true} ] }, + { "id": "hidmsic", + "name": "Bluetooth Music Controls", + "icon": "hid-music.png", + "description": "Enable HID in settings, pair with your phone, then use this app to control music from your watch!", + "tags": "bluetooth", + "storage": [ + {"name":"+hidmsic","url":"hid-music.json"}, + {"name":"-hidmsic","url":"hid-music.js"}, + {"name":"*hidmsic","url":"hid-music-icon.js","evaluate":true} + ] + }, + { "id": "hidkbd", + "name": "Bluetooth Keyboard", + "icon": "hid-keyboard.png", + "description": "Enable HID in settings, pair with your phone/PC, then use this app to control other apps", + "tags": "bluetooth", + "storage": [ + {"name":"+hidkbd","url":"hid-keyboard.json"}, + {"name":"-hidkbd","url":"hid-keyboard.js"}, + {"name":"*hidkbd","url":"hid-keyboard-icon.js","evaluate":true} + ] + }, { "id": "animals", "name": "Animals Game", "icon": "animals.png", diff --git a/apps/hid-keyboard-icon.js b/apps/hid-keyboard-icon.js new file mode 100644 index 000000000..ca63665de --- /dev/null +++ b/apps/hid-keyboard-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwhC/AH4A/AHeIDC+AC60IC/51ELoIXTCYMIDISLpC/67dxAAJHBYsLhAYKLhgXXHhWAdoQbBApAvhBgYcCAogXkI64XYhDtII/oMUERTyDABJ0FPI4A/AH4A/AGY=")) diff --git a/apps/hid-keyboard.js b/apps/hid-keyboard.js new file mode 100644 index 000000000..9ef95eb8a --- /dev/null +++ b/apps/hid-keyboard.js @@ -0,0 +1,86 @@ +var storage = require('Storage'); + +const settings = storage.readJSON('@settings') || { HID: false }; + +var sendHid, next, prev, toggle, up, down, profile; + +if (settings.HID) { + profile = 'Keyboard'; + sendHid = function (code, cb) { + try { + NRF.sendHIDReport([2,0,0,code,0,0,0,0,0], () => { + NRF.sendHIDReport([2,0,0,0,0,0,0,0,0], () => { + if (cb) cb(); + }); + }); + } catch(e) { + print(e); + } + }; + next = function (cb) { sendHid(0x4f, cb); }; + prev = function (cb) { sendHid(0x50, cb); }; + toggle = function (cb) { sendHid(0x2c, cb); }; + up = function (cb) {sendHid(0x52, cb); }; + down = function (cb) { sendHid(0x51, cb); }; +} else { + E.showMessage('HID disabled'); + setTimeout(load, 1000); +} + +function drawApp() { + g.clear(); + g.setFont("6x8",2); + g.setFontAlign(0,0); + g.drawString(profile, 120, 120); + const d = g.getWidth() - 18; + + function c(a) { + return { + width: 8, + height: a.length, + bpp: 1, + buffer: (new Uint8Array(a)).buffer + }; + } + + g.drawImage(c([16,56,124,254,16,16,16,16]),d,40); + g.drawImage(c([16,16,16,16,254,124,56,16]),d,194); + g.drawImage(c([0,8,12,14,255,14,12,8]),d,116); +} + +if (next) { + setWatch(function(e) { + var len = e.time - e.lastTime; + if (len > 0.3 && len < 0.9) { + E.showMessage('prev'); + setTimeout(drawApp, 1000); + prev(() => {}); + } else { + E.showMessage('up'); + setTimeout(drawApp, 1000); + up(() => {}); + } + }, BTN1, { edge:"falling",repeat:true,debounce:50}); + + setWatch(function(e) { + var len = e.time - e.lastTime; + if (len > 0.3 && len < 0.9) { + E.showMessage('next'); + setTimeout(drawApp, 1000); + next(() => {}); + } else { + E.showMessage('down'); + setTimeout(drawApp, 1000); + down(() => {}); + } + }, BTN3, { edge:"falling",repeat:true,debounce:50}); + + setWatch(function(e) { + E.showMessage('toggle') + setTimeout(drawApp, 1000); + toggle(); + }, BTN2, { edge:"falling",repeat:true,debounce:50}); + + drawApp(); +} + diff --git a/apps/hid-keyboard.json b/apps/hid-keyboard.json new file mode 100644 index 000000000..77e848a95 --- /dev/null +++ b/apps/hid-keyboard.json @@ -0,0 +1,5 @@ +{ + "name": "Keyboard Control", + "icon": "*hidkbd", + "src": "-hidkbd" +} diff --git a/apps/hid-keyboard.png b/apps/hid-keyboard.png new file mode 100644 index 0000000000000000000000000000000000000000..19aec3c05b794809eae76077da580c604f981c42 GIT binary patch literal 506 zcmV&(fVX&)lQkODWP$9~zxmoIHO8{0cs!=+0aVFEEh#Mnrn((KgzLy9_SD2DG(jJL z3I|bZO2&XUKHDM4D1e5Nj#`(pC+T~t5!-mw=rtjwp?QeAhgX1$@V)Pie4-Gx(<@u9h&#<}y zF?fK0uBMk4iY^|k$Ef}R5M|re1l#|CCV=Os>T_EIY#V3*c&N&?T9lDwa%>^I;HB#ld_5-jY=EeDzG8vfqF+kTfoZ wlBVcqp}4rSP|^YlrR)v36mmEm4o6w@0yuf5j`FMk(f|Me07*qoM6N<$g18aoQvd(} literal 0 HcmV?d00001 diff --git a/apps/hid-music-icon.js b/apps/hid-music-icon.js new file mode 100644 index 000000000..6a0c64b9c --- /dev/null +++ b/apps/hid-music-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwhC/AH4A5xGICquZzAVUAAIXQCogXQCoxHPCox0BxIXNxIVFBAQXPUAwXPBw4XowAvuC/4X/C9sIC6kIxGZzIXSFgIWBC6QWEC6RECAAOJwAXQFwoXLxAqBC4MICweZCxhWEC4mICxxuDA4I3BCxQ/FQxpyEK6AucC4idMI5OICyQwBQpgA/AH4Au")) diff --git a/apps/hid-music.js b/apps/hid-music.js new file mode 100644 index 000000000..f106b67ef --- /dev/null +++ b/apps/hid-music.js @@ -0,0 +1,85 @@ +var storage = require('Storage'); + +const settings = storage.readJSON('@settings') || { HID: false }; + +var sendHid, next, prev, toggle, up, down, profile; + +if (settings.HID) { + profile = 'Music'; + sendHid = function (code, cb) { + try { + NRF.sendHIDReport([1,code], () => { + NRF.sendHIDReport([1,0], () => { + if (cb) cb(); + }); + }); + } catch(e) { + print(e); + } + }; + next = function (cb) { sendHid(0x01, cb); }; + prev = function (cb) { sendHid(0x02, cb); }; + toggle = function (cb) { sendHid(0x10, cb); }; + up = function (cb) {sendHid(0x40, cb); }; + down = function (cb) { sendHid(0x80, cb); }; +} else { + E.showMessage('HID disabled'); + setTimeout(load, 1000); +} + +function drawApp() { + g.clear(); + g.setFont("6x8",2); + g.setFontAlign(0,0); + g.drawString(profile, 120, 120); + const d = g.getWidth() - 18; + + function c(a) { + return { + width: 8, + height: a.length, + bpp: 1, + buffer: (new Uint8Array(a)).buffer + }; + } + + g.drawImage(c([16,56,124,254,16,16,16,16]),d,40); + g.drawImage(c([16,16,16,16,254,124,56,16]),d,194); + g.drawImage(c([0,8,12,14,255,14,12,8]),d,116); +} + +if (next) { + setWatch(function(e) { + var len = e.time - e.lastTime; + if (len > 0.3 && len < 0.9) { + E.showMessage('prev'); + setTimeout(drawApp, 1000); + prev(() => {}); + } else { + E.showMessage('up'); + setTimeout(drawApp, 1000); + up(() => {}); + } + }, BTN1, { edge:"falling",repeat:true,debounce:50}); + + setWatch(function(e) { + var len = e.time - e.lastTime; + if (len > 0.3 && len < 0.9) { + E.showMessage('next'); + setTimeout(drawApp, 1000); + next(() => {}); + } else { + E.showMessage('down'); + setTimeout(drawApp, 1000); + down(() => {}); + } + }, BTN3, { edge:"falling",repeat:true,debounce:50}); + + setWatch(function(e) { + E.showMessage('toggle') + setTimeout(drawApp, 1000); + toggle(); + }, BTN2, { edge:"falling",repeat:true,debounce:50}); + + drawApp(); +} diff --git a/apps/hid-music.json b/apps/hid-music.json new file mode 100644 index 000000000..23a1e39d2 --- /dev/null +++ b/apps/hid-music.json @@ -0,0 +1,5 @@ +{ + "name": "Music Control", + "icon": "*hidmsic", + "src": "-hidmsic" +} diff --git a/apps/hid-music.png b/apps/hid-music.png new file mode 100644 index 0000000000000000000000000000000000000000..923b5aa0e157bd3c8e32bfd5ce758da2cc8166fc GIT binary patch literal 632 zcmV-;0*C#HP)+gpH?nhpwLAjH%N$)U#%yap|A zfWjsPUE+oZSPY4wjPe5f$aW%Ok{AgJP=a@8Ttr*gd-uni;(py)_ntXtS2JUi_;!J!t=lqd)HeLH>e#l*t#m z*01afFMJdItOEo&0XiTa_+GKU`E}NXOVO>R!d0LF+L*lCnJ+k(x}}t{0kS580D1%D zInV}v##Nhp6Hg|~IQIBRTxtg!*ICe|JpI<2~(s|rg%1whe(AYIVyVt><1#N`ws z&E%u<+M=KLUjwyi=Tu}zRPUbuE$KaA`~`kgn>Anjx4@NIXM^U`z^Dg~%4>@%gfc%b zi~?xhf5ind4+a5-POGkPKTR`H2pvF_CutgqO6UM8dM8aIQ8DR(a%wJOFz-$LD``QK z0EcmlNdg){!Z$H=;}%ocjjItPd=sNvaf_+Qc3h1hM*mBO&eL}w%TWrc$WE!}-ivZ~ z8fKeVaxLIELY+}=tgQ(5W?~ee)N{Xy%41+;aBUFXQ`$v SUX6wT0000Promise.resolve(); if (!s.beep) Bangle.beep=()=>Promise.resolve(); Bangle.setLCDTimeout(s.timeout); if (!s.timeout) Bangle.setLCDPower(1); E.setTimeZone(s.timezone); -})(); - +})()