Porównaj commity

...

75 Commity
v1.0.3 ... main

Autor SHA1 Wiadomość Data
Hans P. Reiser 066e455ab6 typo-- 2022-10-02 23:40:17 +00:00
Hans P. Reiser 8debacde53 travis test 2022-10-02 23:35:48 +00:00
Hans P. Reiser 3d44b7f0e3 fix 1.0.7 2022-10-02 23:26:08 +00:00
Hans P. Reiser 5b863f7a1a url update for prediction 2022-10-02 23:08:31 +00:00
Hans P. Reiser 3e23aa56b5 travis testing for macos 2022-05-26 10:40:33 +00:00
Hans P. Reiser c22720f132 Merge branch 'upa' 2022-05-19 17:18:28 +00:00
Hansi, dl9rdz 6a3af0ad76 test 2022-05-19 19:11:33 +02:00
Hans P. Reiser a63a742e39 some build system verison updates 2022-05-19 00:17:54 +00:00
Hansi, dl9rdz 0fe5f00751 fix prediction for longituade < 0 (tawhiri api uses 0..360) 2021-06-26 12:28:58 +02:00
Hansi, dl9rdz b3808f8e26 electron win testing 2021-06-18 20:28:20 +02:00
Hansi, dl9rdz 1e02a92714 electron win testing 2021-06-18 20:22:28 +02:00
Hansi, dl9rdz 1d54b2e4dc electron win testing 2021-06-18 19:36:51 +02:00
Hansi, dl9rdz 9ab62faf25 electron win testing 2021-06-18 19:22:56 +02:00
Hansi, dl9rdz 17d679bbd8 more travis testing 2021-06-16 22:52:12 +02:00
Hansi, dl9rdz 201c4f412a more travis testing: win 2021-06-16 18:54:29 +02:00
Hansi, dl9rdz fe7977bcd5 more travis testing: win 2021-06-16 18:19:18 +02:00
Hansi, dl9rdz 92e64c1cbc more travis testing: win 2021-06-16 18:06:51 +02:00
Hansi, dl9rdz b369d7c8d4 more travis testing: win 2021-06-16 17:46:07 +02:00
Hansi, dl9rdz 8fb2461c0c more travis testing: win 2021-06-16 17:02:23 +02:00
Hansi, dl9rdz f5f41fc192 more travis testing: win 2021-06-16 16:58:01 +02:00
Hansi, dl9rdz be6d7d5208 more travis testing: win 2021-06-16 16:35:04 +02:00
Hansi, dl9rdz f7d0b306dc more travis testing: win 2021-06-16 16:30:42 +02:00
Hansi, dl9rdz 3c3154a57b more travis testing 2021-06-16 16:08:40 +02:00
Hansi, dl9rdz 604f2f14ac more travis testing 2021-06-16 16:01:27 +02:00
Hansi, dl9rdz 6a733ce6d6 more travis testing 2021-06-16 15:01:40 +02:00
Hansi, dl9rdz e955bec659 missing change for update check 2021-06-16 13:55:37 +02:00
Hansi, dl9rdz 8e3d1d9fd8 more travis testing 2021-06-16 09:27:39 +02:00
Hansi, dl9rdz e39a936336 more travis testing 2021-06-16 09:09:33 +02:00
Hansi, dl9rdz fe26ec60c2 more travis testing 2021-06-16 08:11:04 +02:00
Hansi, dl9rdz 3152941df9 more travis testing 2021-06-16 08:02:33 +02:00
Hansi, dl9rdz 398dad6f8e more travis testing 2021-06-15 23:56:01 +02:00
Hansi, dl9rdz 7ecff3f7e7 more travis testing 2021-06-15 23:45:00 +02:00
Hansi, dl9rdz c1fbd05ee1 more travis testing 2021-06-15 23:37:44 +02:00
Hansi, dl9rdz c998771c05 more travis testing 2021-06-15 23:16:21 +02:00
Hansi, dl9rdz 963cebeeb2 more travis testing 2021-06-15 23:06:57 +02:00
Hansi, dl9rdz 85f23a3082 more travis testing 2021-06-15 22:58:59 +02:00
Hansi, dl9rdz d549cbc836 set JAVA_HOM 2021-06-15 21:35:32 +02:00
Hansi, dl9rdz 4ee76661f2 dep fix 2021-06-15 21:28:56 +02:00
Hansi, dl9rdz 00c1113cdf added missing icon 2021-06-15 21:05:30 +02:00
Hansi, dl9rdz f2241dae35 travis test 2021-06-15 21:01:55 +02:00
Hansi, dl9rdz 1642bcd8d6 travis test 2021-06-15 20:56:51 +02:00
Hansi, dl9rdz e0969103e6 travis test 2021-06-15 20:50:18 +02:00
Hansi, dl9rdz 3fc7d4bced travis test 2021-06-15 20:45:18 +02:00
Hansi, dl9rdz 192a8e6df7 travis test 2021-06-15 20:42:22 +02:00
Hansi, dl9rdz 7e4c06018b travis test 2021-06-15 20:36:40 +02:00
Hansi, dl9rdz 81cb6471d2 travis test 2021-06-15 20:29:43 +02:00
Hansi, dl9rdz 69e96cd166 travis test 2021-06-15 20:25:09 +02:00
Hansi, dl9rdz 3f4849389c travis test 2021-06-15 20:18:51 +02:00
Hansi, dl9rdz 5624735548 travis test 2021-05-29 23:17:14 +02:00
Hansi, dl9rdz 802e6662ea travis test 2021-05-29 23:11:12 +02:00
Hansi, dl9rdz e57e69786a travis test 2021-05-29 23:03:29 +02:00
Hansi, dl9rdz 783716bf55 travis test 2021-05-29 23:01:22 +02:00
Hansi, dl9rdz 231412810e travis test 2021-05-29 22:53:11 +02:00
Hansi, dl9rdz e4a3936c51 travis test 2021-05-29 22:45:45 +02:00
Hansi, dl9rdz b17d83c1a7 travis test 2021-05-29 22:26:03 +02:00
Hansi, dl9rdz 2ed799ac31 travis test 2021-05-29 22:16:19 +02:00
Hansi, dl9rdz 71476626f7 travis test 2021-05-29 22:11:41 +02:00
Hansi, dl9rdz d5ee287f9a travis test 2021-05-29 22:08:48 +02:00
Hansi, dl9rdz 02bfc0ee8c travis test 2021-05-29 22:04:04 +02:00
Hansi, dl9rdz 9f0d3b7220 travis test 2021-05-29 22:00:13 +02:00
Hansi, dl9rdz c714769ee1 travis test 2021-05-29 18:23:06 +02:00
Hansi, dl9rdz d1b1e74bd4 travis test 2021-05-29 18:14:49 +02:00
Hansi, dl9rdz 17a4e44203 version boost, travis test 2021-05-29 18:07:48 +02:00
Hansi, dl9rdz 7531b4be0a +travis test 2021-05-29 17:50:41 +02:00
Hansi, dl9rdz 233fd21ec5 bug-- 2021-02-15 14:54:42 +01:00
Hansi, dl9rdz 4f2101edd9 v1.0.5 2021-02-15 09:27:29 +01:00
Hansi, dl9rdz b71b2e4f8f pre-v1.0.5: new ttgo link icons, clickable sonde tooltip, gps pos info, additional sonde info on popup 2021-02-14 23:06:55 +01:00
Hansi, dl9rdz 7e37c31463 added missing file 2021-02-14 14:36:48 +01:00
Hansi, dl9rdz 4271a97027 bugs-- 2021-02-14 14:35:50 +01:00
Hansi, dl9rdz 7d7e9f64eb test 2021-02-14 11:39:32 +01:00
Hansi, dl9rdz 568fc2bc57 test 2021-02-13 23:21:06 +01:00
Hansi, dl9rdz 4c0e8609f1 v1.0.4 2021-02-13 12:35:23 +01:00
Hansi, dl9rdz 31584d2291 minor polising pre-v.1.0.4 2021-02-09 12:25:14 +01:00
Hansi, dl9rdz 2d191275cc allow geo: url in in-app browser 2021-02-07 12:24:34 +01:00
Hansi, dl9rdz 687bf3e91e v1.0.3 2021-01-31 00:05:16 +01:00
17 zmienionych plików z 859 dodań i 130 usunięć

119
.travis.yml 100644
Wyświetl plik

