Implemented Log packets for the last protocol changes

master
Sven Steudte 2018-01-11 13:31:47 +01:00
rodzic c745ef50c9
commit 955c33a2f8
8 zmienionych plików z 65 dodań i 258 usunięć

Wyświetl plik

@ -1,7 +1,6 @@
#!/usr/bin/python3
import serial,re,io
import base91
import sys
import argparse
import telnetlib
@ -63,7 +62,8 @@ sqlite.cursor().execute("""
si4464_temp INTEGER,
sys_time INTEGER,
sys_error INTEGER
sys_error INTEGER,
PRIMARY KEY (call,reset,id,time)
)
""")
sqlite.cursor().execute("""
@ -104,20 +104,18 @@ def received_data(data):
if pos: # Position packet (with comment and telementry)
posi = pos.group(3)
comm = pos.group(4)
tel = pos.group(5)
position.insert_position(sqlite, call, posi, comm, tel)
position.insert_position(sqlite, call, comm, 'pos')
elif dat: # Data packet
typ = dat.group(3)
data = base91.decode(dat.group(4)) # Decode Base91
data = dat.group(4)
if typ is 'I': # Image packet
image.insert_image(sqlite, rxer, call, data)
elif typ is 'L': # Log packet
position.insert_log(sqlite, call, data)
position.insert_position(sqlite, call, data, 'log')
if args.device == 'I': # Source APRS-IS

Wyświetl plik

@ -1,24 +1,9 @@
<?php
class Telemetry {
/*const TYPE_INT = 0; // Integer
const TYPE_STR = 1; // String
const TYPE_HTML = 2; // HTML
const LOC_INT = 0; // Internal
const LOC_EXT = 1; // External
const LOC_INT1 = 0; // Internal 1
const LOC_EXT1 = 1; // External 1
const LOC_EXT2 = 2; // External 2
const COL_GREEN = "#008000";
const COL_ORANGE = "#CC6600";
const COL_RED = "#FF0000";*/
function __construct($sqlResult) {
$this->reset = $sqlResult['reset'];
$this->id = $sqlResult['id'];
$this->org = $sqlResult['org'];
$this->rxtime = $sqlResult['rxtime'];
@ -68,101 +53,6 @@ class Telemetry {
$this->err_bme280_e2 = ($this->sys_error >> 10) & 0x1;
}
/*function getOV9655Error($type) {
$error = ($this->sys_error >> 4) & 0x3;
if($type == self::TYPE_INT)
return $error;
switch($error) {
case 0: return $this->colorize($type, self::COL_GREEN, "OK");
case 1: return $this->colorize($type, self::COL_RED, "I2C Error - Camera not found");
case 2: return $this->colorize($type, self::COL_RED, "DMA abort - last buffer segment");
case 3: return $this->colorize($type, self::COL_RED, "DMA FIFO error");
case 4: return $this->colorize($type, self::COL_RED, "DMA stream transfer error");
case 5: return $this->colorize($type, self::COL_RED, "DMA direct mode error");
}
}
function getGPSStatus($type) {
if($type == self::TYPE_INT)
return $this->gps_lock;
switch($this->gps_lock) {
case 0: return $this->colorize($type, self::COL_GREEN, "GPS locked");
case 1: return $this->colorize($type, self::COL_GREEN, "GPS locked - kept switched on");
case 2: return $this->colorize($type, self::COL_RED, "GPS loss");
case 3: return $this->colorize($type, self::COL_ORANGE, "Low Batt before switched on");
case 4: return $this->colorize($type, self::COL_ORANGE, "Low Batt while switched on");
case 5: return $this->colorize($type, self::COL_GREEN, "Data from memory");
case 6: return $this->colorize($type, self::COL_RED, "GPS communication error");
}
}
function getEVA7MError($type) {
$error = ($this->sys_error >> 2) & 0x1;
if($type == self::TYPE_INT)
return $error;
switch($error) {
case 0: return $this->colorize($type, self::COL_GREEN, "OK");
case 1: return $this->colorize($type, self::COL_RED, "Fail");
}
}
function getI2cError($loc, $type) {
$error = $loc == self::LOC_INT ? $this->sys_error & 0x1 : ($this->sys_error >> 1) & 0x1;
if($type == self::TYPE_INT)
return $error;
switch($error) {
case 0: return $this->colorize($type, self::COL_GREEN, "OK");
case 1: return $this->colorize($type, self::COL_RED, "Fail");
}
}
function getPAC1720Error($type) {
$error = ($this->sys_error >> 3) & 0x1;
if($type == self::TYPE_INT)
return $error;
switch($error) {
case 0: return $this->colorize($type, self::COL_GREEN, "OK");
case 1: return $this->colorize($type, self::COL_RED, "Fail");
}
}
function getBME280Error($type, $loc) {
switch($loc) {
case self::LOC_INT1: $error = ($this->sys_error >> 7) & 0x1; break;
case self::LOC_EXT1: $error = ($this->sys_error >> 8) & 0x1; break;
case self::LOC_EXT2: $error = ($this->sys_error >> 9) & 0x1; break;
}
if($type == self::TYPE_INT)
return $error;
switch($error) {
case 0: return $this->colorize($type, self::COL_GREEN, "OK");
case 1: return $this->colorize($type, self::COL_RED, "Fail");
}
}
private function colorize($type, $color, $str) {
if($type == self::TYPE_HTML)
return "<font color=\"$color\">$str</font>";
elseif($type == self::TYPE_STR)
return $str;
}*/
}
?>

Wyświetl plik

@ -84,7 +84,20 @@ class Tracker {
if($from - $to > 64281600)
$from = $from + 64281600; // Max. 744 days (2 non leap years + 14 weeks)
$stmt = Database::getInstance()->prepare("SELECT * FROM position WHERE :from <= rxtime AND rxtime <= :to AND call = :call ORDER BY rxtime ASC");
$stmt = Database::getInstance()->prepare("
SELECT *
FROM position
WHERE (
:from <= rxtime
AND rxtime <= :to
AND org = 'pos'
) OR (
:from <= gps_time
AND gps_time <= :to
AND org = 'log'
) AND call = :call
ORDER BY rxtime ASC
");
$stmt->bindValue(':call', $this->call, SQLITE3_TEXT);
$stmt->bindValue(':from', $from, SQLITE3_INTEGER);
$stmt->bindValue(':to', $to, SQLITE3_INTEGER);
@ -131,3 +144,4 @@ class Tracker {
}
}
?>

Wyświetl plik

@ -187,11 +187,10 @@ function loadRecentData() {
$('#act_pos').text(time_format(json['lastActivity']['pos']));
$('#act_img').text(time_format(json['lastActivity']['img']));
// TODO: Remove old entries
// Update charts if there is new data or at a timeout of 300 seconds
if(tel.length > 0 || json['time']-lastChartUpdate > 300) {
// Add new rows
var time = json['time'];
xAxis.minValue = new Date((time-<?=$range?>)*1000),
xAxis.maxValue = new Date(time*1000),
@ -210,7 +209,7 @@ function loadRecentData() {
dataLight.addRow([null,null]);
}
var time = new Date(data['rxtime']*1000);
var time = new Date(data['org'] == 'pos' ? data['rxtime']*1000 : data['gps_time']*1000);
dataBattery.addRow([time, data['adc_vbat'], data['pac_vbat'], data['pac_pbat']/10]);
dataSolar.addRow([time, data['adc_vsol'], data['pac_vsol'], data['pac_psol']/10]);
dataTemp.addRow([time, data['sen_i1_temp']/100, data['sen_e1_temp']/100, data['sen_e2_temp']/100, data['stm32_temp']/100, data['si4464_temp']/100]);
@ -220,6 +219,19 @@ function loadRecentData() {
last = data['rxtime'];
});
// Remove old rows
var removeTime = new Date((time-<?=$range?>)*1000);
for(var c=0; c<dataBattery.getNumberOfColumns(); c++) {
if(dataBattery.getValue(c, 0) < removeTime) {
dataBattery.removeRow(c);
dataSolar.removeRow(c);
dataTemp.removeRow(c);
dataGPS.removeRow(c);
dataLight.removeRow(c);
}
}
// Update charts
batteryChart.draw(dataBattery, voltageOptions);
solarChart.draw(dataSolar, voltageOptions);
tempChart.draw(dataTemp, tempOptions);

Wyświetl plik

@ -2,11 +2,11 @@ import binascii
import urllib.request
import urllib.error
from datetime import datetime
from position import decode_position
from subprocess import *
import time
import threading
from shutil import copyfile
import base91
def decode_callsign(code):
callsign = ''
@ -59,9 +59,10 @@ def imgproc():
time.sleep(1)
w = time.time()
def insert_image(sqlite, receiver, call, data):
def insert_image(sqlite, receiver, call, data_b91):
global imageProcessor,imageData,w
data = base91.decode(data_b91)
if len(data) != 174:
return # APRS message has invalid type or length (or both)
@ -106,7 +107,7 @@ def insert_image(sqlite, receiver, call, data):
_id = 0
# Debug
print('Received image packet %d Packet %d ServerID %d' % (imageID, packetID, _id))
print('Received image packet Call=%s ImageID=%d PacketID=%d ServerID=%d' % (call, imageID, packetID, _id))
# Insert into database
cur.execute("""

Wyświetl plik

@ -3,72 +3,7 @@ import sqlite3
import base91
import struct
def insert_log(sqlite, call, data):
if len(data)/10*10 != len(data): # Is not multiple of 8 bytes
return # APRS message sampled too short
for i in range(int(len(data)/10)):
tim = (data[i*10+3] << 24) | (data[i*10+2] << 16) | (data[i*10+1] << 8) | data[i*10+0]
lat = (data[i*10+5] << 8) | data[i*10+4]
lon = (data[i*10+7] << 8) | data[i*10+6]
alt = (data[i*10+9] << 8) | data[i*10+8]
lat = float(lat * 180) / 65536 - 90
lon = float(lon * 360) / 65536 - 180
tim_stringified = datetime.utcfromtimestamp(tim).strftime("%Y-%m-%d %H:%M:%S")
try:
sqlite.cursor().execute("INSERT OR FAIL INTO position (call,time,org,lat,lon,alt,isnew) VALUES (?,?,'log',?,?,?,1)", (call, tim, lat, lon, alt))
print("Decoded log from %s time %s => lat=%06.3f lon=%07.3f alt=%05d" % (call, tim_stringified, lat, lon, alt))
except sqlite3.IntegrityError:
print("Decoded log from %s time %s => lat=%06.3f lon=%07.3f alt=%05d already in db" % (call, tim_stringified, lat, lon, alt))
sqlite.commit()
def decode_position(posi, tel):
# Decode latitude
y3 = ord(posi[1]) - 33
y2 = ord(posi[2]) - 33
y1 = ord(posi[3]) - 33
y0 = ord(posi[4]) - 33
ye = y0 + y1*91 + y2*8281 + y3*753571
y = -ye / 380926.0 + 90
# Decode longitude
x3 = ord(posi[5]) - 33
x2 = ord(posi[6]) - 33
x1 = ord(posi[7]) - 33
x0 = ord(posi[8]) - 33
xe = x0 + x1*91 + x2*8281 + x3*753571
x = xe / 190463.0 - 180
# Decode altitude
z1 = ord(posi[10]) - 33
z0 = ord(posi[11]) - 33
ze = z0 + z1*91
z = pow(1.002, ze) / 3.281
# Time
timd = datetime.now(timezone.utc)
# Decode GPS Fix Type
isnew = ((ord(posi[12])-33) >> 5) & 0x1
# Decode telemetry
teld = [0]*6
if tel != None:
for i in range(6):
t1 = ord(tel[i*2+0]) - 33
t0 = ord(tel[i*2+1]) - 33
teld.append(t0 + t1*91)
return timd,x,y,z,teld,isnew
def insert_position(sqlite, call, posi, comm, tel): #sqlite, call, data
# Decode position
timd,x,y,z,teld,isnew = decode_position(posi, tel)
def insert_position(sqlite, call, comm, typ):
# Decode comment
data = base91.decode(comm)
(adc_vsol,adc_vbat,pac_vsol,pac_vbat,pac_pbat,pac_psol,light_intensity,
@ -78,36 +13,14 @@ def insert_position(sqlite, call, posi, comm, tel): #sqlite, call, data
si4464_temp,reset,_id,gps_time,sys_time,sys_error) = struct.unpack('HHHHhhHBBBBHiiIIIhhhBBBBhhHIIII', data[:72])
# Insert
rxtime = int(datetime.now(timezone.utc).timestamp())
sqlite.cursor().execute(
"""INSERT INTO position (call,rxtime,org,adc_vsol,adc_vbat,pac_vsol,pac_vbat,pac_pbat,pac_psol,light_intensity,gps_lock,gps_sats,gps_ttff,gps_pdop,gps_alt,gps_lat,gps_lon,sen_i1_press,sen_e1_press,sen_e2_press,sen_i1_temp,sen_e1_temp,sen_e2_temp,sen_i1_hum,sen_e1_hum,sen_e2_hum,sys_error,stm32_temp,si4464_temp,reset,id,sys_time,gps_time)
VALUES (?,?,'pos',?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)""",
(call,int(timd.timestamp()), adc_vsol,adc_vbat,pac_vsol,pac_vbat,pac_pbat,pac_psol,light_intensity,gps_lock,gps_sats,gps_ttff,gps_pdop,gps_alt,gps_lat,gps_lon,sen_i1_press,sen_e1_press,sen_e2_press,sen_i1_temp,sen_e1_temp,sen_e2_temp,sen_i1_hum,sen_e1_hum,sen_e2_hum,sys_error,stm32_temp,si4464_temp,reset,_id,sys_time,gps_time)
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)""",
(call,rxtime,typ,adc_vsol,adc_vbat,pac_vsol,pac_vbat,pac_pbat,pac_psol,light_intensity,gps_lock,gps_sats,gps_ttff,gps_pdop,gps_alt,gps_lat,gps_lon,sen_i1_press,sen_e1_press,sen_e2_press,sen_i1_temp,sen_e1_temp,sen_e2_temp,sen_i1_hum,sen_e1_hum,sen_e2_hum,sys_error,stm32_temp,si4464_temp,reset,_id,sys_time,gps_time)
)
sqlite.commit()
# Debug
tim_stringified = timd.strftime("%Y-%m-%d %H:%M:%S")
print("Decoded position from %s time %s => lat=%f lon=%f alt=%d new=%d comment=%s, sequ=%d tel=[%d,%d,%d,%d,%d]"
% (call, tim_stringified, y, x, int(z), isnew, comm, teld[0], teld[1], teld[2], teld[3], teld[4], teld[5]))
print('Received %s packet packet Call=%s Reset=%d ID=%d' % (typ, call, reset, _id))

Wyświetl plik

@ -386,10 +386,10 @@ void start_user_modules(void)
config[0].frequency.hz = 144800000; // Default frequency 144.800 MHz
config[0].trigger.type = TRIG_NEW_POINT; // Transmit when tracking manager samples new tracking point
chsnprintf(config[0].aprs_conf.callsign, 16, "DL7AD"); // APRS Callsign
config[0].aprs_conf.ssid = 13; // APRS SSID
config[0].aprs_conf.ssid = 15; // APRS SSID
config[0].aprs_conf.symbol = SYM_BALLOON; // APRS Symbol
chsnprintf(config[0].aprs_conf.path, 16, "WIDE1-1"); // APRS Path
config[0].aprs_conf.preamble = 300; // APRS Preamble (300ms)
config[0].aprs_conf.preamble = 200; // APRS Preamble (200ms)
config[0].aprs_conf.tel[0] = TEL_VBAT; // APRS Telemetry parameter 1: Battery voltage
config[0].aprs_conf.tel[1] = TEL_VSOL; // APRS Telemetry parameter 2: Solar voltage
config[0].aprs_conf.tel[2] = TEL_PBAT; // APRS Telemetry parameter 3: Battery charge/discharge power
@ -398,7 +398,7 @@ void start_user_modules(void)
config[0].aprs_conf.tel_enc = TRUE; // Transmit Telemetry encoding information activated
config[0].aprs_conf.tel_enc_cycle = 3600; // Transmit Telemetry encoding information every 3600sec
chsnprintf(config[0].aprs_conf.tel_comment, 30, "http://ssdv.habhub.org/DL7AD");// Telemetry comment
//start_position_thread(&config[0]);
start_position_thread(&config[0]);
// Module POSITION, UKHAS 2m 2FSK
config[1].power = 127; // Transmission Power
@ -440,7 +440,7 @@ void start_user_modules(void)
config[3].trigger.type = TRIG_CONTINUOUSLY; // Transmit continuously
chsnprintf(config[3].aprs_conf.callsign, 16, "DL7AD"); // APRS Callsign
config[3].aprs_conf.ssid = 14; // APRS SSID
config[3].aprs_conf.preamble = 300; // APRS Preamble (300ms)
config[3].aprs_conf.preamble = 200; // APRS Preamble (200ms)
config[3].ssdv_conf.ram_buffer = ssdv_buffer; // Camera buffer
config[3].ssdv_conf.ram_size = sizeof(ssdv_buffer); // Buffer size
config[3].ssdv_conf.res = RES_QVGA; // Resolution QVGA
@ -473,8 +473,8 @@ void start_user_modules(void)
config[5].fsk_conf.bits = 8; // 8bit
config[5].fsk_conf.stopbits = 2; // 2 Stopbits
config[5].fsk_conf.predelay = 3000; // Preamble (1000ms)
config[5].fsk_conf.baud = 300; // Baudrate (600baud)
config[5].fsk_conf.shift = 425; // Frequency shift (1000Hz)
config[5].fsk_conf.baud = 600; // Baudrate (600baud)
config[5].fsk_conf.shift = 425; // Frequency shift (1000Hz)
chsnprintf(config[5].ssdv_conf.callsign, 7, "DL7AD"); // SSDV Callsign
config[5].ssdv_conf.ram_buffer = ssdv_buffer; // Camera buffer
config[5].ssdv_conf.ram_size = sizeof(ssdv_buffer); // Buffer size
@ -492,11 +492,10 @@ void start_user_modules(void)
config[6].frequency.hz = 144800000; // Default frequency 144.800 MHz
config[6].init_delay = 5000; // Module startup delay (5 seconds)
config[6].trigger.type = TRIG_TIMEOUT; // Periodic cycling (every 180 seconds)
config[6].trigger.timeout = 60; // Timeout 180 sec
config[6].trigger.timeout = 60; // Timeout 60 sec
chsnprintf(config[6].aprs_conf.callsign, 16, "DL7AD"); // APRS Callsign
config[6].aprs_conf.ssid = 13; // APRS SSID
chsnprintf(config[6].aprs_conf.path, 16, "WIDE1-1"); // APRS Path
config[6].aprs_conf.preamble = 300; // APRS Preamble (300ms)
//start_logging_thread(&config[6]);
config[6].aprs_conf.ssid = 15; // APRS SSID
config[6].aprs_conf.preamble = 200; // APRS Preamble (200ms)
start_logging_thread(&config[6]);
}

Wyświetl plik

@ -147,32 +147,7 @@ THD_FUNCTION(logThread, arg)
if(!p_sleep(&conf->sleep_conf))
{
// Get log from memory
uint16_t pkt[80]; // 16 PositionPoints each 10 bytes
uint8_t pkt_base91[BASE91LEN(160)];
for(uint16_t t=0; t<sizeof(pkt_base91); t++) pkt_base91[t] = 0; // Deleting buffer
TRACE_INFO("LOG > Encode 16 log points")
for(uint8_t i=0; i<16; i++)
{
trackPoint_t log;
getNextLogTrackPoint(&log);
TRACE_INFO("id=%d time=%d lat=%d lon=%d alt=%d", log.id, log.gps_time, log.gps_lat, log.gps_lon, log.gps_alt);
int64_t lat = (int64_t)log.gps_lat + (int64_t)900000000 + 13733;
lat <<= 16;
lat /= 1800000000;
int64_t lon = (int64_t)log.gps_lon + (int64_t)1800000000 + 27466;
lon <<= 16;
lon /= 3600000000;
pkt[i*5+0] = log.gps_time & 0xFFFF;
pkt[i*5+1] = log.gps_time >> 16;
pkt[i*5+2] = lat; // Latitude (get full 16bit resolution over 180°)
pkt[i*5+3] = lon; // Longitude (get full 16bit resolution over 360°)
pkt[i*5+4] = log.gps_alt; // Altitude in meters (cut off first two MSB bytes)
}
trackPoint_t log;
// Encode radio message
radioMSG_t msg;
@ -188,14 +163,19 @@ THD_FUNCTION(logThread, arg)
msg.afsk_conf = &(conf->afsk_conf);
msg.gfsk_conf = &(conf->gfsk_conf);
ax25_t ax25_handle;
// Encode Base91
base91_encode((uint8_t*)pkt, pkt_base91, sizeof(pkt));
uint8_t pkt_base91[BASE91LEN(sizeof(log))];
// Encode and transmit log packet
ax25_t ax25_handle;
aprs_encode_init(&ax25_handle, buffer, sizeof(buffer), msg.mod);
aprs_encode_data_packet(&ax25_handle, 'L', &conf->aprs_conf, pkt_base91, strlen((char*)pkt_base91)); // Encode packet
for(uint8_t i=0; i<2; i++) { // Transmit two log packets
getNextLogTrackPoint(&log);
base91_encode((uint8_t*)&log, pkt_base91, sizeof(log));
aprs_encode_data_packet(&ax25_handle, 'L', &conf->aprs_conf, pkt_base91, strlen((char*)pkt_base91)); // Encode packet
}
msg.bin_len = aprs_encode_finalize(&ax25_handle);
// Transmit packet