diff --git a/apps.json b/apps.json index 0a6cebba7..35430e235 100644 --- a/apps.json +++ b/apps.json @@ -3,7 +3,7 @@ "id": "fwupdate", "name": "Firmware Update", "version": "0.02", - "description": "Uploads new Espruino firmwares to Bangle.js 2", + "description": "[BETA] Uploads new Espruino firmwares to Bangle.js 2. For now, please use the instructions under https://www.espruino.com/Bangle.js2#firmware-updates", "icon": "app.png", "type": "RAM", "tags": "tools,system", @@ -11,12 +11,12 @@ "custom": "custom.html", "customConnect": true, "storage": [], - "sortorder": -20 + "sortorder": 20 }, { "id": "boot", "name": "Bootloader", - "version": "0.38", + "version": "0.39", "description": "This is needed by Bangle.js to automatically load the clock, menu, widgets and settings", "icon": "bootloader.png", "type": "bootloader", @@ -33,10 +33,11 @@ "id": "hebrew_calendar", "name": "Hebrew Calendar", "shortName": "HebCal", - "version": "0.03", + "version": "0.04", "description": "lists the date according to the hebrew calendar", "icon": "app.png", - "tags": "", + "allow_emulator": false, + "tags": "tool,locale", "supports": [ "BANGLEJS", "BANGLEJS2" @@ -47,6 +48,10 @@ "name": "hebrew_calendar.app.js", "url": "app.js" }, + { + "name": "hebrewDate", + "url": "hebrewDate.js" + }, { "name": "hebrew_calendar.img", "url": "app-icon.js", @@ -54,10 +59,25 @@ } ] }, + { "id": "golfscore", + "name": "Golf Score", + "shortName":"golfscore", + "version":"0.02", + "description": "keeps track of strokes during a golf game", + "icon": "app.png", + "tags": "outdoors", + "allow_emulator": true, + "supports" : ["BANGLEJS","BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"golfscore.app.js","url":"app.js"}, + {"name":"golfscore.img","url":"app-icon.js","evaluate":true} + ] + }, { "id": "messages", "name": "Messages", - "version": "0.11", + "version": "0.16", "description": "App to display notifications from iOS and Gadgetbridge", "icon": "app.png", "type": "app", @@ -72,14 +92,15 @@ {"name":"messages","url":"lib.js"} ], "data": [{"name":"messages.json"},{"name":"messages.settings.json"}], + "screenshots": [{"url":"screenshot.png"},{"url":"screenshot-notify.gif"}], "sortorder": -9 }, { "id": "android", "name": "Android Integration", "shortName": "Android", - "version": "0.04", - "description": "Display notifications/music/etc from Gadgetbridge on Android. This replaces the old Gadgetbridge widget.", + "version": "0.05", + "description": "Display notifications/music/etc sent from the Gadgetbridge app on Android. This replaces the old 'Gadgetbridge' Bangle.js widget.", "icon": "app.png", "tags": "tool,system,messages,notifications", "dependencies": {"messages":"app"}, @@ -95,7 +116,7 @@ { "id": "ios", "name": "iOS Integration", - "version": "0.06", + "version": "0.07", "description": "Display notifications/music/etc from iOS devices", "icon": "app.png", "tags": "tool,system,ios,apple,messages,notifications", @@ -111,7 +132,7 @@ { "id": "health", "name": "Health Tracking", - "version": "0.08", + "version": "0.09", "description": "Logs health data and provides an app to view it (requires firmware 2v10.100 or later)", "icon": "app.png", "tags": "tool,system,health", @@ -146,7 +167,7 @@ { "id": "setting", "name": "Settings", - "version": "0.36", + "version": "0.39", "description": "A menu for setting up Bangle.js", "icon": "settings.png", "tags": "tool,system", @@ -197,7 +218,7 @@ { "id": "locale", "name": "Languages", - "version": "0.13", + "version": "0.14", "description": "Translations for different countries", "icon": "locale.png", "type": "locale", @@ -282,8 +303,8 @@ { "id": "gbridge", "name": "Gadgetbridge", - "version": "0.24", - "description": "(NOT RECOMMENDED) Handles Gadgetbridge notifications from Android. This is now replaced by the 'Android' app.", + "version": "0.25", + "description": "(NOT RECOMMENDED) Displays Gadgetbridge notifications from Android. Please use the 'Android' Bangle.js app instead.", "icon": "app.png", "type": "widget", "tags": "tool,system,android,widget", @@ -533,12 +554,12 @@ { "id": "impwclock", "name": "Imprecise Word Clock", - "version": "0.03", + "version": "0.04", "description": "Imprecise word clock for vacations, weekends, and those who never need accurate time.", "icon": "clock-impword.png", "type": "clock", "tags": "clock", - "supports": ["BANGLEJS"], + "supports": ["BANGLEJS","BANGLEJS2"], "screenshots": [{"url":"bangle1-impercise-word-clock-screenshot.png"}], "allow_emulator": true, "storage": [ @@ -747,7 +768,7 @@ "id": "recorder", "name": "Recorder (BETA)", "shortName": "Recorder", - "version": "0.04", + "version": "0.05", "description": "Record GPS position, heart rate and more in the background, then download to your PC.", "icon": "app.png", "tags": "tool,outdoors,gps,widget", @@ -824,7 +845,7 @@ { "id": "weather", "name": "Weather", - "version": "0.12", + "version": "0.14", "description": "Show Gadgetbridge weather report", "icon": "icon.png", "screenshots": [{"url":"screenshot.png"}], @@ -950,7 +971,7 @@ { "id": "widbt", "name": "Bluetooth Widget", - "version": "0.07", + "version": "0.08", "description": "Show the current Bluetooth connection status in the top right of the clock", "icon": "widget.png", "type": "widget", @@ -1127,7 +1148,7 @@ { "id": "qrcode", "name": "Custom QR Code", - "version": "0.03", + "version": "0.05", "description": "Use this to upload a customised QR code to Bangle.js", "icon": "app.png", "tags": "qrcode", @@ -1480,7 +1501,7 @@ { "id": "gpsinfo", "name": "GPS Info", - "version": "0.05", + "version": "0.06", "description": "An application that displays information about altitude, lat/lon, satellites and time", "icon": "gps-info.png", "type": "app", @@ -1569,7 +1590,7 @@ { "id": "widpedom", "name": "Pedometer widget", - "version": "0.19", + "version": "0.20", "description": "Daily pedometer widget", "icon": "widget.png", "type": "widget", @@ -1678,14 +1699,15 @@ "id": "rtorch", "name": "Red Torch", "shortName": "RedTorch", - "version": "0.01", - "description": "Turns screen RED to help you see in the dark without breaking your night vision. Select from the launcher or press BTN3,BTN1,BTN3,BTN1 quickly to start when in any app that shows widgets", + "version": "0.02", + "description": "Turns screen RED to help you see in the dark without breaking your night vision. Select from the launcher or on Bangle 1 press BTN3,BTN1,BTN3,BTN1 quickly to start when in any app that shows widgets", "icon": "app.png", "tags": "tool,torch", - "supports": ["BANGLEJS"], + "supports": ["BANGLEJS","BANGLEJS2"], + "allow_emulator": true, "storage": [ {"name":"rtorch.app.js","url":"app.js"}, - {"name":"rtorch.wid.js","url":"widget.js"}, + {"name":"rtorch.wid.js","url":"widget.js", "supports": ["BANGLEJS"]}, {"name":"rtorch.img","url":"app-icon.js","evaluate":true} ] }, @@ -2005,7 +2027,7 @@ "id": "chronowid", "name": "Chrono Widget", "shortName": "Chrono Widget", - "version": "0.04", + "version": "0.05", "description": "Chronometer (timer) which runs as widget.", "icon": "app.png", "tags": "tool,widget", @@ -2147,21 +2169,22 @@ { "id": "snek", "name": "The snek game", "shortName":"Snek", - "version": "0.01", + "version": "0.02", "description": "A snek game where you control a snek to eat all the apples!", - "icon": "snek-icon.js", + "screenshots": [{"url":"screenshot_snek.png"}], + "icon": "snek.png", "supports": ["BANGLEJS2"], "tags": "game,fun", "storage": [ {"name":"snek.app.js","url":"snek.js"}, - {"name":"snek.img","url":"snek-icon.js","evaluate":true} + {"name":"snek.img","url":"snek.icon.js","evaluate":true} ] }, { "id": "calculator", "name": "Calculator", "shortName": "Calculator", - "version": "0.04", + "version": "0.05", "description": "Basic calculator reminiscent of MacOs's one. Handy for small calculus.", "icon": "calculator.png", "screenshots": [{"url":"screenshot_calculator.png"}], @@ -2406,7 +2429,7 @@ { "id": "calendar", "name": "Calendar", - "version": "0.03", + "version": "0.05", "description": "Simple calendar", "icon": "calendar.png", "screenshots": [{"url":"screenshot_calendar.png"}], @@ -3274,7 +3297,7 @@ { "id": "dtlaunch", "name": "Desktop Launcher", - "version": "0.05", + "version": "0.07", "description": "Desktop style App Launcher with six (four for Bangle 2) apps per page - fast access if you have lots of apps installed.", "screenshots": [{"url":"shot1.png"},{"url":"shot2.png"},{"url":"shot3.png"}], "icon": "icon.png", @@ -3285,8 +3308,11 @@ "storage": [ {"name":"dtlaunch.app.js","url":"app-b1.js", "supports": ["BANGLEJS"]}, {"name":"dtlaunch.app.js","url":"app-b2.js", "supports": ["BANGLEJS2"]}, + {"name":"dtlaunch.settings.js","url":"settings-b1.js", "supports": ["BANGLEJS"]}, + {"name":"dtlaunch.settings.js","url":"settings-b2.js", "supports": ["BANGLEJS2"]}, {"name":"dtlaunch.img","url":"app-icon.js","evaluate":true} - ] + ], + "data": [{"name":"dtlaunch.json"}] }, { "id": "HRV", @@ -3452,8 +3478,8 @@ { "id": "speedalt2", "name": "GPS Adventure Sports II", - "shortName": "GPS Adv Sport II", - "version": "0.07", + "shortName":"GPS Adv Sport II", + "version":"1.10", "description": "GPS speed, altitude and distance to waypoint display. Designed for easy viewing and use during outdoor activities such as para-gliding, hang-gliding, sailing, cycling etc.", "icon": "app.png", "type": "app", @@ -3870,7 +3896,7 @@ "id": "qmsched", "name": "Quiet Mode Schedule and Widget", "shortName": "Quiet Mode", - "version": "0.04", + "version": "0.06", "description": "Automatically turn Quiet Mode on or off at set times, and change LCD options while Quiet Mode is active.", "icon": "app.png", "screenshots": [{"url":"screenshot_b1_main.png"},{"url":"screenshot_b1_edit.png"},{"url":"screenshot_b1_lcd.png"}, @@ -3988,11 +4014,12 @@ { "id": "thermom", "name": "Thermometer", - "version": "0.03", - "description": "Displays the current temperature in degree Celsius, updated every 20 seconds", + "version": "0.05", + "description": "Displays the current temperature in degree Celsius/Fahrenheit (depending on locale), updates every 10 seconds with average of last 5 readings.", "icon": "app.png", "tags": "tool", - "supports": ["BANGLEJS"], + "supports": ["BANGLEJS", "BANGLEJS2"], + "screenshots": [{"url":"screenshot.png"}], "allow_emulator": true, "storage": [ {"name":"thermom.app.js","url":"app.js"}, @@ -4037,7 +4064,7 @@ { "id": "hcclock", "name": "Hi-Contrast Clock", - "version": "0.02", + "version": "0.03", "description": "Hi-Contrast Clock : A simple yet very bold clock that aims to be readable in high luninosity environments. Uses big 10x5 pixel digits. Use BTN 1 to switch background and foreground colors.", "icon": "hcclock-icon.png", "type": "clock", @@ -4054,7 +4081,7 @@ "id": "thermomF", "name": "Fahrenheit Temp", "version": "0.01", - "description": "A modification of the Thermometer App to display temprature in Fahrenheit", + "description": "[NOT RECOMMENDED] A modification of the Thermometer App to display temprature in Fahrenheit. Please use the 'Thermometer App' and install 'Languages' to get the temperature in the correct format for your locale.", "icon": "thermf.png", "tags": "tool", "supports": ["BANGLEJS"], @@ -4117,14 +4144,17 @@ { "id": "vectorclock", "name": "Vector Clock", - "version": "0.02", + "version": "0.03", "description": "A digital clock that uses the built-in vector font.", "icon": "app.png", "type": "clock", "tags": "clock", - "supports": ["BANGLEJS"], + "supports": ["BANGLEJS", "BANGLEJS2"], "allow_emulator": true, - "screenshots": [{"url":"bangle1-vector-clock-screenshot.png"}], + "screenshots": [ + {"url":"bangle2-vector-clock-screenshot.png"}, + {"url":"bangle1-vector-clock-screenshot.png"} + ], "storage": [ {"name":"vectorclock.app.js","url":"app.js"}, {"name":"vectorclock.img","url":"app-icon.js","evaluate":true} @@ -4180,10 +4210,10 @@ "id": "pastel", "name": "Pastel Clock", "shortName": "Pastel", - "version": "0.08", + "version": "0.09", "description": "A Configurable clock with custom fonts and background. Has a cyclic information line that includes, day, date, battery, sunrise and sunset times", "icon": "pastel.png", - "dependencies": {"mylocation":"app"}, + "dependencies": {"mylocation":"app", "widpedom":"app"}, "screenshots": [{"url":"screenshot_pastel.png"}], "type": "clock", "tags": "clock", @@ -4442,9 +4472,9 @@ "name": "A Battery Widget (with percentage)", "shortName":"A Battery Widget", "icon": "widget.png", - "version":"1.01", + "version":"1.02", "type": "widget", - "supports": ["BANGLEJS2"], + "supports": ["BANGLEJS", "BANGLEJS2"], "readme": "README.md", "description": "Simple and slim battery widget with charge status and percentage", "tags": "widget,battery", @@ -4457,7 +4487,7 @@ "name": "LCARS Clock", "shortName":"LCARS", "icon": "lcars.png", - "version":"0.06", + "version":"0.08", "readme": "README.md", "supports": ["BANGLEJS2"], "description": "Library Computer Access Retrieval System (LCARS) clock.", @@ -4466,7 +4496,8 @@ "screenshots": [{"url":"screenshot.png"}], "storage": [ {"name":"lcars.app.js","url":"lcars.app.js"}, - {"name":"lcars.img","url":"lcars.icon.js","evaluate":true} + {"name":"lcars.img","url":"lcars.icon.js","evaluate":true}, + {"name":"lcars.settings.js","url":"lcars.settings.js"} ] }, { "id": "binwatch", @@ -4621,7 +4652,7 @@ "id": "sensible", "name": "SensiBLE", "shortName": "SensiBLE", - "version": "0.03", + "version": "0.05", "description": "Collect, display and advertise real-time sensor data.", "icon": "sensible.png", "screenshots": [ @@ -4666,6 +4697,8 @@ "tags": "tool,timer", "readme":"README.md", "supports":["BANGLEJS2"], + "screenshots": [{"url":"screenshot1.png"},{"url":"screenshot2.png"},{"url":"screenshot3.png"}], + "allow_emulator": true, "storage": [ {"name":"a_speech_timer.app.js","url":"app.js"}, {"name":"a_speech_timer.img","url":"app-icon.js","evaluate":true} @@ -4694,8 +4727,9 @@ "id": "pebble", "name": "Pebble Clock", "shortName": "Pebble", - "version": "0.04", + "version": "0.06", "description": "A pebble style clock to keep the rebellion going", + "dependencies": {"widpedom":"app"}, "readme": "README.md", "icon": "pebble.png", "screenshots": [{"url":"pebble_screenshot.png"}], @@ -4711,7 +4745,7 @@ { "id": "pooqroman", "name": "pooq Roman watch face", "shortName":"pooq Roman", - "version":"0.0.0", + "version":"0.03", "description": "A classic watch face with a certain dynamicity. Most amusing in 24h mode. Slide up to show more hands, down for less(!). By design does not support standard widgets, sorry!", "icon": "app.png", "type": "clock", @@ -4746,7 +4780,7 @@ { "id": "weatherClock", "name": "Weather Clock", - "version": "0.03", + "version": "0.05", "description": "A clock which displays current weather conditions (requires Gadgetbridge and Weather apps).", "icon": "app.png", "screenshots": [{"url":"screens/screen1.png"}], @@ -4806,6 +4840,25 @@ {"name": "flow.img", "url": "app-icon.js","evaluate": true } ] }, + { "id": "tinydraw", + "name": "TinyDraw", + "shortName":"TinyDraw", + "version":"0.01", + "type": "app", + "description": "Draw stuff in your wrist", + "icon": "app.png", + "allow_emulator": true, + "tags": "tools, keyboard, text, scribble", + "supports" : ["BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"tinydraw.app.js","url":"app.js"}, + {"name":"tinydraw.img","url":"app-icon.js","evaluate":true} + ], + "screenshots":[ + { "url":"screenshot.png" } + ] + }, { "id": "scribble", "name": "Scribble", "shortName":"Scribble", @@ -4829,9 +4882,10 @@ "id": "ptlaunch", "name": "Pattern Launcher", "shortName": "Pattern Launcher", - "version": "0.02", + "version": "0.13", "description": "Directly launch apps from the clock screen with custom patterns.", "icon": "app.png", + "screenshots": [{"url":"manage_patterns_light.png"}], "tags": "tools", "supports": ["BANGLEJS2"], "readme": "README.md", @@ -4842,20 +4896,466 @@ ], "data": [{"name":"ptlaunch.patterns.json"}] }, - { "id": "clicompleteclk", - "name": "CLI complete clock", - "shortName":"CLI cmplt clock", - "version":"0.02", - "description": "Command line styled clock with lots of information", - "icon": "app.png", - "allow_emulator": true, - "type": "clock", - "tags": "clock,cli,command,bash,shell,weather,hrt", - "supports" : ["BANGLEJS", "BANGLEJS2"], - "readme": "README.md", - "storage": [ - {"name":"clicompleteclk.app.js","url":"app.js"}, - {"name":"clicompleteclk.img","url":"app-icon.js","evaluate":true} + { "id": "slimehunt", + "name": "Slime Hunt", + "shortName":"SlimeHunt", + "icon": "app.png", + "version":"0.02", + "description": "Fight against slimes in turn based combat, try to get the highscore!", + "tags": "rpg,slime", + "supports" : ["BANGLEJS"], + "readme": "README.md", + "storage": [ + {"name":"slimehunt.app.js","url":"app.js"}, + {"name":"slimehunt.img","url":"app-icon.js","evaluate":true} ] -} + }, + { + "id": "rebble", + "name": "Rebble Clock", + "shortName": "Rebble", + "version": "0.03", + "description": "A Pebble style clock, with configurable background, three sidebars including steps, day, date, sunrise, sunset, long live the rebellion", + "readme": "README.md", + "icon": "rebble.png", + "dependencies": {"mylocation":"app", "widpedom":"app"}, + "screenshots": [{"url":"screenshot_rebble.png"}], + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS2"], + "storage": [ + {"name":"rebble.app.js","url":"rebble.app.js"}, + {"name":"rebble.settings.js","url":"rebble.settings.js"}, + {"name":"rebble.img","url":"rebble.icon.js","evaluate":true} + ] + }, + { "id": "snaky", + "name": "Snaky", + "shortName":"Snaky", + "version":"0.01", + "description": "The classic snake game. Eat apples and don't bite your tail. Control the snake with the touch screen.", + "tags": "game,fun", + "icon": "snaky.png", + "supports" : ["BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"snaky.app.js","url":"snaky.js"}, + {"name":"snaky.img","url":"snaky-icon.js","evaluate":true} + ] + }, + { + "id": "clicompleteclk", + "name": "CLI complete clock", + "shortName":"CLI cmplt clock", + "version":"0.03", + "description": "Command line styled clock with lots of information", + "icon": "app.png", + "allow_emulator": true, + "type": "clock", + "tags": "clock,cli,command,bash,shell,weather,hrt", + "supports" : ["BANGLEJS", "BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"clicompleteclk.app.js","url":"app.js"}, + {"name":"clicompleteclk.img","url":"app-icon.js","evaluate":true}, + {"name":"clicompleteclk.settings.js","url":"settings.js"} + ], + "data": [{"name":"clicompleteclk.json"}] + }, + { + "id":"awairmonitor", + "name":"Awair Monitor", + "icon": "app.png", + "screenshots": [{"url":"screenshot.png"}], + "allow_emulator": true, + "version":"0.03", + "description": "Displays the level of CO2, VOC, PM 2.5, Humidity and Temperature, from your Awair device.", + "type": "clock", + "tags": "clock,tool,health", + "readme":"README.md", + "supports":["BANGLEJS2"], + "storage": [ + {"name":"awairmonitor.app.js","url":"app.js"}, + {"name":"awairmonitor.img","url":"app-icon.js","evaluate":true} + ] + }, + { "id": "pooqround", + "name": "pooq Round watch face", + "shortName":"pooq Round", + "version":"0.01", + "description": "A 24 hour analogue watchface with high legibility and a novel style.", + "icon": "app.png", + "type": "clock", + "tags": "clock", + "supports" : ["BANGLEJS2"], + "allow_emulator":true, + "readme": "README.md", + "storage": [ + {"name":"pooqround.app.js","url":"app.js"}, + {"name":"pooqround.img","url":"app-icon.js","evaluate":true} + ], + "data": [ + {"name":"pooqround.json"} + ] + }, + { + "id": "coretemp", + "name": "CoreTemp", + "version": "0.02", + "description": "Display CoreTemp device sensor data", + "icon": "coretemp.png", + "type": "app", + "tags": "health", + "readme": "README.md", + "supports": ["BANGLEJS","BANGLEJS2"], + "storage": [ + {"name":"coretemp.wid.js","url":"widget.js"}, + {"name":"coretemp.app.js","url":"coretemp.js"}, + {"name":"coretemp.settings.js","url":"settings.js"}, + {"name":"coretemp.img","url":"coretemp-icon.js","evaluate":true}, + {"name":"coretemp.boot.js","url":"boot.js"} + ], + "data": [{"name":"coretemp.json","url":"app-settings.json"}], + "screenshots": [{"url":"screenshot.png"}] + }, + { + "id": "showimg", + "name": "simple image viewer", + "shortName":"showImage", + "version":"0.2", + "description": "Displays the image in \"showimg.user.img\". The file has to be uploaded via the espruino IDE. Returns to watch face after 60s or button push. I use it to display my vaccination certificate.", + "icon": "app.png", + "tags": "tool", + "supports" : ["BANGLEJS2"], + "storage": [ + {"name":"showimg.app.js","url":"app.js"}, + {"name":"showimg.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "lapcounter", + "name": "Lap Counter", + "version": "0.01", + "description": "Click button to count laps. Shows count and total time snapshot (like a stopwatch, but laid back).", + "icon": "app.png", + "screenshots": [{"url":"screenshot.png"}], + "type": "app", + "tags": "tool,outdoors", + "readme":"README.md", + "supports": ["BANGLEJS", "BANGLEJS2"], + "allow_emulator": true, + "storage": [ + {"name":"lapcounter.app.js","url":"app.js"}, + {"name":"lapcounter.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "pebbled", + "name": "Pebble Clock with distance", + "shortName": "Pebble + distance", + "version": "0.1", + "description": "Fork of Pebble Clock with distance in KM. Both step count and the distance are on the main screen. Default step length = 0.75m (can be changed in settings).", + "readme": "README.md", + "icon": "pebbled.png", + "screenshots": [{"url":"pebble_screenshot.png"}], + "type": "clock", + "tags": "clock,distance", + "supports": ["BANGLEJS2"], + "storage": [ + {"name":"pebbled.app.js","url":"pebbled.app.js"}, + {"name":"pebbled.settings.js","url":"pebbled.settings.js"}, + {"name":"pebbled.img","url":"pebbled.icon.js","evaluate":true} + ] + }, + { "id": "circlesclock", + "name": "Circles clock", + "shortName":"Circles clock", + "version":"0.03", + "description": "A clock with circles for different data at the bottom in a probably familiar style", + "icon": "app.png", + "screenshots": [{"url":"screenshot.png"}], + "dependencies": {"widpedom":"app"}, + "type": "clock", + "tags": "clock", + "supports" : ["BANGLEJS2"], + "allow_emulator":true, + "readme": "README.md", + "storage": [ + {"name":"circlesclock.app.js","url":"app.js"}, + {"name":"circlesclock.img","url":"app-icon.js","evaluate":true}, + {"name":"circlesclock.settings.js","url":"settings.js"} + ], + "data": [ + {"name":"circlesclock.json"} + ] + }, + { "id": "contourclock", + "name": "Contour Clock", + "shortName" : "Contour Clock", + "version":"0.01", + "icon": "app.png", + "description": "A Minimalist clockface with large Digits. Looks best with the dark theme", + "screenshots" : [{"url":"screenshot.png"}], + "tags": "clock", + "allow_emulator":true, + "supports" : ["BANGLEJS2"], + "type": "clock", + "storage": [ + {"name":"contourclock.app.js","url":"app.js"}, + {"name":"contourclock.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "ltherm", + "name": "Localized Thermometer", + "shortName": "Thermometer", + "version": "0.01", + "description": "Displays the current temperature in localized units.", + "icon": "thermf.png", + "tags": "tool", + "supports": ["BANGLEJS2"], + "allow_emulator": true, + "readme": "README.md", + "storage": [ + {"name":"ltherm.app.js","url":"app.js"}, + {"name":"ltherm.img","url":"icon.js","evaluate":true} + ] + }, + { + "id": "slash", + "name": "Slash Watch", + "shortName":"Slash", + "icon": "slash.png", + "screenshots": [{"url":"screenshot.png"}], + "version":"0.01", + "description": "Slash Watch based on Pebble watch face by Nikki.", + "tags": "clock", + "type": "clock", + "supports":["BANGLEJS2"], + "readme": "README.md", + "allow_emulator": true, + "storage": [ + {"name":"slash.app.js","url":"app.js"}, + {"name":"slash.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "promenu", + "name": "Pro Menu", + "version": "0.01", + "description": "Replace Bangle.js 1's built in menu function.", + "icon": "icon.png", + "type": "boot", + "tags": "system", + "supports": ["BANGLEJS"], + "screenshots": [{"url":"pro-menu-screenshot.png"}], + "storage": [ + {"name":"promenu.boot.js","url":"boot.js"}, + {"name":"promenu.img","url":"promenuIcon.js","evaluate":true} + ] + }, + { + "id": "touchtimer", + "name": "Touch Timer", + "shortName": "Touch Timer", + "version": "0.02", + "description": "Quickly and easily create a timer with touch-only input. The time can be easily set with a number pad.", + "icon": "app.png", + "tags": "tools", + "supports": ["BANGLEJS2"], + "readme": "README.md", + "screenshots": [{"url":"0_light_timer_edit.png"},{"url":"1_light_timer_ready.png"},{"url":"2_light_timer_running.png"},{"url":"3_light_timer_finished.png"}], + "storage": [ + { "name": "touchtimer.app.js", "url": "app.js" }, + { "name":"touchtimer.settings.js", "url":"settings.js"}, + { "name": "touchtimer.img", "url": "app-icon.js", "evaluate": true } + ], + "data": [{"name":"touchtimer.data.json"}] + }, + { + "id": "teatimer", + "name": "Tea Timer", + "version": "1.00", + "description": "A simple timer. You can easyly set up the time.", + "icon": "teatimer.png", + "type": "app", + "tags": "tool", + "supports": ["BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"teatimer.app.js","url":"app.js"}, + {"name":"teatimer.img","url":"app-icon.js","evaluate":true} + ], + "screenshots": [ + {"url":"TeatimerStart.jpg"}, + {"url":"TeatimerHelp.jpg"}, + {"url":"TeatimerRun.jpg"}, + {"url":"TeatimerUp.jpg"} + ] + }, + { + "id": "swp2clk", + "name": "Swipe back to the Clock", + "shortName": "Swipe to Clock", + "version": "0.01", + "description": "Let's you swipe from left to right on any app to return back to the clock face. Please configure in the settings app after installing to activate, since its disabled by default.", + "icon": "app.png", + "type": "boot", + "tags": "tools", + "supports": ["BANGLEJS2"], + "readme": "README.md", + "storage": [ + { "name": "swp2clk.boot.js", "url": "boot.js" }, + {"name":"swp2clk.settings.js","url":"settings.js"} + ], + "data": [{"name":"swp2clk.data.json"}] + }, + { + "id":"colorwheel", + "name":"Color Wheel", + "tags":"app,tool", + "version":"0.01", + "description":"a tappable wheel of good-looking colors", + "readme":"README.md", + "supports":["BANGLEJS2"], + "allow_emulator":true, + "icon":"colorwheel.png", + "storage": [ + {"name":"colorwheel.app.js","url":"app.js"}, + {"name":"colorwheel.img","url":"app-icon.js","evaluate":true} + ] + }, + { "id": "minimal_clock", + "name": "Minimal Analog Clock", + "shortName":"Minimal Clock", + "version":"0.03", + "description": "a minimal analog clock - just with some hands and no clock face", + "icon": "app-icon.png", + "type": "clock", + "tags": "clock", + "supports" : ["BANGLEJS2"], + "allow_emulator": true, + "screenshots": [{"url":"app-screenshot.png"}], + "readme": "README.md", + "storage": [ + {"name":"minimal_clock.app.js","url":"app.js"}, + {"name":"minimal_clock.img","url":"app-icon.js","evaluate":true} + ] + }, + { "id": "simple_clock", + "name": "Simple Analog Clock", + "shortName":"Simple Clock", + "version":"0.02", + "description": "a simple, yet stylish, analog clock", + "icon": "app-icon.png", + "type": "clock", + "tags": "clock", + "supports" : ["BANGLEJS2"], + "allow_emulator": true, + "screenshots": [{"url":"app-screenshot.png"}], + "readme": "README.md", + "storage": [ + {"name":"simple_clock.app.js","url":"app.js"}, + {"name":"simple_clock.img","url":"app-icon.js","evaluate":true} + ] + }, + { "id": "colorful_clock", + "name": "Colorful Analog Clock", + "shortName":"Colorful Clock", + "version":"0.02", + "description": "a colorful analog clock", + "icon": "app-icon.png", + "type": "clock", + "tags": "clock", + "supports" : ["BANGLEJS2"], + "allow_emulator": true, + "screenshots": [{"url":"app-screenshot.png"}], + "readme": "README.md", + "storage": [ + {"name":"colorful_clock.app.js","url":"app.js"}, + {"name":"colorful_clock.img","url":"app-icon.js","evaluate":true} + ] + }, + { "id": "themesetter", + "name": "Theme Setter", + "shortName":"Theme Setter", + "version":"0.04", + "description": "a comfortable way to configure theme colors", + "icon": "app-icon.png", + "type": "app", + "tags": "tool", + "supports" : ["BANGLEJS2"], + "allow_emulator": true, + "screenshots": [{"url":"app-screenshot.png"}], + "readme": "README.md", + "storage": [ + {"name":"themesetter.app.js","url":"app.js"}, + {"name":"themesetter.img","url":"app-icon.js","evaluate":true} + ] + }, + { + "id": "widviztime", + "name": "Widget Autohide Widget", + "shortName": "Viz Time Widget", + "version": "0.01", + "description": "The widgets will be shown for four seconds after the device is unlocked.", + "icon": "eye.png", + "type": "widget", + "tags": "widget", + "readme":"README.md", + "supports": ["BANGLEJS","BANGLEJS2"], + "storage": [ + {"name":"widviztime.wid.js","url":"widget.js"} + ] + }, + { + "id": "supf", + "name": "Simple Clock with Date", + "shortName": "supf Clock", + "version": "0.01", + "description": "Simple Clock with seconds and date in custom language. Install 'Languages' to get localized names.", + "icon": "icon.png", + "screenshots": [{"url":"screenshot_supf.png"}], + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS2"], + "allow_emulator": true, + "readme": "README.md", + "storage": [ + {"name":"supf.app.js","url":"app.js"}, + {"name":"supf.img","url":"icon.js","evaluate":true} + ] + }, + { "id": "andark", + "name": "Analog Dark", + "shortName":"AnDark", + "version":"0.04", + "description": "analog clock face without disturbing widgets", + "icon": "andark_icon.png", + "type": "clock", + "tags": "clock", + "supports" : ["BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"andark.app.js","url":"app.js"}, + {"name":"andark.img","url":"app_icon.js","evaluate":true} + ] + }, + { + "id": "diract", + "name": "DirAct", + "shortName": "DirAct", + "version": "0.01", + "description": "Proximity interaction detection.", + "icon": "diract.png", + "type": "app", + "tags": "tool,sensors", + "supports" : [ "BANGLEJS2" ], + "allow_emulator": false, + "readme": "README.md", + "storage": [ + { "name": "diract.app.js", "url": "diract.js" }, + { "name": "diract.img", "url": "diract-icon.js", "evaluate": true } + ] + } ] diff --git a/apps/alarm/alarm.js b/apps/alarm/alarm.js index bb5722106..a655dad1e 100644 --- a/apps/alarm/alarm.js +++ b/apps/alarm/alarm.js @@ -21,8 +21,8 @@ function showAlarm(alarm) { Bangle.loadWidgets(); Bangle.drawWidgets(); E.showPrompt(msg,{ - title:alarm.timer ? "TIMER!" : "ALARM!", - buttons : {"Sleep":true,"Ok":false} // default is sleep so it'll come back in 10 mins + title:alarm.timer ? /*LANG*/"TIMER!" : /*LANG*/"ALARM!", + buttons : {/*LANG*/"Sleep":true,/*LANG*/"Ok":false} // default is sleep so it'll come back in 10 mins }).then(function(sleep) { buzzCount = 0; if (sleep) { diff --git a/apps/alarm/app.js b/apps/alarm/app.js index 53c7154bc..17062d44a 100644 --- a/apps/alarm/app.js +++ b/apps/alarm/app.js @@ -33,16 +33,16 @@ function getCurrentHr() { function showMainMenu() { const menu = { '': { 'title': 'Alarm/Timer' }, - '< Back' : ()=>{load();}, - 'New Alarm': ()=>editAlarm(-1), - 'New Timer': ()=>editTimer(-1) + /*LANG*/'< Back' : ()=>{load();}, + /*LANG*/'New Alarm': ()=>editAlarm(-1), + /*LANG*/'New Timer': ()=>editTimer(-1) }; alarms.forEach((alarm,idx)=>{ if (alarm.timer) { - txt = "TIMER "+(alarm.on?"on ":"off ")+formatMins(alarm.timer); + txt = /*LANG*/"TIMER "+(alarm.on?/*LANG*/"on ":/*LANG*/"off ")+formatMins(alarm.timer); } else { - txt = "ALARM "+(alarm.on?"on ":"off ")+formatTime(alarm.hr); - if (alarm.rp) txt += " (repeat)"; + txt = /*LANG*/"ALARM "+(alarm.on?/*LANG*/"on ":/*LANG*/"off ")+formatTime(alarm.hr); + if (alarm.rp) txt += /*LANG*/" (repeat)"; } menu[txt] = function() { if (alarm.timer) editTimer(idx); @@ -70,27 +70,27 @@ function editAlarm(alarmIndex) { as = a.as; } const menu = { - '': { 'title': 'Alarm' }, - '< Back' : showMainMenu, - 'Hours': { + '': { 'title': /*LANG*/'Alarm' }, + /*LANG*/'< Back' : showMainMenu, + /*LANG*/'Hours': { value: hrs, onchange: function(v){if (v<0)v=23;if (v>23)v=0;hrs=v;this.value=v;} // no arrow fn -> preserve 'this' }, - 'Minutes': { + /*LANG*/'Minutes': { value: mins, onchange: function(v){if (v<0)v=59;if (v>59)v=0;mins=v;this.value=v;} // no arrow fn -> preserve 'this' }, - 'Enabled': { + /*LANG*/'Enabled': { value: en, format: v=>v?"On":"Off", onchange: v=>en=v }, - 'Repeat': { + /*LANG*/'Repeat': { value: en, format: v=>v?"Yes":"No", onchange: v=>repeat=v }, - 'Auto snooze': { + /*LANG*/'Auto snooze': { value: as, format: v=>v?"Yes":"No", onchange: v=>as=v @@ -108,14 +108,14 @@ function editAlarm(alarmIndex) { last : day, rp : repeat, as: as }; } - menu["> Save"] = function() { + menu[/*LANG*/"> Save"] = function() { if (newAlarm) alarms.push(getAlarm()); else alarms[alarmIndex] = getAlarm(); require("Storage").write("alarm.json",JSON.stringify(alarms)); showMainMenu(); }; if (!newAlarm) { - menu["> Delete"] = function() { + menu[/*LANG*/"> Delete"] = function() { alarms.splice(alarmIndex,1); require("Storage").write("alarm.json",JSON.stringify(alarms)); showMainMenu(); @@ -136,18 +136,18 @@ function editTimer(alarmIndex) { en = a.on; } const menu = { - '': { 'title': 'Timer' }, - 'Hours': { + '': { 'title': /*LANG*/'Timer' }, + /*LANG*/'Hours': { value: hrs, onchange: function(v){if (v<0)v=23;if (v>23)v=0;hrs=v;this.value=v;} // no arrow fn -> preserve 'this' }, - 'Minutes': { + /*LANG*/'Minutes': { value: mins, onchange: function(v){if (v<0)v=59;if (v>59)v=0;mins=v;this.value=v;} // no arrow fn -> preserve 'this' }, - 'Enabled': { + /*LANG*/'Enabled': { value: en, - format: v=>v?"On":"Off", + format: v=>v?/*LANG*/"On":/*LANG*/"Off", onchange: v=>en=v } }; diff --git a/apps/alarm/boot.js b/apps/alarm/boot.js index 47dae5361..dffb3a37f 100644 --- a/apps/alarm/boot.js +++ b/apps/alarm/boot.js @@ -7,7 +7,7 @@ active = active.sort((a,b)=>(a.hr-b.hr)+(a.last-b.last)*24); var hr = time.getHours()+(time.getMinutes()/60)+(time.getSeconds()/3600); if (!require('Storage').read("alarm.js")) { - console.log("No alarm app!"); + console.log(/*LANG*/"No alarm app!"); require('Storage').write('alarm.json',"[]"); } else { var t = 3600000*(active[0].hr-hr); diff --git a/apps/andark/ChangeLog b/apps/andark/ChangeLog new file mode 100644 index 000000000..341868930 --- /dev/null +++ b/apps/andark/ChangeLog @@ -0,0 +1,4 @@ +0.01: Release +0.02: Rename app +0.03: Add type "clock" +0.04: changed update cylce, when locked diff --git a/apps/andark/README.md b/apps/andark/README.md new file mode 100644 index 000000000..3770c1017 --- /dev/null +++ b/apps/andark/README.md @@ -0,0 +1,10 @@ +# Analog Clock + +## Features + +* second hand +* date +* battery percantage +* no widgets + + diff --git a/apps/andark/andark_icon.png b/apps/andark/andark_icon.png new file mode 100644 index 000000000..cded02071 Binary files /dev/null and b/apps/andark/andark_icon.png differ diff --git a/apps/andark/andark_screen.png b/apps/andark/andark_screen.png new file mode 100644 index 000000000..2ac54c1cd Binary files /dev/null and b/apps/andark/andark_screen.png differ diff --git a/apps/andark/app.js b/apps/andark/app.js new file mode 100644 index 000000000..efa00ce6f --- /dev/null +++ b/apps/andark/app.js @@ -0,0 +1,125 @@ +const c={"x":g.getWidth()/2,"y":g.getHeight()/2}; +let zahlpos=[]; +let unlock = false; + +function zeiger(len,dia,tim){ + const x =c.x+ Math.cos(tim)*len/2, + y =c.y + Math.sin(tim)*len/2, + d={"d":3,"x":dia/2*Math.cos(tim+Math.PI/2),"y":dia/2*Math.sin(tim+Math.PI/2)}, + pol=[c.x-d.x,c.y-d.y,c.x+d.x,c.y+d.y,x+d.x,y+d.y,x-d.x,y-d.y]; + return pol; + +} + +function draw(){ + const d=new Date(); + let m=d.getMinutes(), h=d.getHours(), s=d.getSeconds(); + //draw black rectangle in the middle to clear screen from scale and hands + g.setColor(0,0,0); + g.fillRect(10,10,2*c.x-10,2*c.x-10); + g.setColor(1,1,1); + + if(h>12){ + h=h-12; + } + //calculates the position of the minute, second and hour hand + h=2*Math.PI/12*(h+m/60)-Math.PI/2; + //more accurate + //m=2*Math.PI/60*(m+s/60)-Math.PI/2; + m=2*Math.PI/60*(m)-Math.PI/2; + + s=2*Math.PI/60*s-Math.PI/2; + g.setFontAlign(0,0); + g.setFont("Vector",10); + let dateStr = " "+require("locale").date(d)+" "; + g.drawString(dateStr, c.x, c.y+20, true); + // g.drawString(d.getDate(),1.4*c.x,c.y,true); + g.drawString(Math.round(E.getBattery()/5)*5+"%",c.x,c.y+40,true); + drawlet(); + //g.setColor(1,0,0); + const hz = zeiger(100,5,h); + g.fillPoly(hz,true); + // g.setColor(1,1,1); + const minz = zeiger(150,5,m); + g.fillPoly(minz,true); + if (unlock){ + const sekz = zeiger(150,2,s); + g.fillPoly(sekz,true); + } + g.fillCircle(c.x,c.y,4); + + + +} +//draws the scale once the app is startet +function drawScale(){ + for(let i=-14;i<47;i++){ + const win=i*2*Math.PI/60; + let d=2; + if(i%5==0){d=5;} + g.fillPoly(zeiger(300,d,win),true); + g.setColor(0,0,0); + g.fillRect(10,10,2*c.x-10,2*c.x-10); + g.setColor(1,1,1); + } +} + +//draws the numbers on the screen + +function drawlet(){ + g.setFont("Vector",20); + for(let i = 0;i<12;i++){ + g.drawString(zahlpos[i][0],zahlpos[i][1],zahlpos[i][2]); + } +} +//calcultes the Position of the numbers when app starts and saves them in an array +function setlet(){ + let sk=1; + for(let i=-10;i<50;i+=5){ + let win=i*2*Math.PI/60; + let xsk =c.x+2+Math.cos(win)*(c.x-10), + ysk =c.y+2+Math.sin(win)*(c.x-10); + if(sk==3){xsk-=10;} + if(sk==6){ysk-=10;} + if(sk==9){xsk+=10;} + if(sk==12){ysk+=10;} + if(sk==10){xsk+=3;} + zahlpos.push([sk,xsk,ysk]); + sk+=1; + } +} +setlet(); +// Clear the screen once, at startup +g.setBgColor(0,0,0); +g.clear(); +drawScale(); +draw(); + +let secondInterval= setInterval(draw, 1000); +// Stop updates when LCD is off, restart when on + +Bangle.on('lcdPower',on=>{ + if (secondInterval) clearInterval(secondInterval); + secondInterval = undefined; + if (on) { + secondInterval = setInterval(draw, 1000); + draw(); // draw immediately + }else{ + } +}); +Bangle.on('lock',on=>{ + if (secondInterval) clearInterval(secondInterval); + secondInterval = undefined; + if (!on) { + secondInterval = setInterval(draw, 1000); + unlock = true; + draw(); // draw immediately + }else{ + secondInterval = setInterval(draw, 60000); + unlock = false; + draw(); + } + }); + +// Show launcher when middle button pressed +Bangle.setUI("clock"); diff --git a/apps/andark/app_icon.js b/apps/andark/app_icon.js new file mode 100644 index 000000000..b213fe5c8 --- /dev/null +++ b/apps/andark/app_icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwgIEBoUAiAKCgUCBQUEColEAYUQhAmKCwgeCAAcCgEDjwEBkEAg8TBocNgYFDh8GAYMDxkPjEA8EAwkHJgIcBAoPfAoYWCBYYFIgfvAoX4FYRJEAp9gAomYNAOAArPwAogAC4AFiRoIFJLgIFJuADCg//Q4U//4FDj4FEAAV4Aoi0CSxBsCA==")) \ No newline at end of file diff --git a/apps/android/ChangeLog b/apps/android/ChangeLog index 35fa0e386..c2c4ea6be 100644 --- a/apps/android/ChangeLog +++ b/apps/android/ChangeLog @@ -3,3 +3,4 @@ Fix music control 0.03: Handling of message actions (ok/clear) 0.04: Android icon now goes to settings page with 'find phone' +0.05: Fix handling of message actions diff --git a/apps/android/boot.js b/apps/android/boot.js index 97e3a5641..59ffe006d 100644 --- a/apps/android/boot.js +++ b/apps/android/boot.js @@ -65,7 +65,7 @@ // Message response Bangle.messageResponse = (msg,response) => { if (msg.id=="call") return gbSend({ t: "call", n:response?"ACCEPT":"REJECT" }); - if (isFinite(msg.id)) return gbSend({ t: "notify", n:response?"OPEN":"DISMISS" }); + if (isFinite(msg.id)) return gbSend({ t: "notify", n:response?"OPEN":"DISMISS", id: msg.id }); // error/warn here? }; })(); diff --git a/apps/authentiwatch/ChangeLog b/apps/authentiwatch/ChangeLog index e1b8ed5bc..7a902a731 100644 --- a/apps/authentiwatch/ChangeLog +++ b/apps/authentiwatch/ChangeLog @@ -1,4 +1,4 @@ -0.04: Fix tapping at very bottom of list, exit on inactivity -0.03: Add "Calculating" placeholder, update JSON save format -0.02: Fix JSON save format 0.01: First release +0.02: Fix JSON save format +0.03: Add "Calculating" placeholder, update JSON save format +0.04: Fix tapping at very bottom of list, exit on inactivity diff --git a/apps/awairmonitor/ChangeLog b/apps/awairmonitor/ChangeLog new file mode 100644 index 000000000..71d6399c4 --- /dev/null +++ b/apps/awairmonitor/ChangeLog @@ -0,0 +1,3 @@ +0.01: Beta version for Bangle 2 paired with Chrome (2021/12/11) +0.02: The app is now a clock, the data is greyed after the connection is lost (2021/12/22) +0.03: Set the Awair's IP directly on the webpage (2021/12/27) diff --git a/apps/awairmonitor/README.md b/apps/awairmonitor/README.md new file mode 100644 index 000000000..f4c7c42c4 --- /dev/null +++ b/apps/awairmonitor/README.md @@ -0,0 +1,21 @@ +# Awair Monitor + +Displays the level of CO2, VOC, PM 2.5, Humidity and Temperature, from your Awair device. + +* What you need: + * A BangleJS 2 + * An Awair device [with local API enabled](https://support.getawair.com/hc/en-us/articles/360049221014-Awair-Local-API-Feature) + * The web app [awair_to_bangle.html](awair_to_bangle.html) that will retrieve the data from your Awair device and sent it to your BangleJS 2 through Chrome's Bluetooth LE connection +* How to get started + * Launch the Awair Monitor app on your BangleJS + * Open awair_to_bangle.html on Chrome (desktop or Android), input the IP address of your Awair device, and click "Connect BangleJS" - it connects to your watch the same way as the Bangle app store + * Once connected to the watch with the app running, the watch app is updated once per second + + + + + +## Creator +[@alainsaas](https://github.com/alainsaas) + +Contributions are welcome, send me your Pull Requests! diff --git a/apps/awairmonitor/app-icon.js b/apps/awairmonitor/app-icon.js new file mode 100644 index 000000000..9d4dcf4a3 --- /dev/null +++ b/apps/awairmonitor/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwgP/AD38g4FD8EAAoeAgE/AoUD/EfAgP+AYMPDgQPBw4FB/F///DAoPwAQPjAQPBAQPxDgJVCAoP4gYaCCwIcBAoM/8P8h0HjEP8f4h0Gp0H4/44lj5+H4/54lzj/jx/5/lyDgIFDh/xAoQRBAoXsuY8Bx4jCAoeEkYFB447CAoRxBOAPxM4RmC8IFD4ZZD/8H/DHDh/+AoaSBUAIABCoYATVwS2Ct4FE84REXQQLCk4RJAo0XGxY=")) diff --git a/apps/awairmonitor/app.js b/apps/awairmonitor/app.js new file mode 100644 index 000000000..9123a9c2c --- /dev/null +++ b/apps/awairmonitor/app.js @@ -0,0 +1,108 @@ +Graphics.prototype.setFontMichroma36 = function() { +g.setFontCustom(atob("AAAAAAAAAAAAAAAAeAAAAAeAAAAAeAAAAAeAAAAAAAAAAAAAAAAAAAAAAAGAAAAA+AAAAD+AAAAP+AAAA/8AAAD/wAAAf/AAAB/4AAAH/gAAAf+AAAB/4AAAH/gAAAf+AAAAfwAAAAfAAAAAcAAAAAAAAAAAAAAAAAAAAAAAA///AAD///wAH///4AP///8APwAD+APAAAeAeAAAeAeAAAPAeAAAPAeAAAPAeAAAPAeAAAPAeAAAPAeAAAPAeAAAPAeAAAPAeAAAPAeAAAPAeAAAPAeAAAPAeAAAPAeAAAPAeAAAPAeAAAPAeAAAPAeAAAeAPAAAeAPwAD+AP///8AH///4AD///wAA///AAAAAAAAAAAAAAAAAAAAAEAAAAAOAAAAAfAAAAA+AAAAB8AAAAD8AAAAH4AAAAPwAAAAPgAAAAfAAAAAf///+Af///+Af///+Af///+AAAAAAAAAAAAAAAAAAAAAAAAAA/Af+AD/A/+AH/B/+AP/D/+APwD4eAPADweAfADweAeADweAeADweAeADweAeAHgeAeAHgeAeAHgeAeAHgeAeAHgeAeAHgeAeAHgeAeAHgeAeAHgeAeAHgeAeAPgeAeAPAeAeAPAeAeAPAeAeAPAeAfAPAeAPw/AeAP/+AeAH/+AeAD/8AeAB/wAOAAAAAAAAAAAAAAAAAAAAAAAAAB8APgAD8AP4AH8AP8AP8AP8APgAB+AfAAAeAeAAAeAeAAAPAeAAAPAeAAAPAeAAAPAeAeAPAeAeAPAeAeAPAeAeAPAeAeAPAeAeAPAeAeAPAeAeAPAeAeAPAeAeAPAeAeAPAeAeAPAeAeAPAeAeAeAfAeAeAPx/h+AP///+AH///8AD///4AB/h/gAAAAAAAAAAAAAAAAAAAAAAeAAAAA/AAAAA/AAAAB/AAAAD/AAAAH/AAAAPvAAAAPPAAAAfPAAAA+PAAAB8PAAAD4PAAADwPAAAHwPAAAPgPAAAfAPAAA+APAAA8APAAB8APAAD4APAAHwAPAAPgAPAAPAAPAAfAAPAAf///+Af///+Af///+Af///+AAAAPAAAAAPAAAAAPAAAAAPAAAAAOAAAAAAAAAAAAAAAAAAAAAAAAAAf/8PgAf/8P4Af/8P8Af/8P8AeB4A+AeB4AeAeDwAeAeDwAPAeDwAPAeDwAPAeDwAPAeDwAPAeDwAPAeDwAPAeDwAPAeDwAPAeDwAPAeDwAPAeDwAPAeDwAPAeDwAPAeDwAPAeDwAPAeDwAfAeDwAeAeD4A+AeD+D+AeB//8AeB//4AeA//4AAAP/AAAAAAAAAAAAAAAAAAAAAAAAAAA///AAD///wAH///4AH///8AP4fB+APAeAeAfA8AeAeA8APAeA8APAeA8APAeA8APAeA8APAeA8APAeA8APAeA8APAeA8APAeA8APAeA8APAeA8APAeA8APAeA8APAeA8APAeA8APAfA8APAPA+AeAPgeAeAP8fh+AH8f/8AD8P/8AA8H/4AAAB/gAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAeAAAAAeAAAAAeAAAAAeAAAAAeAAACAeAAAGAeAAAOAeAAAeAeAAA+AeAAD+AeAAH8AeAAP4AeAAfwAeAA/gAeAB/AAeAD+AAeAP4AAeAfwAAeA/gAAeB/AAAeD+AAAeH8AAAefwAAAe/gAAAf/AAAAf+AAAAf8AAAAf4AAAAfgAAAAfAAAAAAAAAAAAAAAAAAAAAAAAAAMAAB+B/wAD/j/4AH/3/8AP///+AP//A+AfB+AeAeA+AeAeA+APAeA+APAeA+APAeA8APAeA8APAeA8APAeA8APAeA8APAeA8APAeA8APAeA8APAeA8APAeA8APAeA+APAeA+APAeA+APAeA+AOAeA+AeAPh/A+AP///+AP/3/8AH/3/8AB/D/wAAAA/AAAAAAAAAAAAAAAAAAAAAAAAAAA/wAAAD/4HAAH/8HwAP/+H4AP5/H8AfAfA8AeAPAeAeAPAeAeAPAeAeAHgfAeAHgPAeAHgPAeAHgPAeAHgPAeAHgPAeAHgPAeAHgPAeAHgPAeAHgPAeAHgPAeAHgPAeAHgPAeAHAPAeAPAOAeAPAeAPAPAeAPwfB+AP///8AH///4AD///wAA///AAAAAAAAAAAAAAAAAAAAAAAAAAAB8DwAAB8HwAAB8HwAAB8DwAAAAAAAAAAAAA"), 46, atob("CBIkESMjJCMjIyMjCA=="), 36+(1<<8)+(1<<16)); +}; + +var drawTimeout; + +function queueNextDraw() { + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = setTimeout(function() { + drawTimeout = undefined; + draw(); + }, 1000 - (Date.now() % 1000)); +} + +var locale = require("locale"); + +var bt_current_co2 = 0; +var bt_current_voc = 0; +var bt_current_pm25 = 0; +var bt_current_humi = 0; +var bt_current_temp = 0; +var bt_last_update = 0; + +var last_update = 0; +var bt_co2_history = new Array(10).fill(0); +var bt_voc_history = new Array(10).fill(0); +var bt_pm25_history = new Array(10).fill(0); +var bt_humi_history = new Array(10).fill(0); +var bt_temp_history = new Array(10).fill(0); + +var internal_last_update = -1; + +var display_frozen = false; + +function draw() { + g.reset().clearRect(0,24,g.getWidth(),g.getHeight()); + + var date = new Date(); + g.setFontAlign(0,0); + g.setFont("Michroma36").drawString(locale.time(date,1), g.getWidth()/2, 56); + + g.setFont("6x8"); + g.drawString(locale.date(new Date(),1), g.getWidth()/2, 80); + + g.setFont("6x8"); + g.drawString("CO2", 20, 100); + g.drawString("VOC", 55, 100); + g.drawString("PM25", 90, 100); + g.drawString("Humi", 125, 100); + g.drawString("Temp", 160, 100); + + if (last_update != bt_last_update) { + display_frozen = false; + last_update = bt_last_update; + internal_last_update = last_update; + if (last_update % 10 == 0) { + bt_co2_history.shift(); bt_co2_history.push(bt_current_co2); + bt_voc_history.shift(); bt_voc_history.push(bt_current_voc); + bt_pm25_history.shift(); bt_pm25_history.push(bt_current_pm25); + bt_humi_history.shift(); bt_humi_history.push(bt_current_humi); + bt_temp_history.shift(); bt_temp_history.push(bt_current_temp); + } + } + + if (internal_last_update == -1) { + g.drawString("Waiting for connection", 88, 164); + } else if ((internal_last_update > last_update + 5) && (internal_last_update < last_update + 60)) { + g.drawString("Trying to reconnect since " + (internal_last_update - last_update), 88, 164); + } else if (internal_last_update > last_update + 5) { + display_frozen = true; + g.drawString("Waiting for connection", 88, 164); + } + + if (display_frozen) { g.setColor("#888"); } + + g.setFont("HaxorNarrow7x17"); + g.drawString(""+bt_current_co2, 18, 110); + g.drawString(""+bt_current_voc, 53, 110); + g.drawString(""+bt_current_pm25, 88, 110); + g.drawString(""+bt_current_humi, 123, 110); + g.drawString(""+bt_current_temp, 158, 110); + + for (i = 0; i < 10; i++) { + if (display_frozen) { g.setColor("#888"); } + + // max height = 32 + g.drawLine(10+i*2, 150-(Math.min(Math.max(bt_co2_history[i],400), 1200)-400)/25, 10+i*2, 150); + g.drawLine(45+i*2, 150-(Math.min(Math.max(bt_voc_history[i],0), 1440)-0)/45, 45+i*2, 150); + g.drawLine(80+i*2, 150-(Math.min(Math.max(bt_pm25_history[i],0), 32)-0)/1, 80+i*2, 150); + g.drawLine(115+i*2, 150-(Math.min(Math.max(bt_humi_history[i],20), 60)-20)/1.25, 115+i*2, 150); + g.drawLine(150+i*2, 150-(Math.min(Math.max(bt_temp_history[i],19), 27)-19)*4, 150+i*2, 150); + + // target humidity level + g.setColor("#00F").drawLine(115, 150-(40-20)/1.25, 115+18, 150-(40-20)/1.25); + g.reset(); + } + + if (internal_last_update != -1) { internal_last_update++; } + queueNextDraw(); +} + +// init +Bangle.setUI("clock"); +require("FontHaxorNarrow7x17").add(Graphics); +g.clear(); +Bangle.loadWidgets(); +Bangle.drawWidgets(); +draw(); diff --git a/apps/awairmonitor/app.png b/apps/awairmonitor/app.png new file mode 100644 index 000000000..26a5d0cff Binary files /dev/null and b/apps/awairmonitor/app.png differ diff --git a/apps/awairmonitor/awair-monitor-photo.jpg b/apps/awairmonitor/awair-monitor-photo.jpg new file mode 100644 index 000000000..8b62faa24 Binary files /dev/null and b/apps/awairmonitor/awair-monitor-photo.jpg differ diff --git a/apps/awairmonitor/awair_to_bangle.html b/apps/awairmonitor/awair_to_bangle.html new file mode 100644 index 000000000..69c52499f --- /dev/null +++ b/apps/awairmonitor/awair_to_bangle.html @@ -0,0 +1,673 @@ + + +
+ + + + + + + +
+How to use
+
+Step 1: Enable the Local API on your Awair: https://support.getawair.com/hc/en-us/articles/360049221014-Awair-Local-API-Feature
+
+Step 2: Launch the Awair Monitor app on your BangleJS
+
+Step 3: Input your Awair IP address and click the Connect button:
+
+
+
+Step 4: Optionally, open the web inspector's console (Right click > Inspector > Console) to read the Bluetooth logs
+
+Step 5: Once you are done, click the Disconnect button to properly close the Blutooth connection
+