@ -0,0 +1,119 @@
matrix:
include:
- os: osx
osx_image: xcode11.3
language: node_js
node_js: "18"
env:
- ELECTRON_CACHE=$HOME/.cache/electron
- ELECTRON_BUILD_BACHE=$HOME/.cache/electron-builder
deploy:
provider: releases
api_key: ${GITHUB_API_KEY}
file: rdzSonde-v${TRAVIS_TAG}.dmg
skip_cleanup: true
overwrite: true
on:
tags: true
# - os: windows
# language: node_js
# node_js: "12"
# env:
# - ELECTRON_CACHE=$HOME/.cache/electron
# - ELECTRON_BUILD_BACHE=$HOME/.cache/electron-builder
# deploy:
# provider: releases
# api_key: ${GITHUB_API_KEY}
# file: rdzSonde-setup-${TRAVIS_TAG}.exe
# skip_cleanup: true
# overwrite: true
# on:
# tags: true
# - os: linux
# language: minimal
# dist: focal
# group: edge
# deploy:
# provider: releases
# api_key: ${GITHUB_API_KEY}
# file: rdzSonde-${TRAVIS_TAG}.apk
# skip_cleanup: true
# overwrite: true
# on:
# tags: true
#
env:
global:
# for updates check developer.android.com/studio#downloads (current 26.1.1)
- ANDROID_SDK_TOOLS=commandlinetools-linux-7302050_latest.zip
- JAVA_HOME="/usr/lib/jvm/java-11-openjdk-amd64"
cache:
directories:
- mode_modules
- $HOME/.cache/electron
- $HOME/.cache/electron-builder
before_script:
#- echo no | android create avd --force -n test -t android-22 --abi armeabi-v7a
# - emulator -avd test -no-audio -no-window &
# - android-wait-for-emulator
# - adb shell input keyevent 82 &
# - curl -fsSL https://deb.nodesource.com/setup_16.x | sudo -E bash -
- if [ "$TRAVIS_OS_NAME" == "windows" ]; then
npm install -g cordova;
cordova platform add electron;
fi
- if [ "$TRAVIS_OS_NAME" == "osx" ]; then
sudo npm install -g cordova;
cordova platform add electron;
fi
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then
echo ${TEST};
sudo apt-get update;
sudo apt-get install nodejs;
sudo apt-get install npm;
sudo apt-get install openjdk-11-jdk;
sudo apt-get install gradle;
wget -nv https://dl.google.com/android/repository/$ANDROID_SDK_TOOLS;
unzip -q $ANDROID_SDK_TOOLS -d $HOME/sdk;
mv $HOME/sdk/cmdline-tools $HOME/sdk/latest;
mkdir $HOME/sdk/cmdline-tools;
mv $HOME/sdk/latest $HOME/sdk/cmdline-tools/;
export PATH=$PATH:$HOME/sdk/cmdline-tools/latest/bin;
export ANDROID_SDK_ROOT=$HOME/sdk;
yes | sdkmanager --sdk_root=$ANDROID_SDK_ROOT "platforms;android-29";
yes | sdkmanager --sdk_root=$ANDROID_SDK_ROOT "emulator" "tools" "platform-tools";
yes | sdkmanager --sdk_root=$ANDROID_SDK_ROOT --licenses;
yes | sdkmanager --sdk_root=$ANDROID_SDK_ROOT "build-tools;29.0.3";
sudo npm install -g cordova;
sudo chown -R 2000:2000 "/home/travis/.npm";
cordova platform add android;
perl -pi -e 's/1\.8\.x/11.x/' ./platforms/android/cordova/lib/check_reqs.js;
fi
script:
- if [ "$TRAVIS_OS_NAME" == "windows" ]; then
echo "Windows";
cordova build electron --debug;
find platforms;
mv platforms/electron/build/*.exe rdzSonde-setup-${TRAVIS_TAG}.exe;
ls *.exe;
fi
- if [ "$TRAVIS_OS_NAME" == "osx" ]; then
echo "OSX";
cordova build electron --release;
mv platforms/electron/build/rdzSonde*.dmg rdzSonde-v${TRAVIS_TAG}.dmg;
fi
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then
cordova build --release;
export BUILD_TOOLS=$HOME/sdk/build-tools/29.0.3;
${BUILD_TOOLS}/zipalign -v -p 4 platforms/android/app/build/outputs/apk/release/app-release-unsigned.apk rdzSonde-unsigned.apk;
echo ${SUPERSECRET} | gpg --batch --yes --passphrase-fd 0 -d my-release-key.jks.gpg > my-release-key.jks;
echo ${JKSPASS} | ${BUILD_TOOLS}/apksigner sign --ks my-release-key.jks --out rdzSonde-${TRAVIS_TAG}.apk rdzSonde-unsigned.apk;
fi

Wyświetl plik

@ -0,0 +1,22 @@
www/js/L.Control.MousePosition.js
Copyright 2012 Ardhi Lukianto
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

37
Makefile 100644
Wyświetl plik

@ -0,0 +1,37 @@
export ANDROID_SDK_ROOT=/Users/hansr/Library/Android/sdk
all: run
el: plugin
cordova build electron
run:
clear
cp ../rdzwx-plugin/src/android/*.kt ./platforms/android/app/src/main/kotlin/de/dl9rdz/
cordova run android --device
full:
clear
cordova plugin rm de-dl9rdz-rdzwx
cordova plugin add ../rdzwx-plugin/
cordova run android --device
plugin:
cordova plugin rm de-dl9rdz-rdzwx
cordova plugin add ../rdzwx-plugin/
release: apkrelease sign
mkrelease:
cordova build --release
.ONESHELL:
sign:
cd platforms/android/app/build/outputs/apk/release/ && \
rm -f app-release-unsigned-aligned.apk && \
/Users/hansr/Library/Android//sdk/build-tools/30.0.3/zipalign -v -p 4 app-release-unsigned.apk app-release-unsigned-aligned.apk && \
/Users/hansr/Library/Android//sdk/build-tools/30.0.3/apksigner sign --ks ~/src/rdzwx-go/my-release-key.jks --out app-release.apk app-release-unsigned-aligned.apk
apkrelease:
cordova build --release -- --packageType=apk

Wyświetl plik

@ -6,22 +6,29 @@ See https://github.com/dl9rdz/rdzwx-go/wiki for details how to use.
## How to compile and run
- Install Android Studio
- Install Java (I used openjdk 11, gradle and android on API level 30 do not support later openjdk version) and gradle (I used version 7.4.2) (I installed both on MacOS with brew)
- Install Android Studio (currently tested with Chipmunk 2021.2.1)
In Preferences: Appearance&Behaviour > System Settings > Android SDK
SDK Platforms: select some relevant platform (I used API level 29)
SDK Platforms: select some relevant platform (I used API level 32)
SDK Tools: I selected Build-Tools, NDK, SDK command line, emulator, SDKK platform tools (maybe not all necessary)
SDK Tools: I selected Build-Tools, NDK, SDK command line, emulator, SKK platform tools (maybe not all necessary)
Specifically, build tools 30.0.3 are needed!!!
- `export ANDROID_SDK_ROOT=/Users/me/Library/Android/sdk`
Use path shown in Android Studio preferences as "Android SDK Location"!
- Install node.js (after that you should be able to run "node" and "npm" on your command line)
(On MacOS I did 'brew install nodejs')
- Install Cordova (used version 9.0.0): `sudo npm install -g cordova`
- clone the git repository (`git clone https://github.com/dl9rdz/rdzwx-go.git`)
- `cd rdzwx-go; cordova platform add android`
- cordova plugin add cordova-plugin-androidx-adapter
- npm i jetifier
- npx jetifier
- `cordova build` to build debug apk
- `cordova build --release` to build releaes apk
- `cordova run android` to upload apk via usb to phone

Wyświetl plik

@ -1,7 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<widget id="de.dl9rdz" version="1.0.2" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0"
<widget id="de.dl9rdz" version="1.0.7" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0"
xmlns:android="schemas.android.com/apk/res/android">
<name>rdzSondyGO</name>
<name>rdzSonde</name>
<description>
A sample Apache Cordova application that uses rdzwx-plugin.
</description>
@ -20,6 +20,7 @@
<allow-navigation href="http://*/*" />
<allow-navigation href="https://*/*" />
<allow-navigation href="data:*" />
<allow-navigation href="geo:*" />
<platform name="android">
<allow-intent href="market:*" />
@ -28,15 +29,20 @@
<application android:usesCleartextTraffic="true" />
</edit-config>
</platform>
<icon src="res/icon.png"/>
<icon src="res/icon512.png"/>
<platform name="electron">
<preference name="ElectronSettingsFilePath" value="res/electron/settings.json" />
</platform>
<preference name="GradlePluginKotlinEnabled" value="true" />
<preference name="GradlePluginKotlinCodeStyle" value="official" />
<preference name="GradlePluginKotlinVersion" value="1.3.50" />
<preference name="android-minSdkVersion" value="23" />
<preference name="android-targetSdkVersion" value="29" />
<preference name="android-targetSdkVersion" value="30" />
<preference name="SplashScreen" value="none" />
<preference name="AndroidInsecureFileModeEnabled" value="true" />
</widget>

