Commit 1fa6404e authored by Vasilis Tsiligiannis's avatar Vasilis Tsiligiannis
Browse files

Strip client of UPSat and web specific code

parent 264dcb04
......@@ -2,9 +2,8 @@
import logging
from satnogsclient.scheduler.tasks import status_listener, exec_rigctld
from satnogsclient.web.app import app, socketio
from satnogsclient.upsat.packet import folder_init
import threading
import time
logger = logging.getLogger('satnogsclient')
......@@ -15,13 +14,10 @@ def main():
ser = threading.Thread(target=status_listener, args=())
ser.daemon = True
ser.start()
folder_init()
exec_rigctld()
try:
logger.info('Press Ctrl+C to exit SatNOGS poller')
socketio.run(app, host='0.0.0.0')
except (KeyboardInterrupt, SystemExit):
socketio.stop()
logger.info('Press Ctrl+C to exit SatNOGS poller')
while True:
time.sleep(10)
if __name__ == '__main__':
......
# -*- coding: utf-8 -*-
from satnogsclient.web.weblogger import WebLogger
import logging
import os
from datetime import datetime
from time import sleep
from subprocess import call
from flask_socketio import SocketIO
from satnogsclient import settings
from satnogsclient.observer.worker import WorkerFreq, WorkerTrack
from satnogsclient.upsat import gnuradio_handler
logging.setLoggerClass(WebLogger)
logger = logging.getLogger('default')
assert isinstance(logger, WebLogger)
socketio = SocketIO(message_queue='redis://')
class Observer:
......
# -*- coding: utf-8 -*-
from satnogsclient.web.weblogger import WebLogger
import logging
import sys
......@@ -9,9 +8,7 @@ import ephem
import pytz
logging.setLoggerClass(WebLogger)
logger = logging.getLogger('default')
assert isinstance(logger, WebLogger)
def pinpoint(observer_dict, satellite_dict, timestamp=None):
......
# -*- coding: utf-8 -*-
from satnogsclient.web.weblogger import WebLogger
import logging
import math
import threading
......@@ -13,15 +12,11 @@ from datetime import datetime
import ephem
import pytz
from flask_socketio import SocketIO
from satnogsclient.observer.commsocket import Commsocket
from satnogsclient.observer.orbital import pinpoint
logging.setLoggerClass(WebLogger)
logger = logging.getLogger('default')
assert isinstance(logger, WebLogger)
socketio = SocketIO(message_queue='redis://')
class Worker:
......@@ -119,13 +114,6 @@ class Worker:
p = pinpoint(self.observer_dict, self.satellite_dict)
if p['ok']:
dict = {'azimuth': p['az'].conjugate() * 180 / math.pi,
'altitude': p['alt'].conjugate() * 180 / math.pi,
'frequency': self._frequency * (1 - (p['rng_vlct'] / ephem.c)),
'tle0': self.satellite_dict['tle0'],
'tle1': self.satellite_dict['tle1'],
'tle2': self.satellite_dict['tle2']}
socketio.emit('update_rotator', dict, namespace='/update_status')
self.send_to_socket(p, sock)
time.sleep(self.SLEEP_TIME)
......
from satnogsclient.web.weblogger import WebLogger
import logging
import os
import signal
import time
import sys
import cPickle
from dateutil import parser
from urlparse import urljoin
from multiprocessing import Process
import json
from satnogsclient.scheduler import scheduler
from flask_socketio import SocketIO
from satnogsclient.upsat.large_data_service import downlink
from satnogsclient.upsat.wod import wod_decode
import subprocess
import requests
from satnogsclient import settings
from satnogsclient.observer.observer import Observer
from satnogsclient.observer.commsocket import Commsocket
from satnogsclient.observer.udpsocket import Udpsocket
from satnogsclient.upsat import serial_handler, ecss_logic_utils
from satnogsclient.upsat.gnuradio_handler import read_from_gnuradio
from time import sleep
logging.setLoggerClass(WebLogger)
logger = logging.getLogger('default')
assert isinstance(logger, WebLogger)
socketio = SocketIO(message_queue='redis://')
log_path = settings.SATNOGS_OUTPUT_PATH + "/files/"
......@@ -155,8 +139,6 @@ def get_jobs():
if job.name in [spawn_observer.__name__]:
job.remove()
sock = Commsocket('127.0.0.1', settings.TASK_FEEDER_TCP_PORT)
tasks = []
for obj in response.json():
tasks.append(obj)
......@@ -172,61 +154,12 @@ def get_jobs():
kwargs=kwargs)
tasks.reverse()
while sys.getsizeof(json.dumps(tasks)) > sock.tasks_buffer_size:
tasks.pop()
b = sock.connect()
if b:
sock.send_not_recv(json.dumps(tasks))
else:
logger.info('Task listener thread not online')
def task_feeder(port):
sleep(1)
logger.info('Started task feeder')
sock = Commsocket('127.0.0.1', port)
sock.bind()
sock.listen()
while 1:
try:
conn = sock.accept()
except IOError:
logger.info(
'Task feeder is terminated or something bad happened to accept')
return
if conn:
data = conn.recv(sock.tasks_buffer_size)
# Data must be sent to socket.io here
socketio.emit(
'backend_msg', json.loads(data), namespace='/control_rx')
socketio.emit(
'update_scheduled', json.loads(data), namespace='/update_status')
def ecss_feeder(port):
sleep(1)
logger.info('Started ecss feeder')
sock = Udpsocket(('127.0.0.1', port))
while 1:
try:
conn = sock.recv()
except IOError:
logger.info(
'Ecss feeder is terminated or something bad happened to accept')
return
data = ecss_logic_utils.ecss_logic(cPickle.loads(conn[0]))
# Data must be sent to socket.io here
socketio.emit('backend_msg', data, namespace='/control_rx',
callback=success_message_to_frontend())
def success_message_to_frontend():
logger.debug('Successfuly emit to frontend')
def status_listener():
logger.info('Started upsat status listener')
logger.info('Starting scheduler...')
scheduler.start()
scheduler.remove_all_jobs()
......@@ -240,81 +173,10 @@ def status_listener():
interval)
logger.info(msg)
scheduler.add_job(post_data, 'interval', minutes=interval)
tf = Process(target=task_feeder, args=(settings.TASK_FEEDER_TCP_PORT,))
tf.start()
d = Process(target=downlink, args=())
d.daemon = True
d.start()
os.environ['TASK_FEEDER_PID'] = str(tf.pid)
sock = Udpsocket(('127.0.0.1', settings.STATUS_LISTENER_PORT))
os.environ['BACKEND_TX_PID'] = '0'
os.environ['BACKEND_RX_PID'] = '0'
os.environ['BACKEND'] = ""
os.environ['MODE'] = "network"
os.environ['ECSS_FEEDER_PID'] = '0'
os.environ['GNURADIO_SCRIPT_PID'] = '0'
os.environ['SCHEDULER'] = 'ON'
while 1:
conn = sock.recv()
dictionary = json.loads(conn[0])
if 'backend' in dictionary.keys():
if dictionary['backend'] == os.environ['BACKEND']:
continue
kill_cmd_ctrl_proc()
if dictionary['backend'] == 'gnuradio':
if os.environ['BACKEND'] == 'serial':
serial_handler.close()
os.environ['BACKEND'] = 'gnuradio'
rx = Process(target=read_from_gnuradio, args=())
rx.daemon = True
rx.start()
logger.info('Started gnuradio rx process %d', rx.pid)
os.environ['BACKEND_RX_PID'] = str(rx.pid)
elif dictionary['backend'] == 'serial':
os.environ['BACKEND'] = 'serial'
serial_handler.init()
rx = Process(target=serial_handler.read_from_serial, args=())
rx.daemon = True
rx.start()
os.environ['BACKEND_RX_PID'] = str(rx.pid)
if 'mode' in dictionary.keys():
if dictionary['mode'] == os.environ['MODE']:
continue
logger.info('Changing mode')
if dictionary['mode'] == 'cmd_ctrl':
logger.info('Starting ecss feeder thread...')
logger.info('Clearing scheduled observations')
kill_netw_proc()
os.environ['MODE'] = 'cmd_ctrl'
ef = Process(
target=ecss_feeder, args=(settings.ECSS_FEEDER_UDP_PORT,))
start_wod_thread()
ef.start()
os.environ['ECSS_FEEDER_PID'] = str(ef.pid)
logger.info('Started ecss_feeder process %d', ef.pid)
elif dictionary['mode'] == 'network':
os.environ['MODE'] = 'network'
kill_cmd_ctrl_proc()
kill_wod_thread()
if int(os.environ['ECSS_FEEDER_PID']) != 0:
os.kill(int(os.environ['ECSS_FEEDER_PID']), signal.SIGTERM)
os.environ['ECSS_FEEDER_PID'] = '0'
scheduler.remove_all_jobs()
interval = settings.SATNOGS_NETWORK_API_QUERY_INTERVAL
scheduler.add_job(get_jobs, 'interval', minutes=interval)
msg = 'Registering `get_jobs` periodic task ({0} min. interval)'.format(
interval)
logger.info(msg)
interval = settings.SATNOGS_NETWORK_API_POST_INTERVAL
msg = 'Registering `post_data` periodic task ({0} min. interval)'.format(
interval)
logger.info(msg)
scheduler.add_job(post_data, 'interval', minutes=interval)
tf = Process(
target=task_feeder, args=(settings.TASK_FEEDER_TCP_PORT,))
tf.start()
os.environ['TASK_FEEDER_PID'] = str(tf.pid)
logger.info('Started task feeder process %d', tf.pid)
def kill_cmd_ctrl_proc():
......@@ -332,52 +194,6 @@ def kill_netw_proc():
logger.info('Scheduler shutting down')
def start_wod_thread():
wd = Process(target=wod_listener, args=())
wd.daemon = True
wd.start()
os.environ['WOD_THREAD_PID'] = str(wd.pid)
logger.info('WOD listener thread initialized')
def wod_listener():
sock = Udpsocket(('127.0.0.1', settings.WOD_UDP_PORT))
while 1:
try:
conn, addr = sock.recv()
except IOError:
logger.error(
'WOD listerner is terminated or something bad happened to accept')
return
logger.debug("WOD received %s", conn)
# Write to disk the binary packet
timestr = time.strftime("%Y%m%d-%H%M%S")
fwname = log_path + "WOD_RX/wod_" + timestr + ".hex"
myfile = open(fwname, 'w')
myfile.write(conn)
myfile.close()
data = wod_decode(conn)
# Write to disk the decoded packet
timestr = time.strftime("%Y%m%d-%H%M%S")
fwname = log_path + "WOD_RX_DEC/wod_" + timestr + ".json"
myfile = open(fwname, 'w')
myfile.write(str(data['content']))
myfile.close()
# Data must be sent to socket.io here
socketio.emit('backend_msg', data, namespace='/control_rx',
callback=success_message_to_frontend())
def kill_wod_thread():
if 'WOD_THREAD_PID' in os.environ:
os.kill(int(os.environ['WOD_THREAD_PID']), signal.SIGKILL)
os.environ['WOD_THREAD_PID'] = '0'
def add_observation(obj):
start = parser.parse(obj['start'])
job_id = str(obj['id'])
......@@ -389,7 +205,6 @@ def add_observation(obj):
run_date=start,
id=format(job_id),
kwargs=kwargs)
socketio.emit('update_scheduled', obj, namespace='/update_status')
return obs
......@@ -404,7 +219,6 @@ def get_observation(id):
def exec_rigctld():
from multiprocessing import Process
rig = Process(target=rigctld_subprocess, args=())
rig.start()
......
This diff is collapsed.
from satnogsclient.web.weblogger import WebLogger
import logging
import cPickle
import subprocess
......@@ -10,9 +9,7 @@ from satnogsclient.observer.udpsocket import Udpsocket
from satnogsclient.upsat import packet
logging.setLoggerClass(WebLogger)
logger = logging.getLogger('default')
assert isinstance(logger, WebLogger)
backend_listener_sock = Udpsocket(('0.0.0.0', client_settings.BACKEND_LISTENER_PORT)) # Port in which client listens for frames from gnuradio
ui_listener_sock = Udpsocket(('127.0.0.1', client_settings.BACKEND_FEEDER_PORT))
......
import logging
from satnogsclient.upsat import packet_settings
logger = logging.getLogger('satnogsclient')
log_path = ""
def HLDLC_deframe(buf_in, buf_out):
size = len(buf_in)
logger.debug('HLDLC size: %s', size)
r = range(1, size)
for i in r:
if buf_in[i] == packet_settings.HLDLC_START_FLAG:
return packet_settings.SATR_EOT
elif buf_in[i] == packet_settings.HLDLC_CONTROL_FLAG:
r.remove(i + 1) # it skips the next ieteration
i = i + 1
if not (i < size - 1):
return packet_settings.SATR_ERROR
if buf_in[i] == 0x5E:
buf_out.append(0x7E)
elif buf_in[i] == 0x5D:
buf_out.append(0x7D)
else:
return packet_settings.SATR_ERROR
else:
buf_out.append(buf_in[i])
return packet_settings.SATR_ERROR
def HLDLC_frame(buf_in, buf_out):
assert((buf_in != 0) and (buf_out != 0))
assert(len(buf_in) <= packet_settings.MAX_PKT_SIZE)
size = len(buf_in)
for i in range(0, size):
if i == 0:
buf_out.append(packet_settings.HLDLC_START_FLAG)
buf_out.append(buf_in[0])
elif i == size - 1:
if buf_in[i] == packet_settings.HLDLC_START_FLAG:
buf_out.append(packet_settings.HLDLC_CONTROL_FLAG)
buf_out.append(0x5E)
elif buf_in[i] == packet_settings.HLDLC_CONTROL_FLAG:
buf_out.append(packet_settings.HLDLC_CONTROL_FLAG)
buf_out.append(0x5D)
else:
buf_out.append(buf_in[i])
buf_out.append(packet_settings.HLDLC_START_FLAG)
return packet_settings.SATR_EOT
elif buf_in[i] == packet_settings.HLDLC_START_FLAG:
buf_out.append(packet_settings.HLDLC_CONTROL_FLAG)
buf_out.append(0x5E)
elif buf_in[i] == packet_settings.HLDLC_CONTROL_FLAG:
buf_out.append(packet_settings.HLDLC_CONTROL_FLAG)
buf_out.append(0x5D)
else:
buf_out.append(buf_in[i])
return packet_settings.SATR_ERROR
import os
import traceback
import cPickle
import logging
from satnogsclient.upsat import packet_settings
from satnogsclient import settings as client_settings
from satnogsclient.observer.udpsocket import Udpsocket
from satnogsclient.upsat import packet
from time import sleep
from _socket import htons
from satnogsclient.upsat import ecss_logic_utils
import time
import binascii
from flask_socketio import SocketIO
socketio = SocketIO(message_queue='redis://')
logger = logging.getLogger('satnogsclient')
large_data_id = 0
total_downlink_packets = 0
uplink_socket = Udpsocket(('0.0.0.0', client_settings.LD_UPLINK_LISTEN_PORT))
downlink_socket = Udpsocket(('0.0.0.0', client_settings.LD_DOWNLINK_LISTEN_PORT))
gnuradio_sock = Udpsocket([]) # Gnuradio's udp listen port
def uplink(buf_in):
buf = bytearray(0)
available_data_len = packet_settings.MAX_COMMS_PKT_SIZE - packet_settings.ECSS_HEADER_SIZE - packet_settings.ECSS_DATA_HEADER_SIZE - packet_settings.ECSS_CRC_SIZE - 3
buffer_size = len(buf_in)
remaining_bytes = buffer_size
total_packets = buffer_size / available_data_len
if buffer_size % available_data_len > 0:
total_packets = total_packets + 1
packet_count = 0
data_size = 0
while remaining_bytes > 0:
if remaining_bytes >= available_data_len:
data_size = available_data_len
remaining_bytes = remaining_bytes - available_data_len
else:
data_size = remaining_bytes
remaining_bytes = 0
buf = buf_in[0:data_size]
del buf_in[0:data_size]
packet_count_htons = htons(packet_count)
packet_count_ms = (packet_count_htons & 0xFF00) >> 8
packet_count_ls = packet_count_htons & 0x00FF
buf.insert(0, packet_count_ls)
buf.insert(0, packet_count_ms)
buf.insert(0, large_data_id)
if packet_count == 0:
ser_subtype = packet_settings.TC_LD_FIRST_UPLINK
elif packet_count == total_packets - 1:
ser_subtype = packet_settings.TC_LD_LAST_UPLINK
else:
ser_subtype = packet_settings.TC_LD_INT_UPLINK
ecss = {'type': 1,
'app_id': 4,
'size': len(buf),
'ack': 1,
'ser_type': packet_settings.TC_LARGE_DATA_SERVICE,
'ser_subtype': ser_subtype,
'dest_id': 6,
'data': buf,
'seq_count': packet_count}
hldlc_buf = packet.construct_packet(ecss, os.environ['BACKEND'])
gnuradio_sock.sendto(hldlc_buf, (client_settings.GNURADIO_IP, client_settings.GNURADIO_UDP_PORT))
got_ack = 0
retries = 0
while (retries < 30) and (got_ack == 0):
logger.info('[LD] ECSS to be sent: %s', str(ecss))
logger.info('[LD] Retries = %s, got ACK = %s', retries, got_ack)
try:
logger.info('Waiting for ack')
ack = uplink_socket.recv_timeout(client_settings.LD_UPLINK_TIMEOUT)
ecss_dict = cPickle.loads(ack[0])
if len(ecss_dict) == 0:
continue
if hex(ecss_dict['data'][0]) == hex(large_data_id):
logger.info('[LD] Seq count = %s', str(((ecss_dict['data'][0] << 8) | ecss_dict['data'][1])))
if ((ecss_dict['data'][2] << 8) | ecss_dict['data'][1]) == packet_count:
got_ack = 1
sleep(0.5)
logger.info('[LD] Got the right ack')
else:
sleep(0.5)
gnuradio_sock.sendto(hldlc_buf, (client_settings.GNURADIO_IP, client_settings.GNURADIO_UDP_PORT)) # Resend previous frame
retries = retries + 1
logger.error('[LD] Wrong large data sequence number')
else:
logger.error('[LD] Wrong large data ID')
retries = retries + 1
except Exception, e:
traceback.print_exc()
logger.error('[LD] exception: %s', str(e))
sleep(0.5)
gnuradio_sock.sendto(hldlc_buf, (client_settings.GNURADIO_IP, client_settings.GNURADIO_UDP_PORT))
retries = retries + 1
logger.error('[LD] [LD] Timed out')
if got_ack == 1:
if ser_subtype == packet_settings.TC_LD_LAST_UPLINK:
global large_data_id
large_data_id = large_data_id + 1
packet_count = packet_count + 1
else:
logger.info('[LD] Aborted operation')
return
def downlink():
prev_id = -1
end_time = 0
receiving = False
received_packets = {}
while 1:
if receiving:
try:
logger.info('[LD] Downlink thread awaits for next frame')
data = downlink_socket.recv_timeout(end_time - time.time())
logger.info('[LD] Downlink packet received!')
except:
logger.info('[LD] Downlink operation not completed on time. Going to fallback operation')
ret = fallback(received_packets, prev_id)
prev_id = -1
receiving = False
if ret[1] == 1:
frame = construct_downlink_packet(received_packets)
logger.debug('[LD] Packet received is: %s', str(binascii.hexlify(frame)))
logger.info('[LD] Downlink operation completed')
decode_and_send(frame)
logger.info('[LD] Packet sent to front end')
received_packets.clear()
global total_downlink_packets
total_downlink_packets = 0
continue
else:
received_packets.clear()
global total_downlink_packets
total_downlink_packets = 0
continue
ecss_dict = cPickle.loads(data[0])
else:
logger.info('[LD] Downlink thread waiting for first downlink packet')
data = downlink_socket.recv()
logger.info('[LD] First downlink packet received')
end_time = time.time() + client_settings.LD_DOWNLINK_TIMEOUT
ecss_dict = cPickle.loads(data[0])
receiving = True
prev_id = ecss_dict['data'][0]
if len(ecss_dict) == 0:
logger.error('[LD] Received empty ecss_dict. Ignoring frame')