Browse Source

Merge pull request #56 from reynico/web_panel

Web panel
tags/1.5
Nico 3 years ago
committed by GitHub
parent
commit
f3cb154adc
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
37 changed files with 608 additions and 46 deletions
  1. +1
    -0
      .gitignore
  2. +14
    -1
      INSTALL.md
  3. +1
    -0
      README.md
  4. +2
    -7
      common.sh
  5. +21
    -9
      install.sh
  6. +94
    -0
      migrate_data.sh
  7. +1
    -1
      post.py
  8. +20
    -11
      receive.sh
  9. +20
    -13
      receive_meteor.sh
  10. +1
    -1
      rectify.py
  11. +1
    -0
      schedule_meteor.sh
  12. +1
    -0
      schedule_sat.sh
  13. +2
    -2
      sun.py
  14. +9
    -1
      templates/nginx.cfg
  15. +7
    -0
      templates/webpanel/Config.php
  16. +6
    -0
      templates/webpanel/Controller/C_predict.php
  17. +8
    -0
      templates/webpanel/Controller/C_showDetail.php
  18. +6
    -0
      templates/webpanel/Controller/C_showLastImage.php
  19. +11
    -0
      templates/webpanel/Controller/C_showLastImages.php
  20. +0
    -0
      templates/webpanel/Controller/index.html
  21. +74
    -0
      templates/webpanel/Model/Conn.php
  22. +0
    -0
      templates/webpanel/Model/index.html
  23. +23
    -0
      templates/webpanel/Views/V_viewDetail.php
  24. +24
    -0
      templates/webpanel/Views/V_viewLastImage.php
  25. +42
    -0
      templates/webpanel/Views/V_viewLastImages.php
  26. +24
    -0
      templates/webpanel/Views/V_viewPasses.php
  27. +0
    -0
      templates/webpanel/Views/index.html
  28. +7
    -0
      templates/webpanel/detail.php
  29. +6
    -0
      templates/webpanel/footer.php
  30. +27
    -0
      templates/webpanel/header.php
  31. +7
    -0
      templates/webpanel/index.php
  32. +15
    -0
      templates/webpanel/language/en.php
  33. +15
    -0
      templates/webpanel/language/es.php
  34. BIN
      templates/webpanel/logo-small.png
  35. +5
    -0
      templates/webpanel/passes.php
  36. +99
    -0
      templates/webpanel/style.css
  37. +14
    -0
      templates/webpanel_schema.sql

+ 1
- 0
.gitignore View File

@@ -1,2 +1,3 @@
predict/
map/
panel.db

+ 14
- 1
INSTALL.md View File

