diff --git a/README.md b/README.md index cdbc7b24d..ee1173ffe 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ Bangle.js App Loader (and Apps) Try it live at [banglejs.com/apps](https://banglejs.com/apps) -### How does it work? +## How does it work? * A list of apps is in `apps.json` * Each element references an app in `apps/` which is uploaded @@ -12,7 +12,7 @@ it with the files it sees in the watch's storage. * To upload an app, BangleAppLoader checks the files that are listed in `apps.json`, loads them, and sends them over Web Bluetooth. -### What filenames are used +## What filenames are used Filenames in storage are limited to 8 characters. To easily distinguish between file types, we use the following: @@ -22,16 +22,21 @@ easily distinguish between file types, we use the following: * `-stuff` is JS code * `=stuff` is JS code for stuff that is run at boot time - eg. handling settings or creating widgets on the clock screen -### Developing your own app +## Developing your own app + +* Head over to [the Web IDE](https://www.espruino.com/ide/) and ensure `Save on Send` in settings set to the *default setting* of `To RAM` +* We'd recommend that you start off using code from 'Example Applications' (below) to get started... +* Load [`app.js`](apps/_example_app/app.js) or [`widget.js`](apps/_example_widget/widget.js) into the IDE and start developing. +* The `Upload` button will load your app to Bangle.js temporarily + +## Adding your app to the menu -* Start writing your code in the IDE, with `Save on Send` in settings set to -the *default* of `To RAM` * Come up with a unique 7 character name, we'll assume `7chname` -* When you have your app as you want it, add it as a file in `apps/`, lets assume `apps/7chname/my-great-app.js` -* Create `apps/7chname/my-great-app.png` as a 48px icon -* Use http://www.espruino.com/Image+Converter to create as 1 bit, 4 bit or 8 bit Web Palette "Image String" and save it -as `apps/7chname/my-great-app-icon.js` -* Create an entry in `apps/7chname/my-great-app.json` as follows: +* Create a folder called `apps/`, lets assume `apps/7chname` +* We'd recommend that you copy files from 'Example Applications' (below) as a base, or... +* `apps/7chname/app.png` should be a 48px icon +* Use http://www.espruino.com/Image+Converter to create `apps/7chname/app-icon.js`, using a 1 bit, 4 bit or 8 bit Web Palette "Image String" +* Create an entry in `apps/7chname/app.json` as follows: ``` { @@ -46,18 +51,112 @@ as `apps/7chname/my-great-app-icon.js` ``` { "id": "7chname", "name": "My app's human readable name", - "icon": "my-great-app.png", + "icon": "app.png", "description": "A detailed description of my great app", "tags": "", "storage": [ - {"name":"+7chname","url":"my-great-app.json"}, - {"name":"-7chname","url":"my-great-app.js"}, - {"name":"*7chname","url":"my-great-app-icon.js","evaluate":true} + {"name":"+7chname","url":"app.json"}, + {"name":"-7chname","url":"app.js"}, + {"name":"*7chname","url":"app-icon.js","evaluate":true} ], }, ``` -### `apps.json` format +## Testing + +### Online + +This is the best way to test... + +* Fork the https://github.com/espruino/BangleApps git repository +* Add your files +* Go to GitHub Settings and activate GitHub Pages +* Run your personal `Bangle App Loader` at https://\.github.io/BangleApps/index.html to load apps onto your device +* Your apps should be inside it - if there are problems, check your web browser's 'developer console' for errors + +Be aware of the delay between commits and updates on github.io - it can take a few minutes (and a 'hard refresh' of your browser) for changes to take effect. + +### Offline + +You can add the following to the Espruino Web IDE: + +``` +// replace with your 7chname app name +var appname = "mygreat"; + +require("Storage").write('*'+appname, + // place app-icon.js contents here +); + +// +require("Storage").write("+"+appname,{ + "name":"My Great App","type":"", + "icon":"*"+appname, + "src":"-"+appname, +}); + +require("Storage").write("-"+appname,` +// place contents of app.js here +// be aware of double-quoting templated strings +` +``` + +When you upload code this way, your app will be uploaded to Bangle.js's menu +without you having to use the `Bangle App Loader` + +## Example Applications + +To make the process easier we've come up with some example applications that you can use as a base +when creating your own. Just come up with a unique 7 character name, copy `apps/_example_app` +or `apps/_example_widget` to `apps/7chname`, and add `apps/_example_X/add_to_apps.json` to +`apps.json`. + +### App Example + +The app example is available in [`apps/_example_app`](apps/_example_app) + +Apps are listed in the Bangle.js menu, accessible from a clock app via the middle button. + +* `add_to_apps.json` - insert into `apps.json`, describes the widget to bootloader and loader +* `app.png` - app icon - 48x48px +* `app-icon.js` - JS version of the icon (made with http://www.espruino.com/Image+Converter) for use in Bangle.js's menu +* `app.json` - short app name for Bangle.js menu and storage filenames +* `app.js` - app code + +#### `app-icon.js` + +The icon image and short description is used in the menu entry as selection posibility. + +Use the Espruino [image converter](https://www.espruino.com/Image+Converter) and upload your `app.png` file. + +Follow this steps to create a readable icon as image string. + +1. upload a png file +2. set _X_ Use Compression +3. set _X_ Transparency (optional) +4. set Diffusion: _flat_ +5. set Colours: _1 bit_, _4 bit_ or _8 bit Web Palette_ +6. set Output as: _Image String_ + +Replace this line with the image converter output: + +``` +require("heatshrink").decompress(atob("mEwwJC/AH4A/AH4AgA==")); +``` + +Keep in mind to use this converter for creating images you like to draw with `g.drawImage()` with your app. + + +### Widget Example + +The widget example is available in [`apps/_example_widget`](apps/_example_widget) + +* `add_to_apps.json` - insert into `apps.json`, describes the widget to bootloader and loader +* `widget.json` - short widget name and storage names +* `widget.js` - widget code + + +## `apps.json` format ``` { "id": "appid", // 7 character app id @@ -85,6 +184,87 @@ as `apps/7chname/my-great-app-icon.js` } ``` -### Credits +* name, icon and description present the app in the app loader. +* tags is used for grouping apps in the library, separate multiple entries by comma. Known tags are `tool`, `system`, `clock`, `game`, `sound`, `gps`, `widget` or empty. +* storage is used to identify the app files and how to handle them + +## Coding hints + +- use `g.setFont(.., size)` to multiply the font size, eg ("6x8",3) : "18x24" + +- use `g.drawString(text,x,y,true)` to draw with background color to overwrite existing text + +- use `g.clearRect()` to clear parts of the screen, instead of using `g.clear()` + +- use `g.fillPoly()` or `g.drawImage()` for complex graphic elements + +- using `g.clear()` can cause screen flicker + +- using `g.setLCDBrightness()` can save you power during long periods with lcd on + +- chaining graphics methodes, eg `g.setColor(0xFD20).setFontAlign(0,0).setfont("6x8",3)` + +### Graphic areas + +The screen is parted in a widget and app area for lcd mode `direct`(default). + +| areas | as rectangle or point | +| :-:| :-: | +| Widget | (0,0,239,23) | +| Apps | (0,24,239,239) | +| BTN1 | (230, 55) | +| BTN2 | (230, 140) | +| BTN3 | (230, 210) | +| BTN4 | (0,0,119, 239)| +| BTN5 | (120,0,239,239) | + +- Use `g.setFontAlign(0, 0, 3)` to draw rotated string to BTN1-BTN3 with `g.drawString()`. + +- For BTN4-5 the touch area is named + +## Available colors + +Yuu can use `g.setColor(r,g,b)` OR `g.setColor(16bitnumber)` - some common 16 bit colors are below: + +| color-name | color-value| +| :-: | :-: | +| Black | 0x0000 | +| Navy | 0x000F | +| DarkGreen | 0x03E0 | +| DarkCyan | 0x03EF | +| Maroon | 0x7800 | +| Purple | 0x780F | +| Olive | 0x7BE0 +| LightGray | 0xC618 +| DarkGrey | 0x7BEF +| Blue | 0x001F +| Green | 0x07E0 | +| Cyan | 0x07FF | +| RED | 0xF800 | +| Magenta | 0xF81F | +| Yellow | 0xFFE0 | +| White | 0xFFFF | +| Orange | 0xFD20 | +| GreenYellow | 0xAFE5 | +| Pink | 0xF81F | + +## API Reference + +[Reference](http://www.espruino.com/Reference#software) + +[Bangle Class](https://banglejs.com/reference#Bangle) + +[Graphics Class](https://banglejs.com/reference#Graphics) + + +## 'Testing' folder + +The [`testing`](testing) folder contains snippets of code that might be useful for your apps. + +* `testing/colors.js` - 16 bit colors as name value pairs +* `testing/gpstrack.js` - code to store a GPS track in Bagle.js storage and output it back to the console +* `testing/map` - code for splitting an image into map tiles and then displaying them + +## Credits The majority of icons used for these apps are from [Icons8](https://icons8.com/) - we have a commercial license but icons are also free for Open Source projects. diff --git a/skeleton/add_my-great-app_to_apps.json b/apps/_example_app/add_to_apps.json similarity index 50% rename from skeleton/add_my-great-app_to_apps.json rename to apps/_example_app/add_to_apps.json index dd49bca18..941880a65 100644 --- a/skeleton/add_my-great-app_to_apps.json +++ b/apps/_example_app/add_to_apps.json @@ -1,12 +1,12 @@ // Create an entry in apps.json as follows: { "id": "7chname", "name": "My app's human readable name", - "icon": "my-great-app.png", + "icon": "app.png", "description": "A detailed description of my great app", "tags": "", "storage": [ - {"name":"+7chname","url":"my-great-app.json"}, - {"name":"-7chname","url":"my-great-app.js"}, - {"name":"*7chname","url":"my-great-app-icon.js","evaluate":true} + {"name":"+7chname","url":"app.json"}, + {"name":"-7chname","url":"app.js"}, + {"name":"*7chname","url":"app-icon.js","evaluate":true} ], } diff --git a/skeleton/my-great-app-icon.js b/apps/_example_app/app-icon.js similarity index 100% rename from skeleton/my-great-app-icon.js rename to apps/_example_app/app-icon.js diff --git a/skeleton/my-great-app.js b/apps/_example_app/app.js similarity index 100% rename from skeleton/my-great-app.js rename to apps/_example_app/app.js diff --git a/skeleton/my-great-app.json b/apps/_example_app/app.json similarity index 100% rename from skeleton/my-great-app.json rename to apps/_example_app/app.json diff --git a/apps/_example_app/app.png b/apps/_example_app/app.png new file mode 100644 index 000000000..582cb2e08 Binary files /dev/null and b/apps/_example_app/app.png differ diff --git a/skeleton/add_my-great-widget_to_apps.json b/apps/_example_widget/add_to_apps.json similarity index 59% rename from skeleton/add_my-great-widget_to_apps.json rename to apps/_example_widget/add_to_apps.json index 870875c8e..9bc4a8e6e 100644 --- a/skeleton/add_my-great-widget_to_apps.json +++ b/apps/_example_widget/add_to_apps.json @@ -1,11 +1,11 @@ // Create an entry in apps.json as follows: { "id": "7chname", "name": "My widget's human readable name", - "icon": "my-great-widget.png", + "icon": "widget.png", "description": "A detailed description of my great widget", "tags": "", "storage": [ - {"name":"+7chname","url":"my-great-widget.json"}, - {"name":"-7chname","url":"my-great-widget.js"}, + {"name":"+7chname","url":"widget.json"}, + {"name":"-7chname","url":"widget.js"}, ], } diff --git a/skeleton/my-great-widget.js b/apps/_example_widget/widget.js similarity index 100% rename from skeleton/my-great-widget.js rename to apps/_example_widget/widget.js diff --git a/skeleton/my-great-widget.json b/apps/_example_widget/widget.json similarity index 100% rename from skeleton/my-great-widget.json rename to apps/_example_widget/widget.json diff --git a/apps/_example_widget/widget.png b/apps/_example_widget/widget.png new file mode 100644 index 000000000..582cb2e08 Binary files /dev/null and b/apps/_example_widget/widget.png differ diff --git a/skeleton/README.md b/skeleton/README.md deleted file mode 100644 index 3a6486851..000000000 --- a/skeleton/README.md +++ /dev/null @@ -1,302 +0,0 @@ -The Skeleton files -================== - -Maybe it's helpfull to start with some skeleton files -and avoid some common pitfalls, as starting from scratch. - -Take a look into the sections and use the files to quickly start programming Bangle.js apps and widgets. - -* Start with choosing a _7chname_ id, eg _mygreat_. - -* Clock apps use prefix _clock_ for the name, eg _clock-mygreat_ - -* Use prefix _widget_ when writing a widget. eg _widget-mygreat_ - -| files | target location app/ | content | -| :-- | :-- | :-- | -|_for apps_ -|add\_my-great-app\_to\_apps.json| insert into apps.json|describes your app to bootloader and library | -|my-great-app.json| 7chname/ | short app-name and storage names | -|my-great-app.js| 7chname/ | your app code| -|my-great-app-icon.js| 7chname/ | decoded version of the png file | -|_for widgets_ -|add\_my-great-widget\_to\_apps.json| insert into apps.json|describes my widget to bootloader and library | -|my-great-widget.json| 7chname/ | short widget name and storage names | -|my-great-widget.js| 7chname/ | widget code | -|_some snippets_ -|colors.js| - | valid colors as name value pair | -|wrap_my-great-app.js|-| wrapper to store app or widget data and send to device for testing| - -## Files for APP's - -To write a app you need a few files in folder _apps/7chname_ and add a few lines of JSON to file apps.json - -Apps are listed in Bangle.js menue, accessable from a clock app via middle button. - -### add\_my-great-app\_to\_apps.json - -``` -{ "id": "7chname", - "name": "My app's human readable name", - "icon": "my-great-app.png", - "description": "A detailed description of my great app", - "tags": "", - "storage": [ - {"name":"+7chname","url":"my-great-app.json"}, - {"name":"-7chname","url":"my-great-app.js"}, - {"name":"*7chname","url":"my-great-app-icon.js","evaluate":true} - ], -}, -``` -- id is the unique app identified. -- name, icon and description present the app in the library. -- tags is used for grouping apps in the library, separate multiple entries by comma. -- storage is used to identify the app files and how to handle them, like "evaluate": true | false (dafault) - -Known tags: `tool`, `system`, `clock`, `game`, `sound`, `gps`, `widget` or empty. - -Copy and paste lines from `add_my-great-app_to_apps.json`. - -### my-great-app.json - -``` -{ - "name":"Short Name", - "icon":"*7chname", - "src":"-7chname" -} -``` - -The Storage module is _8chname_ based, so all app parts are only allowed _7chname_ in length, firstchar is reserved as content type identifier. - -### my-great-app.js - -Write your app code as encapsulation using anonymous functions with private functional scope. - -``` -(() => { - - // section for const and vars if needed - - ... - - // section for functions, classes - - ... - - function < your main function > () { - - ... - - } - - // special function to handle display switch on - Bangle.on('lcdPower', (on) => { - if (on) { - (); - }}); - - // clear screen and launch - g.clear(); - (); - -})(); -``` - -If you like store and restore data with your app, than use the prefix _@_ and your _7chname_, eg _@mygreat_ as name. - -Make sure to read [Coding Hints](#coding-hints). - -### my-great-app.png - -The png file is displayed in the app loader next to the app name. - -Use your favorite icon creator and go for a 48x48 png file. - -Check avaiable colors to draw a fancy colored icon for your app. - -### my-great-app-icon.js - -The icon image and short description is used in the menue entry as selection posibility. - -Use the Espruino [image converter](https://www.espruino.com/Image+Converter) and upload your my-great-app.png file. - -Follow this steps to create a readable icon as image string. - -1. upload a png file -2. set _X_ Use Compression -3. set _X_ Transparency -4. set Defusion: _flat_ -5. set Colours: _1 bit_, _4 bit_ or _8 bit Web Palette_ -6. set Output as: _Image String_ - -Replace this line with the image converter output - -``` -require("heatshrink").decompress(atob("mEwwJC/AH4A/AH4AgA==")); -``` - -Keep in mind to use this converter for creating images you like to draw with `g.drawImage()` with your app. - -## Files for WIDGET's - -To write a widget you need a few files in folder apps and add a few lines of JSON to file apps.json - -Be aware of this: Widgets are not listed as menue entry. - -### add\_my-great-app\_to\_apps.json - -``` -{ "id": "7chname", - "name": "My widget's human readable name", - "icon": "my-great-widget.png", - "description": "A detailed description of my great widget", - "tags": "widget", - "storage": [ - {"name":"+7chname","url":"my-great-widget.json"}, - {"name":"-7chname","url":"my-great-widget.js"}, - ], -}, -``` -### my-great-widget.js - -Write your widget code as encapsulation using anonymous functions with private functional scope. - -``` -(() => { - - // add the width - var xpos = WIDGETPOS.tr-; - WIDGETPOS.tr-=; - - // draw your widget at xpos - function draw() { - - // add your code - - } - - // add your widget - WIDGETS["mywidget"]={draw:draw}; - -})() -``` - -### my-great-widget.png - -Same as my-great-app.png - -### my-great-widget-icon.js - -Same as my-great-app-icon.png - - -## App development and testing - -Use the wrapper technic from file `wrap_my-great-app.js`, copy paste your code and upload Espruino via Web IDE - -Todo: add a wrapper script for this - -``` -// replace with your 7chname app name -var appname = "mygreat"; - -require("Storage").write('*'+appname,` - // place out of image conterver here -`); - -// -require("Storage").write("+"+appname,{ - "name":"My Great App","type":"", - "icon":"*"+appname, - "src":"-"+appname, -}); - -require("Storage").write("-"+appname,` -// place content of my-great-app.json here -` -``` - -Or fork BANGLEJS, got Setting and activate GitHub Pages and you are good to run your personal `Bangle App Launcher` (https://\.github.io/BangleApps/index.html). - -Now you can use the `Bangle App Launcher` to upload and test you new app - -Be aware of the delay between commit and avaiable on github.io - -##### One way to develop and test your work - -1. Use WebIDE for the development -2. Wrap code and run tests on device -3. Run final test with personal `Bangle App Launcher` - -## Appendex - -### API Reference - -[Reference](http://www.espruino.com/Reference#software) - -[Bangle Class](https://banglejs.com/reference#Bangle) - -[Graphics Class](https://banglejs.com/reference#Graphics) - -### Coding hints - -- use `g.setFont(.., size)` to multiply the font size, eg ("6x8",3) : "18x24" - -- use `g.drawString(..,true)` to draw with background color to overwrite existing text - -- use `g.clearRect()` to clear parts of the screen, instead of using `g.clear()` - -- use `g.fillPoly()` or `g.drawImage()` for complex graphic elements - -- using `g.clear()` can cause screen flicker - -- using `g.setLCDBrightness()` can save you power during long periods with lcd on - -- chaining graphics methodes, eg `g.setColor(0xFD20).setFontAlign(0,0).setfont("6x8",3)` - -### Graphic areas - -The screen is parted in a widget and app area for lcd mode `direct`(default). - -| areas | as rectangle or point | -| :-:| :-: | -| Widget | (0,0,239,23) | -| Apps | (0,24,239,239) | -| BTN1 | (230, 55) | -| BTN2 | (230, 140) | -| BTN3 | (230, 210) | -| BTN4 | (0,0,119, 239)| -| BTN5 | (120,0,239,239) | - -- Use `g.setFontAlign(0, 0, 3)` to draw rotated string to BTN1-BTN3 with `g.drawString()`. - -- For BTN4-5 the touch area is named - -### Available colors - -| color-name | color-value| -| :-: | :-: | -| Black | 0x0000 | -| Navy | 0x000F | -| DarkGreen | 0x03E0 | -| DarkCyan | 0x03EF | -| Maroon | 0x7800 | -| Purple | 0x780F | -| Olive | 0x7BE0 -| LightGray | 0xC618 -| DarkGrey | 0x7BEF -| Blue | 0x001F -| Green | 0x07E0 | -| Cyan | 0x07FF | -| RED | 0xF800 | -| Magenta | 0xF81F | -| Yellow | 0xFFE0 | -| White | 0xFFFF | -| Orange | 0xFD20 | -| GreenYellow | 0xAFE5 | -| Pink | 0xF81F | - - - - diff --git a/skeleton/wrap_my-great-app.js b/skeleton/wrap_my-great-app.js deleted file mode 100644 index de910b3a7..000000000 --- a/skeleton/wrap_my-great-app.js +++ /dev/null @@ -1,15 +0,0 @@ -var appname = 'mygreat'; - -require("Storage").write('*'+appname,` - -`); - -require("Storage").write('+'+appname,{ - "name":"My Great App","type":"", - "icon":"*"+appname, - "src":"-"+appname, -}); - -require("Storage").write("-"+appname,` - -` diff --git a/skeleton/colors.js b/testing/colors.js similarity index 100% rename from skeleton/colors.js rename to testing/colors.js