kopia lustrzana https://github.com/dl9rdz/rdzwx-go
Porównaj commity
75 Commity
Autor | SHA1 | Data |
---|---|---|
Hans P. Reiser | 066e455ab6 | |
Hans P. Reiser | 8debacde53 | |
Hans P. Reiser | 3d44b7f0e3 | |
Hans P. Reiser | 5b863f7a1a | |
Hans P. Reiser | 3e23aa56b5 | |
Hans P. Reiser | c22720f132 | |
Hansi, dl9rdz | 6a3af0ad76 | |
Hans P. Reiser | a63a742e39 | |
Hansi, dl9rdz | 0fe5f00751 | |
Hansi, dl9rdz | b3808f8e26 | |
Hansi, dl9rdz | 1e02a92714 | |
Hansi, dl9rdz | 1d54b2e4dc | |
Hansi, dl9rdz | 9ab62faf25 | |
Hansi, dl9rdz | 17d679bbd8 | |
Hansi, dl9rdz | 201c4f412a | |
Hansi, dl9rdz | fe7977bcd5 | |
Hansi, dl9rdz | 92e64c1cbc | |
Hansi, dl9rdz | b369d7c8d4 | |
Hansi, dl9rdz | 8fb2461c0c | |
Hansi, dl9rdz | f5f41fc192 | |
Hansi, dl9rdz | be6d7d5208 | |
Hansi, dl9rdz | f7d0b306dc | |
Hansi, dl9rdz | 3c3154a57b | |
Hansi, dl9rdz | 604f2f14ac | |
Hansi, dl9rdz | 6a733ce6d6 | |
Hansi, dl9rdz | e955bec659 | |
Hansi, dl9rdz | 8e3d1d9fd8 | |
Hansi, dl9rdz | e39a936336 | |
Hansi, dl9rdz | fe26ec60c2 | |
Hansi, dl9rdz | 3152941df9 | |
Hansi, dl9rdz | 398dad6f8e | |
Hansi, dl9rdz | 7ecff3f7e7 | |
Hansi, dl9rdz | c1fbd05ee1 | |
Hansi, dl9rdz | c998771c05 | |
Hansi, dl9rdz | 963cebeeb2 | |
Hansi, dl9rdz | 85f23a3082 | |
Hansi, dl9rdz | d549cbc836 | |
Hansi, dl9rdz | 4ee76661f2 | |
Hansi, dl9rdz | 00c1113cdf | |
Hansi, dl9rdz | f2241dae35 | |
Hansi, dl9rdz | 1642bcd8d6 | |
Hansi, dl9rdz | e0969103e6 | |
Hansi, dl9rdz | 3fc7d4bced | |
Hansi, dl9rdz | 192a8e6df7 | |
Hansi, dl9rdz | 7e4c06018b | |
Hansi, dl9rdz | 81cb6471d2 | |
Hansi, dl9rdz | 69e96cd166 | |
Hansi, dl9rdz | 3f4849389c | |
Hansi, dl9rdz | 5624735548 | |
Hansi, dl9rdz | 802e6662ea | |
Hansi, dl9rdz | e57e69786a | |
Hansi, dl9rdz | 783716bf55 | |
Hansi, dl9rdz | 231412810e | |
Hansi, dl9rdz | e4a3936c51 | |
Hansi, dl9rdz | b17d83c1a7 | |
Hansi, dl9rdz | 2ed799ac31 | |
Hansi, dl9rdz | 71476626f7 | |
Hansi, dl9rdz | d5ee287f9a | |
Hansi, dl9rdz | 02bfc0ee8c | |
Hansi, dl9rdz | 9f0d3b7220 | |
Hansi, dl9rdz | c714769ee1 | |
Hansi, dl9rdz | d1b1e74bd4 | |
Hansi, dl9rdz | 17a4e44203 | |
Hansi, dl9rdz | 7531b4be0a | |
Hansi, dl9rdz | 233fd21ec5 | |
Hansi, dl9rdz | 4f2101edd9 | |
Hansi, dl9rdz | b71b2e4f8f | |
Hansi, dl9rdz | 7e37c31463 | |
Hansi, dl9rdz | 4271a97027 | |
Hansi, dl9rdz | 7d7e9f64eb | |
Hansi, dl9rdz | 568fc2bc57 | |
Hansi, dl9rdz | 4c0e8609f1 | |
Hansi, dl9rdz | 31584d2291 | |
Hansi, dl9rdz | 2d191275cc | |
Hansi, dl9rdz | 687bf3e91e |
|
@ -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
|
||||
|
||||
|
|
@ -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.
|
|
@ -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
|
||||
|
13
README.md
13
README.md
|
@ -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
|
||||
|
|
14
config.xml
14
config.xml
|
@ -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.
33
package.json
33
package.json
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"browserWindow": {
|
||||
"width": 1200,
|
||||
"height": 800,
|
||||
"webPreferences": {
|
||||
"nodeIntegration": true,
|
||||
"contextIsolation": false
|
||||
}
|
||||
}
|
||||
}
|
Plik binarny nie jest wyświetlany.
Po Szerokość: | Wysokość: | Rozmiar: 64 KiB |
|
@ -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"
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
Plik binarny nie jest wyświetlany.
Po Szerokość: | Wysokość: | Rozmiar: 834 B |
Plik binarny nie jest wyświetlany.
Po Szerokość: | Wysokość: | Rozmiar: 627 B |
|
@ -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 © 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 © 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("map", function(res) { localStorage.setItem("mapstorage", res); })">Select map file </button>
|
||||
<hr>
|
||||
<button onclick="RdzWx.selstorage("theme", function(res) { localStorage.setItem("mapstorage", 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>
|
||||
|
|
|
@ -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;
|
||||
}
|
564
www/js/index.js
564
www/js/index.js
|
@ -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 = "✔";
|
||||
var crossMark = "❌";
|
||||
|
||||
// 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 = "❌";
|
|||
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: '© <a href="http://www.thunderforest.com/">Thunderforest</a>, © <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: '© <a href="http://www.thunderforest.com/">Thunderforest</a>, © <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: '© <a href="http://www.thunderforest.com/">Thunderforest</a>, © <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'}),
|
||||
opentopo = L.tileLayer('https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png', {attribution: 'Kartendaten: © <a href="https://openstreetmap.org/copyright">OpenStreetMap</a>-Mitwirkende, <a href="http://viewfinderpanoramas.org">SRTM</a> | Kartendarstellung: © <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 © Esri — 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: '© <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 © Esri — 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 © <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> — Map data © <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">⌖</span>', function(btn, map) {
|
||||
tbtn = L.easyButton('<span id="targetbtn" class="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 102.4km/h -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\">⬤ </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">✅</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');
|
||||
}
|
||||
|
|
|
@ -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') {
|
||||
|
|
Ładowanie…
Reference in New Issue