diff --git a/apps/getaddr/ChangeLog b/apps/getaddr/ChangeLog new file mode 100644 index 0000000000..af7f83942b --- /dev/null +++ b/apps/getaddr/ChangeLog @@ -0,0 +1 @@ +0.01: Initial release diff --git a/apps/getaddr/README.md b/apps/getaddr/README.md new file mode 100644 index 0000000000..a80486da44 --- /dev/null +++ b/apps/getaddr/README.md @@ -0,0 +1,24 @@ +# Get Address App +This app uses the GPS and compass capabilities of the Bangle.js 2 watch to display your current location and direction. + +The app uses the Nominatim API to reverse geocode your location and display the street and house number. It also uses the compass to display your current direction. + +## Screenshots +![](image1.png) +![](image2.png) + +## Requirements +To run this app, you will need to meet the following requirements: + +1. Android Integration app or iOS integration app must be installed. +2. In Bangle.js Gadgetbridge connect the watch, then navigate to the **Gear icon** and enable "Use GPS data from phone". +3. In the same settings dialog scroll down and enable "Allow internet access". +4. Under **System** > **Settings** > **General Settings**, press "Get location" once and wait until it finds a location +5. In the same settings dialog enable "Keep location up to date". +7. The watch must have a clear view of the sky to receive GPS signals. +8. The compass must be calibrated by moving the watch in a figure-eight motion. + +Note: This app requires an active internet connection to function. It uses the Nominatim API to reverse geocode your location, and it may not work in areas with limited or no internet connectivity. + + +by [Online Speech to Text Cloud](https://www.speech-to-text.cloud/) diff --git a/apps/getaddr/getaddr-icon.js b/apps/getaddr/getaddr-icon.js new file mode 100644 index 0000000000..b2f820e485 --- /dev/null +++ b/apps/getaddr/getaddr-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwYcZhMkyVACBkSpIRBpMgCBUEBwIRCkmACBEBBwYCDIhYRFJRAOFAQVICA0CCJFJNBYCFNwwOHCJpBCCgiMJQY6SECIeQBAYRMBBosVMRAR/CMR9NUKLFVdJpQDyVIAwIFCMRQCICIsSCJMgCK8CCJIQFCKRlFOIwAFhIRHoARZVoi5GAAwRGbogRXdgjmHbRYQKZArCGCK7IECBbIEYRC2IWBC2ICBqkCTxSkGTxYAOA")) diff --git a/apps/getaddr/getaddr.app.js b/apps/getaddr/getaddr.app.js new file mode 100644 index 0000000000..93215c4910 --- /dev/null +++ b/apps/getaddr/getaddr.app.js @@ -0,0 +1,157 @@ +// Set the API endpoint and parameters +const nominatimApi = 'https://nominatim.openstreetmap.org'; +const locale = require('locale'); +let lang = locale.name; + +if (lang.toLowerCase() === 'system') { + lang = 'en'; +} else { + lang = lang.substring(0, 2); +} + +const params = { + format: 'json', + addressdetails: 1, + zoom: 18, + extratags: 1 +}; + +// Function to break a string into lines +function breakStringIntoLines(str, maxWidth) { + const words = str.split(' '); + const lines = []; + let currentLine = ''; + for (const word of words) { + if (currentLine.length + word.length + 1 > maxWidth) { + lines.push(currentLine); + currentLine = word; + } else { + if (currentLine!== '') { + currentLine +=' '; + } + currentLine += word; + } + } + lines.push(currentLine); + return lines; +} + +// Function to clear the screen and display a message +function showMessage(address, error, dir) { + g.clear(); + g.reset(); + g.setFontVector(16); + const addressLines = breakStringIntoLines(address, 20); + let y = 20; + for (const line of addressLines) { + g.drawString(line, 10, y); + y += 20; + } + if (error) { + y += 10; + const errorLines = breakStringIntoLines(error, 20); + for (const line of errorLines) { + g.drawString(line, 10, y); + y += 20; + } + } + g.drawString(`Direction: ${dir}`, 10, 150); + g.flip(); +} + +// Function to get the compass direction +function getCompassDirection() { + const compass = Bangle.getCompass(); + if (compass && compass.heading) { + const direction = Math.floor(compass.heading); + const directions = ['N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW']; + const index = Math.floor(((direction % 360) + 22.5) / 45) % 8; + if (index >= 0 && index < directions.length) { + return directions[index]; + } else { + return 'Invalid index'; + } + } else { + return 'No compass data'; + } +} + +// Variable to store the current address and error +let currentAddress = 'Getting address...'; +let currentError = ''; +let lastUpdateTime = 0; + +// Function to get the current location +function getCurrentLocation() { + Bangle.setGPSPower(1); + Bangle.setCompassPower(1); + Bangle.on('GPS', (gps) => { + if (gps.fix) { + const now = Date.now(); + if (now - lastUpdateTime < 30000) return; + lastUpdateTime = now; + getStreetAndHouseNumber(gps.lat, gps.lon); + } else { + currentAddress = 'No GPS signal'; + currentError = `Sats: ${gps.satellites}`; + showMessage(currentAddress, currentError, getCompassDirection()); + } + }); +} + +// Function to get the street and house number +function getStreetAndHouseNumber(lat, lon) { + const url = `${nominatimApi}/reverse`; + const paramsStr = Object.keys(params).map(key => `${key}=${encodeURIComponent(params[key])}`).join('&'); + const fullUrl = `${url}?${paramsStr}&lat=${lat}&lon=${lon}&accept-language=${lang}&format=json`; + + Bangle.http(fullUrl).then(data => { + try { + const jsonData = JSON.parse(data.resp); + if (jsonData && jsonData.address) { + let street = jsonData.address.road; + if (street.includes('Straße')) { + street = street.replace('Straße', 'Str.'); + } else if (street.includes('Street')) { + street = street.replace('Street', 'St.'); + } + const houseNumber = jsonData.address.house_number; + const newAddress = `${street} ${houseNumber}`; + if (newAddress!== currentAddress) { + currentAddress = newAddress; + currentError = ''; + } + } else { + const newAddress = 'No address'; + if (newAddress!== currentAddress) { + currentAddress = newAddress; + currentError = ''; + } + } + } catch (err) { + const newError = `Error: ${err}`; + if (newError!== currentError) { + currentError = newError; + } + } + showMessage(currentAddress, currentError, getCompassDirection()); + }).catch(err => { + const newError = `Error: ${err}`; + if (newError!== currentError) { + currentError = newError; + } + showMessage(currentAddress, currentError, getCompassDirection()); + }); +} + +// Main function +function main() { + showMessage('Getting address...', '', getCompassDirection()); + getCurrentLocation(); + setInterval(() => { + showMessage(currentAddress, currentError, getCompassDirection()); + }, 1000); +} + +// Call the main function +main(); diff --git a/apps/getaddr/getaddr.png b/apps/getaddr/getaddr.png new file mode 100644 index 0000000000..6dc5cc94d8 Binary files /dev/null and b/apps/getaddr/getaddr.png differ diff --git a/apps/getaddr/image1.png b/apps/getaddr/image1.png new file mode 100644 index 0000000000..a0bbf50efb Binary files /dev/null and b/apps/getaddr/image1.png differ diff --git a/apps/getaddr/image2.png b/apps/getaddr/image2.png new file mode 100644 index 0000000000..112fb8c5af Binary files /dev/null and b/apps/getaddr/image2.png differ diff --git a/apps/getaddr/metadata.json b/apps/getaddr/metadata.json new file mode 100644 index 0000000000..f176a83d1f --- /dev/null +++ b/apps/getaddr/metadata.json @@ -0,0 +1,17 @@ +{ + "id": "getaddr", + "name": "Get Addr", + "version": "0.01", + "description": "An app that shows the address of the current location", + "readme": "README.md", + "icon": "getaddr.png", + "screenshots": [{"url":"image1.png"}, {"url":"image2.png"}], + "type": "app", + "tags": "gps,outdoors,tools", + "supports": ["BANGLEJS2"], + "dependencies" : {}, + "storage": [ + {"name":"getaddr.app.js","url":"getaddr.app.js"}, + {"name":"getaddr.img","url":"getaddr-icon.js","evaluate":true} + ] + }