diff --git a/apps/legoremote/ChangeLog b/apps/legoremote/ChangeLog new file mode 100644 index 000000000..5560f00bc --- /dev/null +++ b/apps/legoremote/ChangeLog @@ -0,0 +1 @@ +0.01: New App! diff --git a/apps/legoremote/README.md b/apps/legoremote/README.md new file mode 100644 index 000000000..a95b7b154 --- /dev/null +++ b/apps/legoremote/README.md @@ -0,0 +1,28 @@ +# LEGO Remote control + +This app allows you to control LEGO models from Bangle.js + +Right now the only supported control device is the Mould King M-0006 +Bluetooth remote for LEGO Power Functions: http://www.espruino.com/LEGO+Power+Functions+Clone + +LEGO Power Functions does not have an official Bluetooth remote controller. Hopefully +in the future this app will be able to support other types of remote (see below). + +## Usage + +Run the app, and ensure you're not connected to your watch via Bluetooth +(a warning will pop up if so). + +Now press the arrow keys on the screen to control the robot. + +It is expected that the robot is controlled by two motors, one on the left +side (connected to the `A` output) and one on the right (connected to the `B` output). + +## Future additions + +In the future it would be great to add: + +* Recording a series of movements and playing them back +* Support for official LEGO bluetooth remotes (via [Pybricks](https://pybricks.com/)) +* Support for different robot styles and configurations +* Using the Bangle's compass (or even GPS) to allow better robot control. diff --git a/apps/legoremote/app-icon.js b/apps/legoremote/app-icon.js new file mode 100644 index 000000000..850e0eda6 --- /dev/null +++ b/apps/legoremote/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEw4X/8H5A4NH/4ABJf4A/AFMC1Uq1QABhWqBYYJDAAegBYWqxWogWohQBCBYWpqsVqoABytVBYUC0u5rf5rf1q/xtQLBhWW/t//2/AYVKBYWX/u//z3B3//rRGCr/1/+H/v9/1/BYn2/lT+v6/oXDlF/4//9/78/5F4epv/X//f7/3+v9I4Wp38b/9v7//+4LD0P/HgN/7f/EgMoBYOlJ4IACDAP1O4QLH6ibCBYI7Br/+qf/iwLC1NIquhq2lquprWAWQVVoNVgtU0NVlQLCZQ7XDbgLWJEgOCdgLZBdwgA/AH4AaA")) diff --git a/apps/legoremote/app.js b/apps/legoremote/app.js new file mode 100644 index 000000000..1c76a54a8 --- /dev/null +++ b/apps/legoremote/app.js @@ -0,0 +1,70 @@ +var lego = require("mouldking"); +lego.start(); +E.on('kill', () => { + // return to normal Bluetooth advertising + NRF.setAdvertising({},{showName:true}); +}); +// You must leave one second after 'start' to allow the remote to be paired + +var arrowIcon = atob("IiiBAAAAwAAAAPwAAAB/gAAAP/AAAB/+AAAP/8AAB//4AAP//wAA///gAH///AA///8AH///4A////wH////gf////D////8f////5/////n////+f////4AP/8AAA//wAAD//AAAP/8AAA//wAAD//AAAH/8AAAf/wAAB//AAAH/8AAAf/gAAB/+AAAH/4AAAf/gAAB/+AAAH/4AAAP/gAAA/+AAAD/wAAAD8AA"); +var controlState = ""; + +Bangle.loadWidgets(); +Bangle.drawWidgets(); +var R = Bangle.appRect; +// we'll divide up into 3x3 +function getBoxCoords(x,y) { + return { + x : R.x + R.w*x/3, + y : R.y + R.h*y/3 + }; +} + +function draw() { + g.reset().clearRect(R); + var c, ninety = Math.PI/2; + var colOn = "#f00", colOff = g.theme.fg; + c = getBoxCoords(1.5, 0.5); + g.setColor(controlState=="up"?colOn:colOff).drawImage(arrowIcon,c.x,c.y,{rotate:0}); + c = getBoxCoords(2.5, 1.5); + g.setColor(controlState=="right"?colOn:colOff).drawImage(arrowIcon,c.x,c.y,{rotate:ninety}); + c = getBoxCoords(0.5, 1.5); + g.setColor(controlState=="left"?colOn:colOff).drawImage(arrowIcon,c.x,c.y,{rotate:-ninety}); + c = getBoxCoords(1.5, 1.5); + g.setColor(controlState=="down"?colOn:colOff).drawImage(arrowIcon,c.x,c.y,{rotate:ninety*2}); + if (NRF.getSecurityStatus().connected) { + c = getBoxCoords(1.5, 2.5); + g.setFontAlign(0,0).setFont("6x8").drawString("WARNING:\nBluetooth Connected\nYou must disconnect\nbefore LEGO will work",c.x,c.y); + } +} +draw(); +NRF.on('connect', draw); +NRF.on('disconnect', draw); + +function setControlState(s) { + controlState = s; + var c = {}; + var speed = 3; + if (s=="up") c={a:-speed,b:-speed}; + if (s=="down") c={a:speed,b:speed}; + if (s=="left") c={a:speed,b:-speed}; + if (s=="right") c={a:-speed,b:speed}; + draw(); + lego.set(c); +} + +Bangle.on('drag',e => { + var x = Math.floor(E.clip((e.x - R.x) * 3 / R.w,0,2.99)); + var y = Math.floor(E.clip((e.y - R.y) * 3 / R.h,0,2.99)); + if (!e.b) { + setControlState(""); + return; + } + if (y==0) { // top row + if (x==1) setControlState("up"); + } else if (y==1) { + if (x==0) setControlState("left"); + if (x==1) setControlState("down"); + if (x==2) setControlState("right"); + } +}); diff --git a/apps/legoremote/app.png b/apps/legoremote/app.png new file mode 100644 index 000000000..727049e2b Binary files /dev/null and b/apps/legoremote/app.png differ diff --git a/apps/legoremote/metadata.json b/apps/legoremote/metadata.json new file mode 100644 index 000000000..c86251860 --- /dev/null +++ b/apps/legoremote/metadata.json @@ -0,0 +1,14 @@ +{ "id": "legoremote", + "name": "LEGO Remote control", + "shortName":"LEGO Remote", + "version":"0.01", + "description": "Use your Bangle.js to control LEGO models. See the README for compatibility", + "icon": "app.png", + "tags": "toy,lego,bluetooth", + "supports" : ["BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"legoremote.app.js","url":"app.js"}, + {"name":"legoremote.img","url":"app-icon.js","evaluate":true} + ] +}