diff --git a/decoder/decoder.py b/decoder/decoder.py index fc0868d..2cbc586 100755 --- a/decoder/decoder.py +++ b/decoder/decoder.py @@ -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 diff --git a/decoder/html/Telemetry.class.php b/decoder/html/Telemetry.class.php index 3175247..4c3eee3 100644 --- a/decoder/html/Telemetry.class.php +++ b/decoder/html/Telemetry.class.php @@ -1,24 +1,9 @@ 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 "$str"; - elseif($type == self::TYPE_STR) - return $str; - }*/ } ?> - - - - - - - - - - - - - - - - diff --git a/decoder/html/Tracker.class.php b/decoder/html/Tracker.class.php index dcb7ae6..dfd4ffb 100644 --- a/decoder/html/Tracker.class.php +++ b/decoder/html/Tracker.class.php @@ -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 { } } ?> + diff --git a/decoder/html/telemetry.php b/decoder/html/telemetry.php index 8a9ea90..5fb72ca 100644 --- a/decoder/html/telemetry.php +++ b/decoder/html/telemetry.php @@ -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-)*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-)*1000); + for(var c=0; c 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)) diff --git a/tracker/software/config.c b/tracker/software/config.c index c3ca3e3..692cb44 100644 --- a/tracker/software/config.c +++ b/tracker/software/config.c @@ -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]); } diff --git a/tracker/software/threads/log.c b/tracker/software/threads/log.c index 2916f5d..1fd2c8b 100644 --- a/tracker/software/threads/log.c +++ b/tracker/software/threads/log.c @@ -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 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