@@ -11,6 +11,7 @@
- [Install the default configuration files](#install-the-default-configuration-files)
- [Install Meteor software](#install-meteor-software)
- [Setup Nginx](#setup-nginx)
- [Setup Database](#setup-database)
- [Setup RamFS](#setup-ramfs)
- [Cron the scheduling job](#cron-the-scheduling-job)
- [Set your Twitter credentials](#set-your-twitter-credentials)
@@ -60,7 +61,13 @@ sudo apt install -yq predict \
python3-pip \
imagemagick \
libxft-dev \
libxft2
libxft2 \
libjpeg9 \
libjpeg9-dev \
socat \
php7.2-fpm \
php7.2-sqlite \
sqlite3
```

```
@@ -145,6 +152,12 @@ sudo chmod 775 /var/www/wx
sudo cp templates/index.html /var/www/wx/index.html
sudo cp templates/logo-small.png /var/www/wx/logo-small.png
sudo systemctl restart nginx
sudo cp -rp templates/webpanel/* /var/www/wx/
```

### Setup Database
```
sqlite3 "panel.db" < "templates/webpanel_schema.sql"
```

### Setup RamFS


+ 1
- 0
README.md View File

@@ -4,6 +4,7 @@
Most of the code and setup stolen from: [Instructables](https://www.instructables.com/id/Raspberry-Pi-NOAA-Weather-Satellite-Receiver/)

## New Features!
- A webpanel!
- [Meteor M2 full decoding!](METEOR.md)
- Nginx webserver to show images
- Timestamp and satellite name overlay on every image


+ 2
- 7
common.sh View File

@@ -25,7 +25,6 @@ log() {

## current date and folder structure
START_DATE=$(date '+%d-%m-%Y %H:%M')
FOLDER_DATE="$(date +%Y)/$(date +%m)/$(date +%d)"

## sane checks
if [ ! -d "${NOAA_HOME}" ]; then
@@ -44,8 +43,8 @@ if [ ! -d "${RAMFS_AUDIO}/audio/" ]; then
mkdir -m 775 -p "${RAMFS_AUDIO}/audio/"
fi

if [ ! -d "${NOAA_OUTPUT}/image/" ]; then
mkdir -m 775 -p "${NOAA_OUTPUT}/image/"
if [ ! -d "${NOAA_OUTPUT}/images/thumb" ]; then
mkdir -m 775 -p "${NOAA_OUTPUT}/images/thumb"
fi

if [ ! -d "${NOAA_HOME}/map/" ]; then
@@ -55,7 +54,3 @@ fi
if [ ! -d "${NOAA_HOME}/predict/" ]; then
mkdir -m 775 -p "${NOAA_HOME}/predict/"
fi

if [ ! -d "${NOAA_OUTPUT}/image/${FOLDER_DATE}" ]; then
mkdir -m 775 -p "${NOAA_OUTPUT}/image/${FOLDER_DATE}"
fi

+ 21
- 9
install.sh View File

@@ -54,11 +54,22 @@ sudo apt install -yq predict \
libxft2 \
libjpeg9 \
libjpeg9-dev \
socat
socat \
php7.2-fpm \
php7.2-sqlite \
sqlite3

sudo pip3 install numpy ephem tweepy Pillow
log_done "Packages installed"

### Create the database schema
if [ -e "$HOME/raspberry-noaa/panel.db" ]; then
log_done "Database already created"
else
sqlite3 "panel.db" < "templates/webpanel_schema.sql"
log_done "Database schema created"
fi

### Blacklist DVB modules
if [ -e /etc/modprobe.d/rtlsdr.conf ]; then
log_done "DVB modules were already blacklisted"
@@ -173,12 +184,8 @@ sudo cp templates/nginx.cfg /etc/nginx/sites-enabled/default
sudo chmod 775 /var/www/wx
)
sudo systemctl restart nginx
if [ ! -e /var/www/wx/index.html ]; then
sudo cp templates/index.html /var/www/wx/index.html
fi
if [ ! -e /var/www/wx/logo-small.png ]; then
sudo cp templates/logo-small.png /var/www/wx/logo-small.png
fi
sudo cp -rp templates/webpanel/* /var/www/wx/

log_done "Nginx configured"

### Setup ramFS
@@ -229,8 +236,10 @@ sed -i -e "s/change_latitude/${lat}/g;s/change_longitude/${lon}/g" "$HOME/.wxtoi
sed -i -e "s/change_latitude/${lat}/g;s/change_longitude/$(echo "$lon * -1" | bc)/g" "$HOME/.predict/predict.qth"
sed -i -e "s/change_latitude/${lat}/g;s/change_longitude/${lon}/g;s/change_tz/$(echo "$timezone * -1" | bc)/g" "sun.py"

# Running WXTOIMG to have the user accept the licensing agreement
wxtoimg
### Launch scheduler
newgrp www-data << END
/home/pi/raspberry-noaa/schedule.sh
END

success "Install done! Double check your $HOME/.noaa.conf settings"

@@ -238,3 +247,6 @@ echo "
If you want to post your images to Twitter, please setup
your Twitter credentials on $HOME/.tweepy.conf
"

### Running WXTOIMG to have the user accept the licensing agreement
wxtoimg

+ 94
- 0
migrate_data.sh View File

@@ -0,0 +1,94 @@
#!/bin/bash

## import common lib
. "$HOME/.noaa.conf"
. "$HOME/.tweepy.conf"
. "$NOAA_HOME/common.sh"


# Free disk space
FREE_DISK="$(df | grep "/dev/root" | awk {'print $3'})"

# This is the original path where images were stored
BASEPATH="/var/www/wx/image"

# Size of the old images folder
IMAGEPATH_SIZE="$(du -s $BASEPATH | awk {'print $1'})"

SPACE_NEEDED="$((IMAGEPATH_SIZE * 2))"

if [ "$SPACE_NEEDED" -gt "$FREE_DISK" ]; then
echo "You need more free space"
exit 1
fi

# This is the destination path (AKA the new path)
FINALPATH="/var/www/wx/images"

# This is a list of satellite names
SAT_NAMES="NOAA15 NOAA18 NOAA19 METEOR-M2"

# Here's where the database will live
DB_PATH="${NOAA_HOME}/panel.db"

(
# To speed up the migration process and
# reduce the SD card wear, the database
# operations are done over the RAMFS
# partition
cd "${RAMFS_AUDIO}" || exit 1
sqlite3 "$DB_PATH" < "${NOAA_HOME}/templates/webpanel_schema.sql"
)


cd "$BASEPATH" || exit 1

# The webpanel have thumbnails!
mkdir -p "$FINALPATH/thumb"

# Find all the images
for filename in $(find . -name *.jpg); do
# Grab just the filename without the yyyy/mm/dd path
basename="$(echo "$filename" | sed 's~.*/~~')"
for prefix in $SAT_NAMES; do
basedate="$(echo "$basename" | sed -e "s/^$prefix//" | cut -f1,2 -d'-' | sed -e "s/-//")"
if [[ $basename == *"$prefix"* ]]; then
# Grab the satellite name from the file name
sat_name=$prefix
fi
done
date_normalized=$(echo "$basedate" | sed -e "s/^$sat_name//;s/./&:/12;s/./&:/10;s/./& /8;s/./&\//6;s/./&\//4")
epoch_date=$(date "+%s" -d "$date_normalized")
if [[ $basename == *"METEOR"* ]]; then
# Meteor files have one more dash on its name
passname=$(echo "$basename" | cut -f1,2,3 -d'-')
else
passname=$(echo "$basename" | cut -f1,2 -d'-')
fi
echo "Migration in progress: $basename"
cp "$BASEPATH/$filename" "$FINALPATH"

# Create thumbnails for old images
convert -thumbnail 300 "$BASEPATH/$filename" "$FINALPATH/thumb/$basename"
if [[ $basename == *"METEOR"* ]]; then
# Insert each pass on the database. Also insert the pass prediction
sqlite3 "${RAMFS_AUDIO}/panel.db" "INSERT INTO decoded_passes (pass_start, file_path, daylight_pass, is_noaa) VALUES ($epoch_date,\"$passname\",1,0);"
sqlite3 "${RAMFS_AUDIO}/panel.db" "INSERT OR REPLACE INTO predict_passes (sat_name,pass_start,pass_end,max_elev) VALUES (\"$sat_name\",$epoch_date,$epoch_date,0);"
elif [[ $basename == *"ZA"* ]]; then
sqlite3 "${RAMFS_AUDIO}/panel.db" "INSERT OR REPLACE INTO predict_passes (sat_name,pass_start,pass_end,max_elev) VALUES (\"$sat_name\",$epoch_date,$epoch_date,0);"
if [[ -f "$FINALPATH/$passname-MSA.jpg" ]]; then
# MSA requires a daylight pass and daylight pass is a column of decoded_passes so this is the way to grab them
sqlite3 "${RAMFS_AUDIO}/panel.db" "INSERT INTO decoded_passes (pass_start, file_path, daylight_pass, is_noaa) VALUES ($epoch_date,\"$passname\",1,1);"
else
sqlite3 "${RAMFS_AUDIO}/panel.db" "INSERT INTO decoded_passes (pass_start, file_path, daylight_pass, is_noaa) VALUES ($epoch_date,\"$passname\",0,1);"
fi
fi

# Move the database file to its final destination
mv "${RAMFS_AUDIO}/panel.db" "$DB_PATH"
echo "Done."
echo ""
done



+ 1
- 1
post.py View File

@@ -23,4 +23,4 @@ for filename in filenames:
res = api.media_upload(filename)
media_ids.append(res.media_id)

api.update_status(status=argentinaFlag + ' Imagen satelital: ' + sys.argv[1] + '. Elevacion maxima: ' + sys.argv[2] + ' grados. #NOAA #weather #argentinaimagenes #noaasatellite #clima #wxtoimg #raspberrypi #argentina #argentinasat', media_ids=media_ids)
api.update_status(status=argentinaFlag + ' Imagen satelital: ' + sys.argv[1] + '. Elevacion maxima: ' + sys.argv[2] + ' grados. #NOAA #weather #argentinaimagenes #noaasatellite #clima #wxtoimg #raspberrynoaa #argentina #argentinasat', media_ids=media_ids)

+ 20
- 11
receive.sh View File

@@ -28,39 +28,48 @@ fi
log "Starting rtl_fm record" "INFO"
timeout "${6}" /usr/local/bin/rtl_fm ${BIAS_TEE} -f "${2}"M -s 60k -g 50 -E wav -E deemp -F 9 - | /usr/bin/sox -t raw -e signed -c 1 -b 16 -r 60000 - "${RAMFS_AUDIO}/audio/${3}.wav" rate 11025

if [ ! -d "{NOAA_OUTPUT}/image/${FOLDER_DATE}" ]; then
mkdir -m 775 -p "${NOAA_OUTPUT}/image/${FOLDER_DATE}"
fi

if [ "${SUN_ELEV}" -gt "${SUN_MIN_ELEV}" ]; then
ENHANCEMENTS="ZA MCIR MCIR-precip MSA MSA-precip HVC-precip HVCT-precip HVC HVCT"
daylight="true"
else
ENHANCEMENTS="ZA MCIR MCIR-precip"
daylight="false"
fi

log "Bulding pass map" "INFO"
/usr/local/bin/wxmap -T "${1}" -H "${4}" -p 0 -l 0 -o "${PASS_START}" "${NOAA_HOME}/map/${3}-map.png"
for i in $ENHANCEMENTS; do
log "Decoding image" "INFO"
/usr/local/bin/wxtoimg -o -m "${NOAA_HOME}/map/${3}-map.png" -e "$i" "${RAMFS_AUDIO}/audio/${3}.wav" "${NOAA_OUTPUT}/image/${FOLDER_DATE}/${3}-$i.jpg"
/usr/bin/convert -quality 90 -format jpg "${NOAA_OUTPUT}/image/${FOLDER_DATE}/${3}-$i.jpg" -undercolor black -fill yellow -pointsize 18 -annotate +20+20 "${1} $i ${START_DATE} Elev: $7°" "${NOAA_OUTPUT}/image/${FOLDER_DATE}/${3}-$i.jpg"
/usr/local/bin/wxtoimg -o -m "${NOAA_HOME}/map/${3}-map.png" -e "$i" "${RAMFS_AUDIO}/audio/${3}.wav" "${NOAA_OUTPUT}/images/${3}-$i.jpg"
/usr/bin/convert -quality 90 -format jpg "${NOAA_OUTPUT}/images/${3}-$i.jpg" -undercolor black -fill yellow -pointsize 18 -annotate +20+20 "${1} $i ${START_DATE} Elev: $7°" "${NOAA_OUTPUT}/images/${3}-$i.jpg"
/usr/bin/convert -thumbnail 300 "${NOAA_OUTPUT}/images/${3}-$i.jpg" "${NOAA_OUTPUT}/images/thumb/${3}-$i.jpg"
done

rm "${NOAA_HOME}/map/${3}-map.png"

if [ "${SUN_ELEV}" -gt "${SUN_MIN_ELEV}" ]; then
sqlite3 /home/pi/raspberry-noaa/panel.db "insert into decoded_passes (pass_start, file_path, daylight_pass, is_noaa) values ($5,\"$3\", 1,1);"
else
sqlite3 /home/pi/raspberry-noaa/panel.db "insert into decoded_passes (pass_start, file_path, daylight_pass, is_noaa) values ($5,\"$3\", 0,1);"
fi

pass_id=$(sqlite3 /home/pi/raspberry-noaa/panel.db "select id from decoded_passes order by id desc limit 1;")

if [ -n "$CONSUMER_KEY" ]; then
log "Posting to Twitter" "INFO"
if [ "${SUN_ELEV}" -gt "${SUN_MIN_ELEV}" ]; then
python3 "${NOAA_HOME}/post.py" "$1 ${START_DATE}" "$7" "${NOAA_OUTPUT}/image/${FOLDER_DATE}/$3-MCIR-precip.jpg" "${NOAA_OUTPUT}/image/${FOLDER_DATE}/$3-MSA-precip.jpg" "${NOAA_OUTPUT}/image/${FOLDER_DATE}/$3-HVC-precip.jpg" "${NOAA_OUTPUT}/image/${FOLDER_DATE}/$3-HVCT-precip.jpg"
python3 "${NOAA_HOME}/post.py" "$1 ${START_DATE} Mas imagenes: https://weather.reyni.co/detail.php?id=$pass_id" "$7" "${NOAA_OUTPUT}/images/$3-MCIR-precip.jpg" "${NOAA_OUTPUT}/images/$3-MSA-precip.jpg" "${NOAA_OUTPUT}/images/$3-HVC-precip.jpg" "${NOAA_OUTPUT}/images/$3-HVCT-precip.jpg"
else
python3 "${NOAA_HOME}/post.py" "$1 ${START_DATE}" "$7" "${NOAA_OUTPUT}/image/${FOLDER_DATE}/$3-MCIR-precip.jpg" "${NOAA_OUTPUT}/image/${FOLDER_DATE}/$3-MCIR.jpg"
python3 "${NOAA_HOME}/post.py" "$1 ${START_DATE} Mas imagenes: https://weather.reyni.co/detail.php?id=$pass_id" "$7" "${NOAA_OUTPUT}/images/$3-MCIR-precip.jpg" "${NOAA_OUTPUT}/images/$3-MCIR.jpg"
fi
fi

sqlite3 /home/pi/raspberry-noaa/panel.db "update predict_passes set is_active = 0 where (predict_passes.pass_start) in (select predict_passes.pass_start from predict_passes inner join decoded_passes on predict_passes.pass_start = decoded_passes.pass_start where decoded_passes.id = $pass_id);"

if [ "$DELETE_AUDIO" = true ]; then
log "Deleting audio files" "INFO"
rm "${RAMFS_AUDIO}/audio/${3}.wav"
rm "${RAMFS_AUDIO}/audio/${3}.wav"
else
log "Moving audio files out of the SD card" "INFO"
mv "${RAMFS_AUDIO}/audio/${3}.wav" "${NOAA_OUTPUT}/audio/${3}.wav"
log "Moving audio files out to the SD card" "INFO"
mv "${RAMFS_AUDIO}/audio/${3}.wav" "${NOAA_OUTPUT}/audio/${3}.wav"
fi

+ 20
- 13
receive_meteor.sh View File

@@ -25,8 +25,8 @@ SUN_ELEV=$(python3 "$NOAA_HOME"/sun.py "$PASS_START")

if pgrep "rtl_fm" > /dev/null
then
log "There is an already running rtl_fm instance but I dont care for now, I prefer this pass" "INFO"
pkill -9 -f rtl_fm
log "There is an already running rtl_fm instance but I dont care for now, I prefer this pass" "INFO"
pkill -9 -f rtl_fm
fi

# $1 = Satellite Name
@@ -40,14 +40,15 @@ fi
log "Starting rtl_fm record" "INFO"
timeout "${6}" /usr/local/bin/rtl_fm ${BIAS_TEE} -M raw -f "${2}"M -s 288k -g 48 | sox -t raw -r 288k -c 2 -b 16 -e s - -t wav "${RAMFS_AUDIO}/audio/${3}.wav" rate 96k

log "Normalization in progress" "INFO"
sox "${RAMFS_AUDIO}/audio/${3}.wav" "${METEOR_OUTPUT}/${3}.wav" gain -n

log "Demodulation in progress (QPSK)" "INFO"
meteor_demod -B -o "${METEOR_OUTPUT}/${3}.qpsk" "${METEOR_OUTPUT}/${3}.wav"
meteor_demod -B -o "${METEOR_OUTPUT}/${3}.qpsk" "${RAMFS_AUDIO}/audio/${3}.wav"

if [ "$DELETE_AUDIO" = true ]; then
log "Deleting audio files" "INFO"
rm "${RAMFS_AUDIO}/audio/${3}.wav"
else
log "Moving audio files out to the SD card" "INFO"
mv "${RAMFS_AUDIO}/audio/${3}.wav" "${NOAA_OUTPUT}/audio/${3}.wav"
rm "${METEOR_OUTPUT}/audio/${3}.wav"
rm "${RAMFS_AUDIO}/audio/${3}.wav"
fi
@@ -61,23 +62,29 @@ if [ -f "${METEOR_OUTPUT}/${3}.dec" ]; then

if [ "${SUN_ELEV}" -lt "${SUN_MIN_ELEV}" ]; then
log "I got a successful ${3}.dec file. Decoding APID 68" "INFO"
medet_arm "${METEOR_OUTPUT}/${3}.dec" "${NOAA_OUTPUT}/image/${FOLDER_DATE}/${3}-122" -r 68 -g 68 -b 68 -d
/usr/bin/convert -negate $FLIP "${NOAA_OUTPUT}/image/${FOLDER_DATE}/${3}-122.bmp" "${NOAA_OUTPUT}/image/${FOLDER_DATE}/${3}-122.bmp"

medet_arm "${METEOR_OUTPUT}/${3}.dec" "${NOAA_OUTPUT}/images/${3}-122" -r 68 -g 68 -b 68 -d
/usr/bin/convert $FLIP -negate "${NOAA_OUTPUT}/images/${3}-122.bmp" "${NOAA_OUTPUT}/images/${3}-122.bmp"
else
log "I got a successful ${3}.dec file. Creating false color image" "INFO"
medet_arm "${METEOR_OUTPUT}/${3}.dec" "${NOAA_OUTPUT}/image/${FOLDER_DATE}/${3}-122" -r 65 -g 65 -b 64 -d
medet_arm "${METEOR_OUTPUT}/${3}.dec" "${NOAA_OUTPUT}/images/${3}-122" -r 65 -g 65 -b 64 -d
fi

log "Rectifying image to adjust aspect ratio" "INFO"
python3 "${NOAA_HOME}/rectify.py" "${NOAA_OUTPUT}/image/${FOLDER_DATE}/${3}-122.bmp"
convert "${NOAA_OUTPUT}/image/${FOLDER_DATE}/${3}-122-rectified.jpg" -channel rgb -normalize -channel rgb -normalize -undercolor black -fill yellow -pointsize 60 -annotate +20+60 "${1} ${START_DATE} Elev: $7°" "${NOAA_OUTPUT}/image/${FOLDER_DATE}/${3}-122-rectified.jpg"
python3 "${NOAA_HOME}/rectify.py" "${NOAA_OUTPUT}/images/${3}-122.bmp"
convert "${NOAA_OUTPUT}/images/${3}-122-rectified.jpg" -channel rgb -normalize -undercolor black -fill yellow -pointsize 60 -annotate +20+60 "${1} ${START_DATE} Elev: $7°" "${NOAA_OUTPUT}/images/${3}-122-rectified.jpg"
/usr/bin/convert -thumbnail 300 "${NOAA_OUTPUT}/images/${3}-122-rectified.jpg" "${NOAA_OUTPUT}/images/thumb/${3}-122-rectified.jpg"
rm "${NOAA_OUTPUT}/images/${3}-122.bmp"
rm "${METEOR_OUTPUT}/${3}.bmp"
rm "${METEOR_OUTPUT}/${3}-122.bmp"
rm "${METEOR_OUTPUT}/${3}.dec"

sqlite3 /home/pi/raspberry-noaa/panel.db "insert into decoded_passes (pass_start, file_path, daylight_pass, is_noaa) values ($5,\"$3\", 1,0);"
pass_id=$(sqlite3 /home/pi/raspberry-noaa/panel.db "select id from decoded_passes order by id desc limit 1;")
if [ -n "$CONSUMER_KEY" ]; then
log "Posting to Twitter" "INFO"
python3 "${NOAA_HOME}/post.py" "$1 EXPERIMENTAL ${START_DATE} Resolución completa: http://weather.reyni.co/image/${FOLDER_DATE}/${3}-122-rectified.jpg" "$7" "${NOAA_OUTPUT}/image/${FOLDER_DATE}/${3}-122-rectified.jpg"
python3 "${NOAA_HOME}/post.py" "$1 ${START_DATE} Resolución completa: https://weather.reyni.co/detail.php?id=$pass_id" "$7" "${NOAA_OUTPUT}/images/${3}-122-rectified.jpg"
fi
sqlite3 /home/pi/raspberry-noaa/panel.db "update predict_passes set is_active = 0 where (predict_passes.pass_start) in (select predict_passes.pass_start from predict_passes inner join decoded_passes on predict_passes.pass_start = decoded_passes.pass_start where decoded_passes.id = $pass_id);"
else
log "Decoding failed, either a bad pass/low SNR or a software problem" "ERROR"
fi

+ 1
- 1
rectify.py View File

@@ -8,7 +8,7 @@ from math import atan,sin,cos,sqrt,tan,acos,ceil
from PIL import Image

EARTH_RADIUS = 6371.0
SAT_HEIGHT = 822.5
SAT_HEIGHT = 830.0
SAT_ORBIT_RADIUS = EARTH_RADIUS + SAT_HEIGHT
SWATH_KM = 2800.0
THETA_C = SWATH_KM / EARTH_RADIUS


+ 1
- 0
schedule_meteor.sh View File

@@ -25,6 +25,7 @@ while [ "$(date --date="@${var2}" +%D)" = "$(date +%D)" ]; do
echo "${SATNAME}" "${OUTDATE}" "$MAXELEV"
echo "${NOAA_HOME}/receive_meteor.sh \"${1}\" $2 ${SATNAME}${OUTDATE} "${NOAA_HOME}"/predict/weather.tle \
${var1} ${TIMER} ${MAXELEV}" | at "$(date --date="TZ=\"UTC\" ${START_TIME}" +"%H:%M %D")"
sqlite3 /home/pi/raspberry-noaa/panel.db "insert or replace into predict_passes (sat_name,pass_start,pass_end,max_elev,is_active) values (\"$SATNAME\",$var1,$var2,$MAXELEV,1);"
fi
NEXTPREDICT=$(expr "${var2}" + 60)
PREDICTION_START=$(/usr/bin/predict -t "${NOAA_HOME}"/predict/weather.tle -p "${1}" "${NEXTPREDICT}" | head -1)


+ 1
- 0
schedule_sat.sh View File

@@ -31,6 +31,7 @@ while [ "$(date --date="@${var2}" +%D)" = "$(date +%D)" ]; do
echo "${SATNAME}" "${OUTDATE}" "$MAXELEV"
echo "${NOAA_HOME}/receive.sh \"${1}\" $2 ${SATNAME}${OUTDATE} "${NOAA_HOME}"/predict/weather.tle \
${var1} ${TIMER} ${MAXELEV}" | at "$(date --date="TZ=\"UTC\" ${START_TIME}" +"%H:%M %D")"
sqlite3 /home/pi/raspberry-noaa/panel.db "insert or replace into predict_passes (sat_name,pass_start,pass_end,max_elev,is_active) values (\"$SATNAME\",$var1,$var2,$MAXELEV, 1);"
fi
NEXTPREDICT=$(expr "${var2}" + 60)
PREDICTION_START=$(/usr/bin/predict -t "${NOAA_HOME}"/predict/weather.tle -p "${1}" "${NEXTPREDICT}" | head -1)


+ 2
- 2
sun.py View File

@@ -2,8 +2,8 @@
import ephem
import time
import sys
timezone = change_tz
date = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(int(sys.argv[1])+(timezone*60*60)))
timezone = change_tz + time.localtime().tm_isdst
date = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(int(sys.argv[1])-(timezone*60*60)))

obs=ephem.Observer()
obs.lat='change_latitude'


+ 9
- 1
templates/nginx.cfg View File

@@ -1,7 +1,7 @@
server {
listen 80 default_server;
root /var/www/wx;
index index.html index.htm index.nginx-debian.html;
index index.php index.html index.htm index.nginx-debian.html;
autoindex on;

server_name wx.home;
@@ -9,4 +9,12 @@ server {
location / {
try_files $uri $uri/ =404;
}

location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
}

# Rewrite the old path yyyy/mm/dd/ to /images/
rewrite "^/image/\d{4}/\d{2}/\d{2}/(.+)$" /images/$1 permanent;
}

+ 7
- 0
templates/webpanel/Config.php View File

@@ -0,0 +1,7 @@
<?php
return (object) array(
'base_url' => '/images/',
'img_per_page' => 12,
'lang' => 'es'
);
?>

+ 6
- 0
templates/webpanel/Controller/C_predict.php View File

@@ -0,0 +1,6 @@
<?php
require('Model/Conn.php');
$con = new Conn();
$passes = $con->getPasses();
require('Views/V_viewPasses.php');
?>

+ 8
- 0
templates/webpanel/Controller/C_showDetail.php View File

@@ -0,0 +1,8 @@
<?php
require('Model/Conn.php');
$con = new Conn();
if ($pass_id < 1) $pass_id = 1;
$enhacements = $con->getEnhacements($pass_id);
$path = $con->getPath($pass_id);
require('Views/V_viewDetail.php');
?>

+ 6
- 0
templates/webpanel/Controller/C_showLastImage.php View File

@@ -0,0 +1,6 @@
<?php
require('Model/Conn.php');
$con = new Conn();
$images = $con->getLastImage();
require('Views/V_viewLastImage.php');
?>

+ 11
- 0
templates/webpanel/Controller/C_showLastImages.php View File

@@ -0,0 +1,11 @@
<?php
require('Model/Conn.php');
$con = new Conn();
if ($page < 1) $page = 1;
$img_per_page = $configs->img_per_page;
$page_count = $con->totalPages($img_per_page);
if ($page < 1) $page = 1;
if ($page > $page_count) $page = $page_count;
$images = $con->getImages($page, $img_per_page);
require('Views/V_viewLastImages.php');
?>

+ 0
- 0
templates/webpanel/Controller/index.html View File


+ 74
- 0
templates/webpanel/Model/Conn.php View File

@@ -0,0 +1,74 @@
<?php
class Conn {
private $con;
public function __construct() {
$this->con = new SQLite3("/home/pi/raspberry-noaa/panel.db");
}
public function getPasses() {
$today = strtotime(date('Y-m-d', time()));
$query = $this->con->query("SELECT sat_name, is_active,
pass_start, pass_end,
max_elev FROM predict_passes
WHERE (pass_start > $today) ORDER BY
pass_start ASC;");
$passes = [];
$i = 0;
while($row = $query->fetchArray()){
$passes[$i] = $row;
$i++;
}
return $passes;
}
public function totalPages($img_per_page) {
$total_pages = $this->con->querySingle("SELECT count() from decoded_passes;");
return ceil($total_pages/$img_per_page);
}
public function getImages($page, $img_per_page) {
$query = $this->con->prepare("SELECT decoded_passes.id, predict_passes.pass_start,
file_path, is_noaa, predict_passes.sat_name, predict_passes.max_elev
FROM decoded_passes INNER JOIN predict_passes
ON predict_passes.pass_start = decoded_passes.pass_start
ORDER BY decoded_passes.pass_start DESC LIMIT ? OFFSET ?;");
$query->bindValue(1, $img_per_page);
$query->bindValue(2, $img_per_page * ($page-1));
$result = $query->execute();
$images = [];
$i = 0;
while($row = $result->fetchArray()){
$images[$i] = $row;
$i++;
}
return $images;
}
public function getEnhacements($id) {
$query = $this->con->prepare('SELECT daylight_pass, is_noaa
FROM decoded_passes WHERE id = ?;');
$query->bindValue(1, $id);
$result = $query->execute();
$pass = $result->fetchArray();
if ($pass['is_noaa'] == 0) {
$enhacements = ['-122-rectified.jpg'];
} else {
if ($pass['daylight_pass'] == 1) {
$enhacements = ['-ZA.jpg','-MCIR.jpg','-MCIR-precip.jpg','-MSA.jpg','-MSA-precip.jpg','-HVC.jpg','-HVC-precip.jpg','-HVCT.jpg','-HVCT-precip.jpg'];
} else {
$enhacements = ['-ZA.jpg','-MCIR.jpg','-MCIR-precip.jpg'];
}
}
return $enhacements;
}
public function getPath($id) {
$query = $this->con->prepare('SELECT file_path FROM decoded_passes
WHERE id = ?;');
$query->bindValue(1, $id);
$result = $query->execute();
$image = $result->fetchArray();
return $image['file_path'];
}
}
?>

+ 0
- 0
templates/webpanel/Model/index.html View File


+ 23
- 0
templates/webpanel/Views/V_viewDetail.php View File

@@ -0,0 +1,23 @@
<div style="overflow-x:auto;">
<table id="passes">
<?php
$row_count=0;
$col_count=0;
$baseurl = $configs->base_url;
foreach ($enhacements as $enhacement) {
if($row_count%3==0) {
echo "<tr>";
$col_count=1;
}
echo "<td><div id =\"satimgdiv\"><a href=". $baseurl . $path . $enhacement ."><img id=\"satimg\" src=". $baseurl . "thumb/" . $path . $enhacement ."></img></a></div>";
if($col_count==3) {
echo "</tr>";
}
$row_count++;
$col_count++;
}
?>
</table>
</div>
</body>
</html>

+ 24
- 0
templates/webpanel/Views/V_viewLastImage.php View File

@@ -0,0 +1,24 @@
<table id="passes" class="img-grid">
<?php
$row_count=0;
$col_count=0;
$baseurl = $configs->base_url;
foreach ($images as $image) {
if($row_count%3==0) {
echo "<tr>";
$col_count=1;
}
echo "<td><div id =\"satimgdiv\"><a href=". $baseurl . $image['file_path'] ."><img id=\"satimg\" src=". $baseurl . "thumb/" . $image['file_path'] ."></img></a></div>";
echo "<ul><li>". $image['sat_name'] ."</li>";
echo "<li>". date('d/m/Y H:i:s', $image['pass_start']) ."</li></ul></td>";
if($col_count==3) {
echo "</tr>";
}
$row_count++;
$col_count++;
}
?>
</table>
</body>
</html>

+ 42
- 0
templates/webpanel/Views/V_viewLastImages.php View File

@@ -0,0 +1,42 @@
<div style="overflow-x:auto;">
<table id="passes" class="img-grid">
<?php
if ($page > 1) {
echo "<tr><th><a href=\"?page=" . ($page-1) . "\">" . $lang['prev'] . "</a></th>";
} else {
echo "<tr><th></th>";
}
echo "<th>" . $lang['page'] . " $page " . $lang['of'] . " $page_count</th>";
if ($page < $page_count) {
echo "<th><a href=\"?page=" . ($page+1) . "\">" . $lang['next'] . "</a></th></tr>";
} else {
echo "<th></th></tr>";
}
$row_count=0;
$col_count=0;
$baseurl = $configs->base_url;
foreach ($images as $image) {
if($row_count%3==0) {
echo "<tr>";
$col_count=1;
}
if ($image['is_noaa'] == true) {
$ending = "-MCIR.jpg";
} else {
$ending = "-122-rectified.jpg";
}
echo "<td><div id =\"satimgdiv\"><a href=". "detail.php?id=" . $image['id'] ."><img id=\"satimg\" src=". $baseurl . "thumb/" . $image['file_path'] . $ending ."></img></a></div>";
echo "<ul><li>". $image['sat_name'] ."</li>";
echo "<li> " . $lang['elev'] . ": ". $image['max_elev'] ."°</li>";
echo "<li>". date('d/m/Y H:i:s', $image['pass_start']) ."</li></ul></td>";
if($col_count==3) {
echo "</tr>";
}
$row_count++;
$col_count++;
}
?>
</table>
</div>
</body>
</html>

+ 24
- 0
templates/webpanel/Views/V_viewPasses.php View File

@@ -0,0 +1,24 @@
<div style="overflow-x:auto;">
<table id="passes">
<tr>
<th><?php echo $lang['satellite']; ?></th>
<th><?php echo $lang['pass_start']; ?></th>
<th><?php echo $lang['pass_end']; ?></th>
<th><?php echo $lang['max_elev']; ?></th>
</tr>
<?php
foreach ($passes as $pass) {
if ($pass['is_active'] == false) {
echo "<tr class='inactive'>";
} else {
echo "<tr>";
}
echo "<td>". $pass['sat_name'] ."</td>";
echo "<td>". date('H:i:s', $pass['pass_start']) ."</td>";
echo "<td>". date('H:i:s', $pass['pass_end']) ."</td>";
echo "<td>". $pass['max_elev'] ."</td>";
echo "</tr>";
}
?>
</table>
</div>

+ 0
- 0
templates/webpanel/Views/index.html View File


+ 7
- 0
templates/webpanel/detail.php View File

@@ -0,0 +1,7 @@
<?php
$configs = include('Config.php');
include_once('header.php');
$pass_id = isset($_GET['id']) ? intval($_GET['id']) : 1;
require('Controller/C_showDetail.php');
include_once("footer.php")
?>

+ 6
- 0
templates/webpanel/footer.php View File

@@ -0,0 +1,6 @@
</div>
<footer>
<a href="https://github.com/reynico/raspberry-noaa"><img class="img-footer" src="logo-small.png"></a>
</footer>
</body>
</html>

+ 27
- 0
templates/webpanel/header.php View File

@@ -0,0 +1,27 @@
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
date_default_timezone_set('America/Argentina/Buenos_Aires');
$page = basename($_SERVER['PHP_SELF']);
$configs = include('Config.php');
$lang = $configs->lang;
include_once('language/' . $lang . '.php');
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" type="text/css" href="style.css">
<title><?= isset($PageTitle) ? $PageTitle : "Raspberry NOAA"?></title>
</head>
<body>
<div class="topnav">
<a class="<?php if($page == 'passes.php'){ echo ' active"';}?>" href="passes.php"><?php echo $lang['passes']; ?></a>
<a class="<?php if($page == 'index.php' || $page == 'detail.php'){ echo ' active"';}?>" href="index.php"><?php echo $lang['images']; ?></a>
</div>
<div class="container">



+ 7
- 0
templates/webpanel/index.php View File

@@ -0,0 +1,7 @@
<?php
include_once('header.php');
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
require('Controller/C_showLastImages.php');
include_once("footer.php")
?>

+ 15
- 0
templates/webpanel/language/en.php View File

@@ -0,0 +1,15 @@
<?php
$lang = array(
"passes" => "Passes",
"satellite" => "Satellite",
"images" => "Images",
"pass_start" => "Pass start",
"pass_end" => "Pass end",
"max_elev" => "Max elevation",
"elev" => "Elevation",
"page" => "Page",
"of" => "of",
"prev" => "Prev",
"next" => "Next",
);
?>

+ 15
- 0
templates/webpanel/language/es.php View File

@@ -0,0 +1,15 @@
<?php
$lang = array(
"passes" => "Pasadas",
"satellite" => "Satélite",
"images" => "Imagenes",
"pass_start" => "Inicio",
"pass_end" => "Fin",
"max_elev" => "Elevación",
"elev" => "Elevación",
"page" => "Página",
"of" => "de",
"prev" => "Anterior",
"next" => "Siguiente",
);
?>

BIN
templates/webpanel/logo-small.png View File

Before After
Width: 358  |  Height: 70  |  Size: 16 KiB

+ 5
- 0
templates/webpanel/passes.php View File

@@ -0,0 +1,5 @@
<?php
include_once('header.php');
require('Controller/C_predict.php');
include_once("footer.php")
?>

+ 99
- 0
templates/webpanel/style.css View File

@@ -0,0 +1,99 @@
body {
margin: 0;
font-family: Arial, Helvetica, sans-serif;
}

.container {
margin: 20px auto;
max-width: 800px;
}

.topnav {
overflow: hidden;
background-color: #333;
}

.topnav a {
float: left;
color: #f2f2f2;
text-align: center;
padding: 14px 16px;
text-decoration: none;
font-size: 17px;
}

.topnav a:hover {
background-color: #ddd;
color: black;
}

.topnav a.active {
background-color: #4CAF50;
color: white;
}

#passes {
font-family: "Trebuchet MS", Arial, Helvetica, sans-serif;
border-collapse: collapse;
max-width: 500px;
width: 100%;
margin: auto;
}

#passes.img-grid {
max-width: 700px;
}

#passes td,
#passes th {
border: 1px solid #ddd;
padding: 8px;
}

#passes tr:nth-child(even) {
background-color: #f2f2f2;
}


/* #passes tr:hover {background-color: #ddd;} */

#passes th {
padding-top: 12px;
padding-bottom: 12px;
background-color: #4CAF50;
text-align: center;
color: white;
}

#passes tr.inactive {
color: lightgray;
}

#satimg {
max-width: 200px;
max-height: 200px;
width: 100%;
}

#satimgdiv {
width: 100%;
height: 100%;
max-width: 200px;
background-color: antiquewhite;
/* margin: 10px; */
display: inline-block;
vertical-align: middle;
text-align: center;
}

footer {
/* position: absolute; */
margin: 20px;
bottom: 0;
max-width: 100%;
text-align: center;
}

img.img-footer {
max-width: 100%;
}

+ 14
- 0
templates/webpanel_schema.sql View File

@@ -0,0 +1,14 @@
create table predict_passes(
sat_name text not null,
pass_start timestamp primary key default (strftime('%s', 'now')) not null,
pass_end timestamp default (strftime('%s', 'now')) not null,
max_elev int not null,
is_active boolean);


CREATE TABLE decoded_passes(
id integer primary key autoincrement,
pass_start integer,
file_path text not null,
daylight_pass boolean, is_noaa boolean,
foreign key(pass_start) references passes(pass_start));

Loading…
Cancel
Save