Plik binarny nie jest wyświetlany.

Wyświetl plik

@ -1,7 +1,7 @@
{
"name": "de.dl9rdz",
"displayName": "rdzwx-go",
"version": "1.0.1",
"version": "1.0.7",
"description": "A sample Apache Cordova application that uses rdzwx-plugin.",
"main": "index.js",
"scripts": {
@ -12,22 +12,41 @@
],
"author": "Hansi Reiser <dl9rdz@darc.de>",
"license": "Apache-2.0",
"overrides": {
"electron-builder": "23.0.3"
},
"dependencies": {
"jetifier": "^2.0.0",
"net": "^1.0.2",
"update": "^0.7.4",
"xmlhttprequest": "^1.8.0"
},
"devDependencies": {
"cordova-android": "^9.0.0",
"cordova-android": "^10.1.2",
"cordova-browser": "^6.0.0",
"cordova-plugin-inappbrowser": "^4.1.0",
"cordova-plugin-whitelist": "^1.3.4",
"de-dl9rdz-rdzwx": "https://github.com/dl9rdz/rdzwx-plugin.git"
"cordova-electron": "^3.0.0",
"cordova-plugin-androidx-adapter": "^1.1.3",
"cordova-plugin-inappbrowser": "^5.0.0",
"rdzwx-plugin": "github:dl9rdz/rdzwx-plugin"
},
"cordova": {
"plugins": {
"cordova-plugin-whitelist": {},
"cordova-plugin-androidx-adapter": {},
"cordova-plugin-inappbrowser": {},
"de-dl9rdz-rdzwx": {}
},
"platforms": [
"android",
"browser"
"browser",
"electron"
]
},
"browser": {
"net": false,
"fs": false
},
"electron": {
"net": false,
"fs": false
}
}

Wyświetl plik

@ -0,0 +1,10 @@
{
"browserWindow": {
"width": 1200,
"height": 800,
"webPreferences": {
"nodeIntegration": true,
"contextIsolation": false
}
}
}

BIN
res/icon512.png 100644

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 64 KiB

5
version.json 100644
Wyświetl plik

@ -0,0 +1,5 @@
{
"version": "1.0.7",
"url": "https://github.com/dl9rdz/rdzwx-go/releases/tag/v1.0.7",
"apkurl": "https://github.com/dl9rdz/rdzwx-go/releases/download/v1.0.7/rdzSonde-v1.0.7.apk"
}

Wyświetl plik

@ -106,6 +106,9 @@ html, body {
padding: 0px;
float: right;
}
.infomax {
width: 99%;
}
.tawhiridiv {
background-color: #ecfedf;
@ -124,6 +127,8 @@ html, body {
font-size: 11pt;
}
.tawhiricontent input {
color: #ffffff;
background-color: #000000;
font-size: 11pt;
width: 5em;
}
@ -166,7 +171,7 @@ html, body {
font-size: 5vw;
}
.infocontentl3 {
font-size: 6vw;
font-size: 5.5vw;
}
.infocontentl4 {
font-size: 5vw;
@ -175,19 +180,19 @@ html, body {
@media (orientation: landscape) {
.infotable {
width: 60vw;
width: 50vw;
}
.infocontentl1 {
font-size: 4vw;
font-size: 3.5vw;
}
.infocontentl2 {
font-size: 3vw;
font-size: 2.5vw;
}
.infocontentl3 {
font-size: 4vw;
font-size: 3.5vw;
}
.infocontentl4 {
font-size: 3vw;
font-size: 2.5vw;
}
}
@ -217,12 +222,19 @@ html, body {
.pop-header {
display: flex;
align-items:center;
margin: 4px;
}
.pop-header > h4{
margin: 4px;
}
.pop-header > img{
display: inline-block;
height: 16px;
}
.leaflet-popup-content {
margin: 6px 12px;
}
.leaflet-center {
position: relative !important;
@ -245,6 +257,13 @@ html, body {
right: 0;
}
.leaflet-control-container .leaflet-control-topcenter {
position: absolute;
top: 0;
left: 0;
right: 0;
}
/* Portrait layout (default) */
.app {
@ -317,3 +336,21 @@ h1 {
background-image:linear-gradient(to bottom, #585858 0%, #1B1B1B 51%);
}
}
.leaflet-container .leaflet-control-mouseposition {
background-color: rgba(255, 255, 255, 0.7);
box-shadow: 0 0 5px #bbb;
padding: 0 2px;
margin:0;
color: #333;
font: 11px/1.5 "Helvetica Neue", Arial, Helvetica, sans-serif;
}
.online-active, .offline-active {
padding-left: 0px;
padding-right: 0px;
}
button.offline-active, button.online-active {
padding-top: 4px;
}

BIN
www/img/ttgooff.png 100644

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 834 B

BIN
www/img/ttgoon.png 100644

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 627 B

Wyświetl plik

@ -33,10 +33,10 @@
<meta name="format-detection" content="telephone=no">
<meta name="msapplication-tap-highlight" content="no">
<meta name="viewport" content="initial-scale=1, width=device-width, viewport-fit=cover, user-scalable=no">
<meta name="color-scheme" content="light dark">
<link rel="stylesheet" href="css/index.css">
<meta name="color-scheme" content="light">
<link rel="stylesheet" href="css/leaflet.css">
<link rel="stylesheet" href="css/leaflet.contextmenu.css">
<link rel="stylesheet" href="css/index.css">
<script src="cordova.js"></script>
<script src="js/leaflet.js"></script>
<script src="js/leaflet.contextmenu.js"></script>
@ -46,23 +46,31 @@
<script src="https://cdn.jsdelivr.net/npm/leaflet-easybutton@2/src/easy-button.js"></script>
-->
<script src="js/easy-button.js"></script>
<script src="js/L.Control.MousePosition.js"></script>
<title>rdzSondyGO V1.0.1</title>
<title>rdzSonde v1.0.7 +experimental</title>
</head>
<body>
<div id="all">
<div id="toolbar">
<a id="toolbarclose" class="leaflet-popup-close-button" style="cursor: pointer; float: right;">x</a>
<h2>rdzSondyGO v1.0.1</h2>
<p>Copyright &copy; 2021 Hansi Reiser, dl9rdz</p>
<a id="toolbarclose" class="leaflet-popup-close-button" style="cursor: pointer; float: right;">X</a>
<h2>rdzSonde v1.0.7 +experimental</h2>
<p>Copyright &copy; 2022 Hansi Reiser, dl9rdz</p>
<p>see <a href="https://github.com/dl9rdz/rdzwx-go">https://github.com/dl9rdz/rdzwx-go</a> for details</p>
<p>Apache License Version 2.0</p>
<hr>
<button onclick="RdzWx.selstorage(&quot;map&quot;, function(res) { localStorage.setItem(&quot;mapstorage&quot;, res); })">Select map file </button>
<hr>
<button onclick="RdzWx.selstorage(&quot;theme&quot;, function(res) { localStorage.setItem(&quot;mapstorage&quot;, res); })">Select map theme </button>
<hr>
<div id="toolbaritems">
</div>
</div>
<div id='map'></div>
</div>
<script>
if(typeof(global)=='undefined') { global = globalThis; }
</script>
<script src="js/index.js"></script>
</body>
</html>

Wyświetl plik

@ -0,0 +1,100 @@
L.Control.MousePosition = L.Control.extend({
options: {
position: 'bottomleft',
separator: ' : ',
emptyString: 'Unavailable',
lngFirst: false,
numDigits: 5,
lngFormatter: undefined,
latFormatter: undefined,
prefix: ""
},
onAdd: function (map) {
this._container = L.DomUtil.create('div', 'leaflet-control-mouseposition');
L.DomEvent.disableClickPropagation(this._container);
map.on('mousemove', this._onMouseMove, this);
this._container.innerHTML=this.options.emptyString;
return this._container;
},
onRemove: function (map) {
map.off('mousemove', this._onMouseMove)
},
_onMouseMove: function (e) {
var lng = this.options.lngFormatter ? this.options.lngFormatter(e.latlng.lng) : L.Util.formatNum(e.latlng.lng, this.options.numDigits);
var lat = this.options.latFormatter ? this.options.latFormatter(e.latlng.lat) : L.Util.formatNum(e.latlng.lat, this.options.numDigits);
var value = this.options.lngFirst ? lng + this.options.separator + lat : lat + this.options.separator + lng;
var prefixAndValue = this.options.prefix + ' ' + value;
//var locator = calcLocator(lat,lng);
this._container.innerHTML = prefixAndValue; // + " | " + locator ;
}
});
L.Map.mergeOptions({
positionControl: false
});
L.Map.addInitHook(function () {
if (this.options.positionControl) {
this.positionControl = new L.Control.MousePosition();
this.addControl(this.positionControl);
}
});
L.control.mousePosition = function (options) {
return new L.Control.MousePosition(options);
};
function calcLocator(lat,lon)
{
//lon = document.getElementById("longitude").value;
//lat = document.getElementById("latitude").value;
var locator = "";
//lat=47.78689;
//lon=12.98875;
//lat=47.8093
//lon=12.9904
lon=parseFloat(lon);
lat=parseFloat(lat);
lat += 90;
lon += 180;
locator += String.fromCharCode(65 + Math.floor(lon / 20));
locator += String.fromCharCode(65 + Math.floor(lat / 10));
lon = lon % 20;
if (lon < 0) lon += 20;
lat = lat % 10;
if (lat < 0) lat += 10;
locator += String.fromCharCode(48 + Math.floor(lon / 2));
locator += String.fromCharCode(48 + Math.floor(lat / 1));
lon = lon % 2;
if (lon < 0) lon += 2;
lat = lat % 1;
if (lat < 0) lat += 1;
locator += String.fromCharCode(65 + Math.floor(lon * 12));
locator += String.fromCharCode(65 + Math.floor(lat * 24));
lon = lon % ( 1 / 12);
if (lon < 0) lon += 1 / 12;
lat = lat % ( 1 / 24);
if (lat < 0) lat += 1 / 24;
locator += String.fromCharCode(48 + Math.floor(lon * 120));
locator += String.fromCharCode(48 + Math.floor(lat * 240));
lon = lon % (1 / 120);
if (lon < 0) lon += 1 / 120;
lat = lat %( 1 / 240);
if (lat < 0) lat += 1 / 240;
locator += String.fromCharCode(65 + Math.floor(lon * 120 * 24));
locator += String.fromCharCode(65 + Math.floor(lat * 240 * 24));
lon = lon % ( 1 / 120 / 24);
if (lon < 0) lon += 1 / 120 / 24;
lat = lat % (1 / 240 / 24);
if (lat < 0) lat += 1 / 240 / 24;
if(/[A-Z0-9]{10}/.test(locator))
return locator;
}

Wyświetl plik

@ -28,8 +28,7 @@ var map = null;
/////var lastObj = { obj: null, marker: null, /*no longer used: */pred: null, land: null };
var lastMarker = null;
var mypos = {lat: 48.56, lon: 13.43};
//var mypos = {lat: 48.1, lon: 13.1};
var mypos = {lat: 48.56, lon: 13.43, hdop: 25, alt: 480};
var myposMarker = null;
var ballonIcon, landIcon, burstIcon;
@ -39,7 +38,11 @@ var infobox = null;
var checkMark = "&#x2714;";
var crossMark = "&#x274C;";
// add "bottom center" to leaflet
var offlineMap = localStorage.getItem("mapstorage");
if(!offlineMap) offlineMap="file:///sdcard/Android/data/de.dl9rdz.files/";
console.log("Map storage location: "+offlineMap);
// add "top center" and "bottom center" to leaflet
(function (L) {
L.Map.prototype._initControlPos = function(_initControlPos) {
return function() {
@ -47,16 +50,52 @@ var crossMark = "&#x274C;";
this._controlCorners['bottomcenter'] = L.DomUtil.create('div', 'leaflet-bottom leaflet-center',
L.DomUtil.create('div', 'leaflet-control-bottomcenter', this._controlContainer)
);
this._controlCorners['topcenter'] = L.DomUtil.create('div', 'leaflet-top leaflet-center',
L.DomUtil.create('div', 'leaflet-control-topcenter', this._controlContainer)
);
};
} (L.Map.prototype._initControlPos);
}(L, this, document));
// Let's add bearing calculation to latLngs...
L.LatLng.prototype.bearingTo = function(target) {
var lat1 = this.lat * Math.PI / 180;
var lat2 = target.lat * Math.PI / 180;
var dLon = (target.lng-this.lng) * Math.PI / 180;
//console.log("b2: "+lat1+", "+lat2+", "+dLon+" -- "+JSON.stringify(target));
var y = Math.sin(dLon) * Math.cos(lat2);
var x = Math.cos(lat1)*Math.sin(lat2) - Math.sin(lat1)*Math.cos(lat2)*Math.cos(dLon);
var bearing = Math.atan2(y, x) * 180 / Math.PI;
bearing = ( parseInt( bearing ) + 360 ) % 360;
console.log("bearing : "+x+", "+y+", => "+bearing);
return bearing;
};
function onDeviceReady() {
// Cordova is now initialized. Have fun!
console.log('Running cordova-' + cordova.platformId + '@' + cordova.version);
// Check for updates
fetch("https://raw.githubusercontent.com/dl9rdz/rdzwx-go/main/version.json")
.then(response => response.json())
.then(data => {
console.log('Success:', data);
if(data.version > "1.0.7") {
if(window.confirm("New version "+ data.version + " available! Download?")) {
console.log("opening "+data.url);
cordova.InAppBrowser.open(data.url, "_system");
}
}
})
.catch((error) => {
console.error('Error:', error);
});
// Some map tile sources
var tfapikey = "01be52efbdc14d38beac233a870c8d4f";
var tfland = L.tileLayer('https://{s}.tile.thunderforest.com/landscape/{z}/{x}/{y}.png?apikey=' + tfapikey, {attribution: '&copy; <a href="http://www.thunderforest.com/">Thunderforest</a>, &copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'}),
@ -65,8 +104,76 @@ function onDeviceReady() {
tfcycle = L.tileLayer('https://{s}.tile.thunderforest.com/cycle/{z}/{x}/{y}.png?apikey=' + tfapikey, {attribution: '&copy; <a href="http://www.thunderforest.com/">Thunderforest</a>, &copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'}),
tfatlas = L.tileLayer('https://{s}.tile.thunderforest.com/mobile-atlas/{z}/{x}/{y}.png?apikey=' + tfapikey, {attribution: '&copy; <a href="http://www.thunderforest.com/">Thunderforest</a>, &copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'}),
opentopo = L.tileLayer('https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png', {attribution: 'Kartendaten: &copy; <a href="https://openstreetmap.org/copyright">OpenStreetMap</a>-Mitwirkende, <a href="http://viewfinderpanoramas.org">SRTM</a> | Kartendarstellung: &copy; <a href="https://opentopomap.org">OpenTopoMap</a> (<a href="https://creativecommons.org/licenses/by-sa/3.0/">CC-BY-SA</a>)'}),
sat = L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', { attribution: 'Tiles &copy; Esri &mdash; Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community'}),
offline = L.tileLayer('file:///android_asset/www/tiles/{z}/{x}/{y}.png', {attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>', maxNativeZoom: 14} );
sat = L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', { attribution: 'Tiles &copy; Esri &mdash; Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community'})
L.OfflineTileLayer = L.TileLayer.extend({
getTileUrl: function(tilePoint, tile, done) {
var tilesrc;
var z = tilePoint.z, x = tilePoint.x, y = tilePoint.y;
console.log("Coord: "+x+","+y+","+z);
console.log("this: " + this);
tile.thethis = this;
RdzWx.gettile(x, y, z, function(result) {
if(result.tile) {
console.log("gettile: success: " + result.tile);
tile.onload = L.Util.bind(tile.thethis._tileOnLoad, this, done, tile);
tile.src = result.tile;
//done(tile);
} else {
console.log("gettile: success but no tile");
tile.src = "img/MapTileUnavailable.png";
done(tile);
}
}, function(error) {
console.log("gettile: error: " + error);
tile.src = "img/MapTileUnavailable.png";
done(tile);
});
console.log("getTileUrl returning...");
//return tilestr;
},
createTile: function (coords, done) {
var tile = document.createElement('img');
//DomEvent.on(tile, 'load', Util.bind(this._tileOnLoad, this, done, tile));
//DomEvent.on(tile, 'error', Util.bind(this._tileOnError, this, done, tile));
if (this.options.crossOrigin || this.options.crossOrigin === '') {
tile.crossOrigin = this.options.crossOrigin === true ? '' : this.options.crossOrigin;
}
/*
Alt tag is set to empty string to keep screen readers from reading URL and for compliance reasons
http://www.w3.org/TR/WCAG20-TECHS/H67
*/
tile.alt = '';
/*
Set role="presentation" to force screen readers to ignore this
https://www.w3.org/TR/wai-aria/roles#textalternativecomputation
*/
tile.setAttribute('role', 'presentation');
//tile.src = this.getTileUrl(coords);
this.getTileUrl(coords, tile, done);
return tile;
}
/*
_loadTile: function(tile, tilePoint) {
tile._layer = this;
tile.onload = this._tileOnLoad;
tile.onerror = this._tileOnError;
this._adjustTilePoint(tilePoint);
this.getTileURL(tilePoint, tile);
this.fire("tileloadstart", { tile: tile, url: tile.src } );
},
*/
});
L.offlineTileLayer = function(url, options) {
return new L.OfflineTileLayer(url, options);
};
var offline = L.offlineTileLayer("http://NOWHERE", {attribution: 'Map data &copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors', maxZoom: 22});
Stamen_TonerHybrid = L.tileLayer('https://stamen-tiles-{s}.a.ssl.fastly.net/toner-hybrid/{z}/{x}/{y}{r}.{ext}', {
attribution: 'Map tiles by <a href="http://stamen.com">Stamen Design</a>, <a href="http://creativecommons.org/licenses/by/3.0">CC BY 3.0</a> &mdash; Map data &copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
subdomains: 'abcd',
@ -82,6 +189,7 @@ function onDeviceReady() {
map = L.map('map', { layers: [osm], contextmenu: true, zoomControl: false} ).setView([48,13],12);
var baseMaps = {
'Offline': offline,
"Openstreetmap": osm,
"Landscape": tfland,
"Transport": tftrans,
@ -90,8 +198,7 @@ function onDeviceReady() {
"OpenCycleMap": tfcycle,
"OpenTopoMap" : opentopo,
"Sat": sat,
"Hybdir": hybrid
<!-- 'Offline': offline -->
"Sat/Hybrid": hybrid
};
var baseMapControl = new L.control.layers(baseMaps, {}, { collapsed: true, position: 'topright' } ).addTo(map);
@ -111,11 +218,10 @@ function onDeviceReady() {
new L.Control.Zoom({position: "topleft" }).addTo(map);
// prediction
L.easyButton('<span id="targetbtn" class="target">&target;</span>', function(btn, map) {
tbtn = L.easyButton('<span id="targetbtn" class="target">&target;</span>', function(btn, map) {
getPrediction();
}).addTo(map);
t = L.DomUtil.get("targetbtn");
if(t) { L.DomEvent.on(t, 'contextmenu', function(e) { tawhiriCtl.toggle(); } ); }
L.DomEvent.on(tbtn.button, 'contextmenu', function(e) { tawhiriCtl.toggle(); } );
map.locate({setView: true, maxZoom: 16});
@ -143,7 +249,7 @@ function onDeviceReady() {
tawhiriContent.appendChild(infoContent);
this._tawhiriBody = tawhiriBody;
this._infoCloseButton = infoCloseButton;
this._showContent();
this._hideContent();
L.DomEvent.disableClickPropagation(tawhiriContainer);
L.DomEvent.on(infoCloseButton, 'click', L.DomEvent.stop);
@ -151,7 +257,7 @@ function onDeviceReady() {
return tawhiriContainer;
},
toggle: function() {
if(this._contentShown==false) { this._showContent(); } else { this._hideContent(); }
if(this._contentShown==false) { this._showContent(); } else { this._hideContent(); }
},
_hideContent: function(ev) {
this._tawhiriBody.style.display = 'none';
@ -166,7 +272,7 @@ function onDeviceReady() {
})
tawhiriCtl = new TawhiriCtl();
tawhiriCtl.addTo(map);
var Infobox = L.Control.extend({
options: { position: 'bottomcenter' },
@ -206,10 +312,16 @@ function onDeviceReady() {
"<table style=\"width:100%;\"><tr><td>403.012 MHz</td><td style=\"float:right; font-size:0.9em;\">+ 1.2 kHz</td></tr></table>",
"12345m &nbsp; 102.4km/h &nbsp; -12.2m/s", "RSSI -90.5 ||||...EEE||||");
*/
this._icd = 0;
this._layout = 0;
this._gpsHeading = 0;
this._gpsHeadingGood = false;
return infoContainer;
},
toggle: function() {
if(this._contentShown == false) { this._showContent(); } else { this._hideContent(); }
if(this._contentShown == false) { this._showContent(); }
else if (this._layout==0) { this._showCompass(); }
else { this._hideContent(); }
},
setContent: function(obj) {
//alert(JSON.stringify(obj));
@ -217,31 +329,104 @@ function onDeviceReady() {
if(obj.type == null) obj.type = "RS41"; // TODO fix in plugin
distance = "";
distance = L.latLng(obj).distanceTo(L.latLng(mypos))
if(distance>9999) { distance = distance.toFixed(0); }
else { distance = distance.toFixed(1); }
distance = "d=" + distance + "m";
if(distance>9999) { distance = "d=" + (0.001*distance).toFixed(1) + "km"; }
else if (distance>99) { distance = "d=" + distance.toFixed(0) + "m"; }
else { distance = "d=" + distance.toFixed(1) + "m"; }
sym = "<span class=\"lifenessinfo\">&#x2B24; </span>";
l1 = "<table class=\"infotable\"><tr><td class=\"infotd\">" + sym + obj.type + "</td><td class=\"infotdr\">" + obj.ser + "</td></tr></table>";
l2 = "<table class=\"infotable\"><tr><td class=\"infotd\">" + (1*obj.freq).toFixed(3) + " MHz </td><td class=\"infotdr\" style=\”font-size:0.9em;\">" + (0.001*obj.afc).toFixed(2) + " kHz</td></tr></table>";
l3 = "<table class=\"infotable\"><tr><td class=\"infotd\">" + obj.alt.toFixed(0) + "m</td><td class=\"infotd\">" + obj.vs + "m/s </td><td class=\"infotdr\">" + (obj.hs*3.6).toFixed(1) + "km/h </td></tr></table>";
l4 = "<table class=\"infotable\"><tr><td class=\"infotd\">RSSI: " + -0.5*obj.rssi + " </td><td class=\"infotdr\">" + distance + " </td></tr></table>";
// normal layout
if(this._layout==0) {
l2 = "<table class=\"infotable\"><tr><td class=\"infotd\">" + (1*obj.freq).toFixed(3) + " MHz </td><td class=\"infotdr\" style=\”font-size:0.9em;\">" + (0.001*obj.afc).toFixed(2) + " kHz</td></tr></table>";
l2 += "<table class=\"infotable\"><tr><td class=\"infotd\">" + ll2str(obj.lat,false) + "</td><td class=\"infotdr\">" + ll2str(obj.lon,true) + " </td></tr></table>";
l3 = "<table class=\"infotable\"><tr><td class=\"infotd\">" + obj.alt.toFixed(0) + "m</td><td class=\"infotd\">" + obj.vs + "m/s </td><td class=\"infotdr\">" + (obj.hs*3.6).toFixed(1) + "km/h </td></tr></table>";
l4 = "<table class=\"infotable\"><tr><td class=\"infotd\">RSSI: " + -0.5*obj.rssi + " </td><td class=\"infotdr\">" + distance + " </td></tr></table>";
} else {
var b = L.latLng(mypos).bearingTo(L.latLng(obj));
l2 = '<table class="infotable"><tr><td><svg width="100" height="110">' +
'<marker id="arrowhead" fill="#f00" markerWidth="10" markerHeight="7" refX="10" refY="3.5" orient="auto"> ' +
'<polygon points="0 0, 10 3.5, 0 7" />' +
'</marker>' +
' <circle cx="50" cy="60" r="40" stroke="black" stroke-width="2" fill="#ffe" /> ' +
'<text x="50" y="14" font-size="smaller" fill="black" dominant-baseline="middle" text-anchor="middle">N</text>' +
'<rect visible=0 id="imgCompDir" x="46" y="12" width="8" height="16" transform="rotate(' + (this._icd) + ',50,60)"/>' +
'<line id="imgToSonde" x1="50" y1="60" x2="50" y2="20" stroke="#f00" stroke-width="2" marker-end="url(#arrowhead)" transform="rotate('
+ b + ',50,60)" />' +
'<circle id="imgMoveDir" cx="50" cy="20" r="5" stroke="black" stroke-width="1" fill="' + (this._gpsHeadingGood?"yellow":"lightgray") + '" transform="rotate(' + this._gpsHeading + ',50,60)"/> ' +
'</svg> ';
l2 += '</td><td class="infotd infomax">';
l2 += distance + '<br>';
l2 += '<span class="infocontentl3">'+ obj.alt.toFixed(0) + "m "+obj.vs+'m/s </span><br>';
l2 += '<span class="infocontentl3">'+ (obj.hs*3.6).toFixed(1)+' km/h</span><br>';
l2 += 'RSSI: '+ -0.5*obj.rssi + '</td></tr></table>'
l3 = "";
l4 = "";
}
this._infoContentL1.innerHTML = l1;
this._infoContentL2.innerHTML = l2;
this._infoContentL3.innerHTML = l3;
this._infoContentL4.innerHTML = l4;
this._currentObj = obj;
},
setStatus: function(status) { // 0: rx, 1=to, 2=err, ...
L.DomUtil.setClass(this._infoContentL1, "infocontent infocontentl1 infocontent-status"+status);
},
_hideContent: function(ev) {
if(this._layout == 1) { this._hideCompass(); }
this._infoBody.style.display = 'none';
this._infoCloseButton.style.display = 'none';
this._contentShown = false;
},
_showContent: function(ev) {
if(this._layout == 1) { this._hideCompass(); this._layout = 0; }
this._infoBody.style.display = '';
this._infoCloseButton.style.display = '';
this._contentShown = true;
this.setContent(this._currentObj);
},
_hideCompass: function() {
window.removeEventListener("deviceorientationabsolute", this._orientationListener);
},
_showCompass: function(ev) {
if(this._contentShown && this._layout==1) return;
this._layout = 1
this._infoBody.style.display = '';
this._infoCloseButton.style.display = '';
this._contentShown = true;
this.setContent(this._currentObj);
window.addEventListener("deviceorientationabsolute", this._orientationListener, true);
},
_orientationListener: function(event) {
var icd = document.getElementById("imgCompDir");
if(!icd) return;
infobox._icd = 360-event.alpha;
icd.setAttribute("transform","rotate(" + infobox._icd + ",50,60)");
},
_updateMypos: function(obj) {
if(obj.dir>0) { this._gpsHeading = obj.dir; this._gpsHeadingGood = true; } else { this._gpsHeadingGood = false; }
console.log("update GPS dir: "+obj.dir);
if(this._contentShown && this._layout==1) {
var imd = document.getElementById("imgMoveDir");
if(!imd) return;
if(this._gpsHeadingGood == false) {
imd.setAttribute("fill", "lightgray");
imd.setAttribute("transform", "rotate(" + this._gpsHeading + ",50,60)");
} else {
imd.setAttribute("fill", "yellow");
imd.setAttribute("transform", "rotate(" + this._gpsHeading + ",50,60)");
}
if(obj.hdop<0) { // GPS fix lost
} else {
var p0 = L.latLng(obj);
var p1 = L.latLng(this._currentObj);
var b = p0.bearingTo(p1);
var d = p0.distanceTo(p1);
this._icd = b;
//console.log("mypos "+p0+" and sondepos "+p1+": bearing: "+b+", distance: "+d);
var icd = document.getElementById("imgToSonde");
icd.setAttribute("transform", "rotate(" + b + ",50,60)");
// TODO: also update distance to target
}
}
},
});
infobox = new Infobox();
@ -267,12 +452,23 @@ function onDeviceReady() {
ttgoStatus = L.easyButton( {
ttgourl: "http://192.168.42.1",
states: [{ stateName: 'offline',
icon: '<span class="ttgostatus">' + crossMark + '</span>'
, onClick: function(btn, map) { btn.state('online'); }
//icon: '<span class="ttgostatus">' + crossMark + '</span>'
icon: '<img width=24 height=24 src="img/ttgooff.png"/>'
, onClick: function(btn, map) { /* just for testing btn.state('online');*/ }
},
{ stateName: 'online',
icon: '<span style="color: transparent; text-shadow: 0 0 0 #009900; font-size:15pt" class="ttgostatus">' + checkMark + '</span>',
onClick: function(btn, map) { cordova.InAppBrowser.open(btn.ttgourl, '_blank', "location=yes"); }
//icon: '<span style="color: transparent; text-shadow: 0 0 0 #009900; font-size:15pt" class="ttgostatus">' + checkMark + '</span>',
icon: '<img width=24 height=24 src="img/ttgoon.png"/>',
onClick: function(btn, map) {
var app = cordova.InAppBrowser.open(btn.ttgourl, '_blank', "location=yes,beforeload=yes");
app.addEventListener("loadstart", function(e) {
if(e.url.startsWith("geo:")) {
//alert("external: "+e.url);
RdzWx.showmap(e.url, function(){});
app.close();
}
});
}
}
],
position: "topright"
@ -280,7 +476,8 @@ function onDeviceReady() {
ttgoStatus.state('offline');
ttgoStatus.addTo(map);
// '<span class="ttgosttus">&#9989;</span>', )
L.control.mousePosition({position: 'bottomleft', emptyString: ''}).addTo(map);
ballonIcon = L.icon({
iconUrl: "img/ballon.png",
@ -305,8 +502,69 @@ function onDeviceReady() {
setInterval(periodicStatusCheck, 1000);
// just for testing
update( {res: 0, validId: 1, validPos: 127, id: "A1234567", lat: 48, lon: 13, alt: 10000, vs: 10, hs: 30, rssi: -90, rxStat: "||||||||||||....", type: "RS41", freq: "400.000", afc: "+1.2", ser: "A1234567"} );
update( {res: 0, validId: 1, validPos: 127, id: "A1234567", lat: 48.8621, lon: 12.064, alt: 20744, vs: 4.8, hs: 11.0, rssi: -90, rxStat: "||||||||||||....", type: "RS41", freq: "400.000", afc: "+1.2", ser: "A1234567"} );
var g = localStorage.getItem('lastgps');
if(g) { mypos = JSON.parse( g ); }
mypos.hdop = -1;
// create mypos marker
myposMarker = new L.marker(mypos, {
contextmenu: true,
contextmenuItems: [{
text: "Zoom to location",
callback: function(e) { b=new L.LatLngBounds([myposMarker.getLatLng()]); map.fitBounds(b, {maxZoom: 16}); }
}]
});
myposMarker.addTo(map);
updateMypos(mypos);
myposMarker.bindPopup( function(lay) {
var alt = lay.getLatLng().alt;
if(!alt) alt = 0;
return '<div class="pop-header"><img src="css/images/marker-icon.png"/><h4> Current position </h4></div>' +
'<p>Lat: ' + lay.getLatLng().lat.toFixed(5) + '<br>' +
'Lon: ' + lay.getLatLng().lng.toFixed(5) + '<br>' +
'Altutide: ' + alt + '</p>' +
'<p>HDOP: ' + (lay.hdop>0 ? lay.hdop : 'no GPS fix') + '</p>';
});
document.addEventListener("pause", onPause);
document.addEventListener("resume", onResume);
document.addEventListener("backbutton", onBackButton);
}
function ll2str(l,islon) {
var res;
if(islon) { res = l<0 ? "W":"E"; }
else { res = l<0 ? "S":"N"; }
if(l<0) l=-l;
return res + l.toFixed(5);
}
// so let's try this approach for state management
// - "back" button on main screen -> close app (state is lost)?
// - "pause" event with TTGO connected: keep connection and all running in background, create notification entry
// without TTGO connected: stop background thread
// - "resume" event: if stopped, start background thread
function onPause() {
if(ttgoStatus.state() == 'offline') {
console.log("onPause(): TTGO is offline, stopping all activities");
window.localStorage.setItem('lastgps', JSON.stringify(mypos));
RdzWx.stop("", function(){});
} else {
console.log("onPause(): TTGO is online, keeping activities running in background");
}
}
function onResume() {
console.log("onResume()");
//if(ttgoStatus.state() == 'offline') {
// if already started (not stopped in onPause()), start will do nothign....
RdzWx.start("testarg", callBack);
//}
}
function onBackButton() {
console.log("onBackButton(): Exit");
window.localStorage.setItem('lastgps', JSON.stringify(mypos));
RdzWx.stop("", function(){});
navigator.app.exitApp(); // note: this will also call onPause()
}
function formatParams(params) {
@ -316,7 +574,7 @@ function formatParams(params) {
}
// borrowed from wetterson.de/karte .....
function calc_drag(drag,alt){
function calc_drag(drag,alt,desc){
if (alt < 1000 ){
drag = drag * 1;
} else if (alt < 2000){
@ -338,7 +596,7 @@ function calc_drag(drag,alt){
dragfak = (( alt - 10000 )* ( 0.3 - 0.55) / ( 20000 - 10000)) + 0.55;
drag = drag * dragfak;
} else {
drag = 5;
drag = desc;
}
return drag;
}
@ -350,7 +608,8 @@ function removePrediction(marker) {
}
function getPrediction(refobj) {
TAWHIRI = 'http://predict.cusf.co.uk/api/v1';
// going out of service soon... TAWHIRI = 'http://predict.cusf.co.uk/api/v1';
TAWHIRI = 'https://api.v2.sondehub.org/tawhiri';
if(refobj == null) { refobj = lastMarker; }
if(refobj == null) {
alert("no object available");
@ -365,15 +624,17 @@ function getPrediction(refobj) {
var desc = document.getElementById("tawhiri-descent").value;
if(desc) desc=parseFloat(desc); else desc=5.0;
var usecurrent = document.getElementById("tawhiri-current").checked;
var lon = refobj.obj.lon;
if(lon<0) lon+=360; // tawhiri api needs 0..360
var tParams = {
"launch_latitude": refobj.obj.lat,
"launch_longitude": refobj.obj.lon,
"launch_altitude": refobj.obj.alt,
"launch_longitude": lon,
"launch_altitude": refobj.obj.alt.toFixed(1),
"launch_datetime": new Date().toISOString().split('.')[0] + 'Z',
"ascent_rate": asc,
"descent_rate": desc,
"burst_altitude": refobj.obj.alt+2,
"burst_altitude": (refobj.obj.alt+2).toFixed(1),
"profile": "standard_profile",
}
var vs = refobj.obj.vs;
@ -384,9 +645,9 @@ function getPrediction(refobj) {
if(vs > 0) {
// still climbing up
tParams["ascent_rate"] = usecurrent ? vs : asc;
tParams["burst_altitude"] = burst;
if(burst > refobj.obj.alt+2) { tParams["burst_altitude"] = burst; }
} else {
tParams["descent_rate"] = usecurrent ? calc_drag( -vs, refobj.obj.alt ) : desc;
tParams["descent_rate"] = usecurrent ? calc_drag( -vs, refobj.obj.alt, desc ) : desc;
}
const xhr = new XMLHttpRequest();
const url = TAWHIRI + formatParams(tParams);
@ -400,16 +661,28 @@ function getPrediction(refobj) {
var traj0 = pred.prediction[0].trajectory; // 0 is ascent, 1 is descent...
var traj1 = pred.prediction[1].trajectory; // 0 is ascent, 1 is descent...
var latlons = [];
traj0.forEach( p => latlons.push( [p.latitude, p.longitude] ) );
traj1.forEach( p => latlons.push( [p.latitude, p.longitude] ) );
traj0.forEach( p => latlons.push( [p.latitude, wrap(p.longitude)] ) );
traj1.forEach( p => latlons.push( [p.latitude, wrap(p.longitude)] ) );
//alert("path: "+JSON.stringify(traj));
poly = L.polyline(latlons, { opacity: 0.5, color: '#EE0000', dashArray: '8, 6'} );
poly = L.polyline(latlons, { opacity: 0.7, color: '#EE0000', dashArray: '8, 6'} );
poly.addTo(map);
if( refobj.pred ) { refobj.pred.remove(map); }
refobj.pred = poly;
if( refobj.land ) { refobj.land.remove(map); }
refobj.land = new L.marker(latlons.slice(-1)[0], {icon: landingIcon});
refobj.land = new L.marker(latlons.slice(-1)[0], {icon: landingIcon,
contextmenu: true,
contextmenuItems: [{
text: "Zoom to location",
callback: function(e) { b=new L.LatLngBounds([refobj.land.getLatLng()]); map.fitBounds(b, {maxZoom: 16}); }
}, {
separator: true
}, {
text: "Export to map app",
callback: function(e) { ll=refobj.land.getLatLng(); uri="geo:0:0?q="+ll.lat+","+ll.lng+"(X-"+refobj.obj.id+")"; RdzWx.showmap(uri, function(){}); }
}]
});
refobj.land.addTo(map);
if( refobj.burst ) { refobj.burst.remove(map); }
if( vs>0 ) { // still climbing, so add burst mark
var b = traj0.slice(-1)[0];
@ -421,7 +694,7 @@ function getPrediction(refobj) {
var popup = '<div class="pop-header"><img src="img/landing.png"><h4> Landing Point </h4></div>' +
'<strong>Time: ' + lastpt.datetime + '</strong><br/>' +
'<strong>(' + new Date(lastpt.datetime).toTimeString().split(" (")[0] + ')</strong><br/>' +
'<p> Altitude: ' + lastpt.altitude.toFixed(2) + ' m'+
'<p> Altitude: ' + lastpt.altitude.toFixed(1) + ' m'+
'</br>Asc. Rate: ' + tParams["ascent_rate"].toFixed(2) + ' m/s'+
'</br>Burst: ' + tParams["burst_altitude"] + ' m'+
'</br>Desc. Rate: ' + tParams["descent_rate"].toFixed(2) + ' m/s</p>' +
@ -436,38 +709,55 @@ function getPrediction(refobj) {
function callBack(arg) {
var obj;
try {
console.log("callback: "+arg);
obj = JSON.parse(arg);
} catch(err) {
console.log("callBack: JSON error: "+arg+": "+err.message);
return;
}
console.log("callback: "+JSON.stringify(arg));
//if(obj.res || obj.msgtype) {
update(obj);
//}
// for now, only for electron (does not support keepCallback)
//RdzWx.next(callBack);
}
function updateMypos(obj) {
console.log("updateMypos");
infobox._updateMypos(obj);
if(obj.hdop<0) {
// GPS fix lost
console.log("gps fix lost");
if(myposMarker.hdop) myposMarker.hdop = 0;
if(myposMarker.hdopCircle) {
map.removeLayer(myposMarker.hdopCircle);
myposMarker.hdopCircle = null;
}
return;
}
mypos = obj;
var pos = [obj.lat, obj.lon]
if(myposMarker == null) {
// create marker
myposMarker = new L.marker(pos);
myposMarker.addTo(map);
var pos = [obj.lat, obj.lon, obj.alt];
myposMarker.setLatLng(pos);
myposMarker.update();
if(myposMarker.hdop) {
myposMarker.hdopCircle.setLatLng(pos)
if(obj.hdop != myposMarker.hdop) {
myposMarker.hdopCircle.setRadius(obj.hdop);
myposMarker.hdop = obj.hdop;
}
} else {
myposMarker.setLatLng(pos);
myposMarker.update();
if(obj.hdop) {
myposMarker.hdopCircle = L.circle(pos, {radius: obj.hdop, dashArray: "2 2" }).addTo(map);
myposMarker.hdop = obj.hdop;
}
}
}
var lastMsgTS = 0;
function periodicStatusCheck() {
now = new Date();
if( lastMsgTS && (now-lastMsgTS) > 5000 ) {
if( lastMsgTS && (now-lastMsgTS) > 10000 ) {
// handle connection broken (if still connnected)
//alert("Closing conn: "+now+" vs "+lastMsgTS);
console.log("no data for 5 seconds, closing connection to rdzTTGOsonde");
console.log("no data for 10 seconds, closing connection to rdzTTGOsonde");
lastMsgTS = 0;
RdzWx.closeconn("", function(){});
}
}
@ -478,11 +768,11 @@ function update(obj) {
return;
}
lastMsgTS = new Date();
console.log("update: "+lastMsgTS);
if(obj.msgtype) {
if(obj.msgtype == "ttgostatus") {
ttgoStatus.ttgourl = 'http://' + obj.ip;
ttgoStatus.state(obj.state)
if(obj.state=="offline") { infobox.setStatus(1); }
}
if(obj.msgtype == "gps") {
updateMypos(obj);
@ -492,73 +782,122 @@ function update(obj) {
}
// position update
if( ((obj.validPos&0x03) != 0x03) || ((obj.validPos&0x80)!=0) ) { // latitude and longitude are invalid
console.log("invalid position, ignoring");
return;
}
console.log("Pos update: "+JSON.stringify(obj));
//console.log("Pos update: "+JSON.stringify(obj));
if(obj.egmdiff && obj.alt) { obj.alt -= obj.egmdiff; }
infobox.setContent(obj);
infobox.setStatus(obj.res);
if( (!obj.validId) || (!obj.validPos) || (obj.res!=0) ) {
var isValidPos = true;
if( ((obj.validPos&0x03) != 0x03) || ((obj.validPos&0x80)!=0) ) { // latitude and longitude are invalid
isValidPos = false;
}
var marker;
if( (!obj.validId) || (!isValidPos) || (obj.res!=0) ) {
// no valid pos...
// res: 1=Timeout, 2=CRC error, 3=unknown, 4=no position
console.log("valid: "+(!obj.validId)+" validPos: "+(!obj.validPos)+" res: "+(obj.res!=0));
console.log("update with no valid pos");
// Check if it is an object marked "old" from TTGO which we do not yet have on the map
if( ((obj.validPos&0x3)==0x3) && obj.validId && !markers[obj.id]) {
console.log("pos update: Adding old TTGO pos: "+JSON.stringify(obj));
marker = createNewMarker(obj);
updateMarkerTooltip(marker, obj);
markers[obj.id] = marker;
lastMarker = marker
} else {
console.log("pos update: No valid update: "+JSON.stringify(obj));
}
return;
}
console.log("Good update!");
console.log("pos update: Good update! "+JSON.stringify(obj));
var pos = new L.LatLng(obj.lat, obj.lon);
var marker;
var tooltip;
if(markers[obj.id]) {
marker = markers[obj.id];
if(pos.equals(marker.getLatLng())) { console.log("update: position unchanged"); }
else { marker.path.addLatLng(pos); console.log("update: appending new position"); }
tooltip = marker.tt;
marker.vsavg = 0.9 * marker.vsavg + 0.1 * obj.vs;
} else {
console.log("creating new marker");
marker = new L.marker(pos, {icon: ballonIcon,
contextmenu: true,
contextmenuItems: [{
/*
text: "Show info",
callback: function(e) { alert("not available yet"); }
}, {
*/
text: "Make prediction",
callback: function(e) { getPrediction(marker); }
}, {
text: "Configure prediction",
callback: function(e) { tawhiriCtl.toggle(); }
}, {
text: "Remove prediction",
callback: function(e) { removePrediction(marker); }
}, {
separator: true
}, {
text: "Delete item",
callback: function(e) { removePrediction(marker); map.removeLayer(marker); if(marker==lastMarker) lastMarker=null; }
}]
});
poly = L.polyline(pos, { opacity: 0.5, color: '#3388ff'} );
marker.path = poly;
//marker.on('clock', function() { showMarkerInfoWindow( obj.id, pos) } );
marker = createNewMarker(obj);
markers[obj.id] = marker;
marker.addTo(map);
poly.addTo(map);
tooltip = L.tooltip({ direction: 'right', permanent: true, className: 'sondeTooltip', offset: [10,-16], interactive: false, opacity: 0.6 });
marker.bindTooltip(tooltip);
marker.tt = tooltip;
marker.vsavg = obj.vs;
}
lastMarker = marker;
lastMarker.obj = obj;
var tt = '<div class="tooltip-container">' + obj.id + '<div class="text-speed tooltip-container">' + obj.alt + 'm '+ obj.vs +'m/s ' + (obj.hs*3.6).toFixed(1) + 'km/h </div></div>';
tooltip.setContent(tt);
updateMarkerTooltip(marker, obj);
}
function updateMarkerTooltip(marker, obj) {
var tt = '<div class="tooltip-container">' + obj.id + '<div class="text-speed tooltip-container">' + obj.alt.toFixed(1) + 'm '+ obj.vs +'m/s ' + (obj.hs*3.6).toFixed(1) + 'km/h </div></div>';
marker.tt.setContent(tt);
marker.setLatLng( new L.LatLng(obj.lat, obj.lon));
marker.obj = obj;
marker.getPopup().update();
marker.update();
}
function createNewMarker(obj) {
console.log("creating new marker");
var pos = new L.LatLng(obj.lat, obj.lon);
var marker = new L.marker(pos, {icon: ballonIcon,
contextmenu: true,
contextmenuItems: [{
text: "Make prediction",
callback: function(e) { lastMarker = marker; getPrediction(marker); }
}, {
text: "Configure prediction",
callback: function(e) { tawhiriCtl.toggle(); }
}, {
text: "Remove prediction",
callback: function(e) { removePrediction(marker); }
}, {
separator: true
}, {
text: "Zoom to location",
callback: function(e) { b=new L.LatLngBounds([[marker.obj.lat, marker.obj.lon]]); map.fitBounds(b, {maxZoom: 16}); }
}, {
separator: true
}, {
text: "Export to map app",
callback: function(e) { uri="geo:0:0?q="+marker.obj.lat+","+marker.obj.lon+"("+marker.obj.id+")"; RdzWx.showmap(uri, function(){}); }
}, {
separator: true
}, {
text: "Delete item",
callback: function(e) { deleteMarker(marker); }
}]
});
poly = L.polyline(pos, { opacity: 0.8, color: '#3388ff'} );
marker.path = poly;
marker.addTo(map);
poly.addTo(map);
var tooltip = L.tooltip({ direction: 'right', permanent: true, className: 'sondeTooltip', offset: [10,-16], interactive: true, opacity: 0.6 });
marker.setLatLng(pos);
marker.update(); // necessary?
marker.bindTooltip(tooltip);
marker.tt = tooltip;
marker.vsavg = obj.vs;
marker.obj = obj;
marker.bindPopup( function(lay) {
var alt = lay.getLatLng().alt;
if(!alt) alt = 0;
return '<div class="pop-header"><img src="img/ballon.png"/><h4> ' + lay.obj.id + '</h4></div>' +
'<p>Serial: '+ lay.obj.ser + '<br>' +
''+(new Date(1000*lay.obj.time)).toString().split(" (")[0] + '<br/>' +
'(' + formathms( new Date().valueOf() / 1000 - lay.obj.time ) + ' ago) <br/>' +
'Frame #'+lay.obj.frame+', Sats='+lay.obj.sats + '<br/>' +
'burstKT='+formathms(lay.obj.burstKT)+'<br>launchKT='+formathms(lay.obj.launchKT)+'<br>countdown='+formathms(lay.obj.countKT+lay.obj.crefKT-lay.obj.frame)+'<br/>' +
'</p>';
});
return marker;
}
function formathms(ts) {
if(typeof ts === "undefined") { return "<undef>"; }
var h = Math.floor(ts/3600); ts-=h*3600;
var m = Math.floor(ts/60); ts=Math.floor(ts-m*60);
return ("0"+h).slice(-2) + ":" + ("0"+m).slice(-2) + ":" + ("0"+ts).slice(-2);
}
function deleteMarker(m) {
removePrediction(m);
m.unbindTooltip();
map.removeLayer(m.path);
map.removeLayer(m);
if(m==lastMarker) lastMarker=null;
delete markers[m.obj.id];
}
function createButton(label, container) {
@ -567,3 +906,20 @@ function createButton(label, container) {
btn.innerHTML = label;
return btn;
}
function wrap(lng) {
if(lng>180) { return lng-360; }
return lng;
}
// radiosondy.info
function reqauth() {
var xhr = new XMLHttpRequest();
xhr.open("POST", "https://radiosondy.info/user/login.php?", true);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.onreadystatechange = function() {
if(http.readyState == 4 && http.satus == 200) {
alert(http.resonseText);
}
}
xhr.send('submitted=1&username=DL9RDZ&password=ct1jzmhr&Submit=Login');
}

Wyświetl plik

@ -11,10 +11,13 @@
if (typeof define === 'function' && define.amd) {
// AMD
define(['leaflet'], factory);
/*
// not working well with Cordova/electron
} else if (typeof module === 'object' && typeof module.exports === 'object') {
// Node/CommonJS
L = require('leaflet');
module.exports = factory(L);
*/
} else {
// Browser globals
if (typeof window.L === 'undefined') {