diff --git a/README.md b/README.md index a8ef79a..7966005 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,10 @@ # Ground station core (GSC) -All-in-one open-source utility for SDR-based satellite tracking. All you need to establish your own ground station with your equipment. +All-in-one open-source utility for SDR-based satellite tracking. All you need to establish your own amateur or professional ground station. +## Wiki + +Find the detailed documentation on the [wiki](https://github.com/skypodolsky/ground-station-core/wiki) ## Features @@ -12,7 +15,7 @@ All-in-one open-source utility for SDR-based satellite tracking. All you need to - [x] Flexible: customize the digital signal processing with **GNU Radio** - [x] Flexible: customize needed actions before and after each pass - [x] Flexible: uses networking to operate with different SW parts -- [x] All Unix-based systems supported +- [x] All common Linux-based systems supported - [x] Read-time status monitoring - [x] Email notification system - [x] JSON-based configuration @@ -25,199 +28,5 @@ All-in-one open-source utility for SDR-based satellite tracking. All you need to - [x] NOAA weather satellites - [x] Voice audio conversations - [x] Two weeks in autonomous beta testing -- [ ] GOES geostationary satellites -- [ ] Meteor satellite - [x] Cubesats (BPSK, FSK) -# Installation (Debian/Ubuntu) - -Install `libpredict`: -``` -git clone https://github.com/la1k/libpredict.git -cd libpredict -mkdir build -cd build -cmake .. -sudo make install -``` - -Install prerequisites -``` -sudo apt-get install cmake gcc make predict libjson-c-dev hamlib-utils msmtp msmtp-mta libxmlrpc-core-c3-dev libconfig-dev -``` - -Configure msmtp -https://wiki.archlinux.org/title/Msmtp - -Install GSC: -``` -git clone https://github.com/skypodolsky/isu_ground_station.git -cd isu_ground_station -mkdir build -cd build -cmake .. -sudo make install -``` - -GSC will download a list of active satellites. -It will also register a new cron task to update this list every five days. - -Configure `gsc_notify.sh` and set relevant e-mails: - -``` -web_addr="http://172.16.30.52:8000" -sender="gsnotification38@gmail.com" -recipient="stanislav.barantsev@community.isunet.edu" -``` - -## Launch - -Start `rotctld` antenna controlling daemon(-s): - -``` -#azimuth controller -screen sudo rotctld -s 9600 -m 1004 -r /dev/ttyUSB0 -T 127.0.0.1 -t 8080 -vvvvv - -#elevation controller -screen sudo rotctld -s 9600 -m 1005 -r /dev/ttyUSB1 -T 127.0.0.1 -t 8081 -vvvvv -``` - -## Create a config file - -``` -// ground station parameters -latitude = 48.31237; -longitude = 7.44126; - -// rotctld ports -azimuth-port = 8080; -elevation-port = 8081; -remote-addr = "127.0.0.1"; - -// inbound port -request-port = 25565; - -// logging -verbosity = 3; -log-file = "dump.log" - -// gnuradio parameters -gnuradio-config = ; -gnuradio-flowgraph = ; -``` - -Start GSC: -``` -screen gsc -``` - -# Architecture - -## Main software structure -The main concept of the GSC is based on core architecture, which means that all main features are provided by a functional core block, in which all interaction with other utilities is strictly defined. The architecture is portable, which means that it can be moved without almost any changes to other Unix-based platforms (f.e., Raspberry PI, Debian, Ubuntu, Mint, etc). The product is written in C and compiled with CMake, which makes its deployment easier on different Linux platforms. - -The architecture consists primarily of the following subsystems: - - Configuration server - - JSON REST API - - Configuration parser - - Block for orbit prediction - - Block for antenna handling - - Block for SDR interaction - - Block for scheduling satellites - - Notification system - - - -Antenna rotators’ controllers are programmed by rotctld daemon. It is a part of Hamlib library, which is widely used as a software controlling unit for ground stations all around the world. It is a standard Linux-based utility that supports a lot of controllers of antenna rotators. Widely used for numerous prediction programs like GPredict, libpredict library for orbit prediction has found an application in this project too. For compatibility with all popular SDRs, SoapySDR library was chosen. It provides a hardware-independent C API for interaction, which is used to control an SDR. The system is configured from console (all static variables, f.e., latitude, longitude, azimuth offset compensation, etc.) and via network requests (dynamic configuration, f.e., tracking configuration). GSC uses a network server to make the second configuration type possible. To provide a reliable solution, libev library for network events handling has been integrated. Last but not least, libjson-c, a C-based library for parsing JSON requests, has also been chosen as a lightweight JSON parsing library. - -## Configuration -The utility operates in a fully autonomous mode, allowing it to pass the configuration through the REST API. Fully automated mode means that the system **does not require a network connection to operate**, it needs it only at the dynamic configuration stage. After the system has been configured, the connection isn’t crucial anymore. The configuration requests are transferred with HTTP or HTTPS protocols and invoked in JSON format. The example of JSON REST API POST request is provided below: - -``` -{ - "observation": { - "satellite" : [ - { - "name": "NAYIF-1", - "modulation": "bpsk", - "bpsk_manchester": false, - "bpsk_differential": true, - "bpsk_short_preamble": false, - "bpsk_crc16": false, - "baud_rate": 1200, - "frequency": 145940000, - "bandwidth": 20000, - "priority": 2, - "min_elevation": 30.0 - }, - { - "name": "FUNCUBE-1", - "modulation": "bpsk", - "bpsk_manchester": false, - "bpsk_differential": true, - "bpsk_short_preamble": false, - "bpsk_crc16": false, - "baud_rate": 1200, - "frequency": 145935000, - "bandwidth": 20000, - "priority": 1, - "min_elevation": 30.0 - }, - { - "name": "JY1SAT", - "modulation": "bpsk", - "bpsk_manchester": false, - "bpsk_differential": true, - "bpsk_short_preamble": false, - "bpsk_crc16": false, - "baud_rate": 1200, - "frequency": 145840000, - "bandwidth": 20000, - "priority": 3, - "min_elevation": 30.0 - } - ] - } -} -``` - -The typical response: - - - -## Work sequence - - -## Satellite scheduling - - -## Debugging of scheduler -A so-called ‘time travel’ approach was implemented. By ‘time travel’ a virtual change in time is assumed. It means that if we need to simulate a moving satellite that was scheduled to a specific time, we just need to make the system think that this time has arrived. In such a case system will behave exactly as when the real satellite comes over the horizon. There are two time travels possible in the scope of the GSC utility, that provides a full scope of debugging functionality that was needed during development: - - - Time travel to the next satellite’s AOS - - Time travel to the next satellite’s LOS - -The first case in makes it possible to simulate the next satellite: this is important to verify that the antenna positioning system and SDR recording works properly. The second one was useful to estimate the scheduling for a bigger time scale. - - - -## Notification system -As the new demodulated files are placed on the Web Server/FTP server, the author found it useful to notify users about the new data available. Every time when SDR accomplishes the recording process, a report with the link on the new data is sent. Therefore, two tasks are solved: - - - No need to constantly check the next AOS of a satellite: the system will send a notification - - No need to look for the most recent data among hundreds of other files: the system will send a direct link to the file - -From the perspective of Linux, this task was solved with msmtp utility. There is a possibility to attach the file directly to the email, but this functionality isn’t implemented in the current release yet. Despite that, the notification can be done for multiple people/groups (this aspect is disclosed in the documentation). - - - -# Results - -## Western Europe from the NOAA 18 satellite on 30 Mar 2021, multispectral analysis instrument - - -## Northern Sahara and Italy in Map Colored in Infrared (MCIR), NOAA-18, 5 Apr 2021 - - -## France as seen from the NOAA 18 satellite on 6 Apr 2021, multispectral analysis instrument - diff --git a/grc/downlink-principal.grc b/grc/downlink-principal.grc new file mode 100644 index 0000000..d882889 --- /dev/null +++ b/grc/downlink-principal.grc @@ -0,0 +1,1537 @@ +options: + parameters: + author: '' + category: '[GRC Hier Blocks]' + cmake_opt: '' + comment: '' + copyright: '' + description: '' + gen_cmake: 'On' + gen_linking: dynamic + generate_options: no_gui + hier_block_src_path: '.:' + id: fmDemod + max_nouts: '0' + output_language: python + placement: (0,0) + qt_qss_theme: '' + realtime_scheduling: '' + run: 'True' + run_command: '{python} -u {filename}' + run_options: prompt + sizing_mode: fixed + thread_safe_setters: '' + title: Leanspace + GNU Radio + window_size: (1000,1000) + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [8, 8] + rotation: 0 + state: enabled + +blocks: +- name: deframer_CRC16_Bool + id: variable_config + parameters: + comment: '' + config_file: /home/stanislavb/sdr_prototypes/master/default + option: deframer_CRC16 + section: deframer + type: bool + value: 'False' + writeback: None + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [2144, 12.0] + rotation: 0 + state: true +- name: deframer_G3RUH_Bool + id: variable_config + parameters: + comment: '' + config_file: /home/stanislavb/sdr_prototypes/master/default + option: deframer_G3RUH + section: deframer + type: bool + value: 'False' + writeback: None + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [1984, 12.0] + rotation: 0 + state: true +- name: deframer_Short_Frames_Bool + id: variable_config + parameters: + comment: '' + config_file: /home/stanislavb/sdr_prototypes/master/default + option: deframer_Short_Frames + section: deframer + type: bool + value: 'False' + writeback: None + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [1984, 156.0] + rotation: 0 + state: true +- name: deframer_Syncword_Threshold_Int + id: variable_config + parameters: + comment: '' + config_file: /home/stanislavb/sdr_prototypes/master/default + option: deframer_Syncword_Threshold + section: deframer + type: int + value: '4' + writeback: None + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [2168, 156.0] + rotation: 0 + state: enabled +- name: fileNameRaw + id: variable + parameters: + comment: '' + value: main_Result_File_Prefix_Str + ".raw" + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [440, 220.0] + rotation: 0 + state: enabled +- name: fileNameRes + id: variable + parameters: + comment: '' + value: main_Result_File_Prefix_Str + ".dat" + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [440, 156.0] + rotation: 0 + state: enabled +- name: freqOffset + id: variable + parameters: + comment: '' + value: '11000' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [280, 12.0] + rotation: 0 + state: enabled +- name: main_LPF_Cutoff_Freq_Int + id: variable_config + parameters: + comment: '' + config_file: /home/stanislavb/sdr_prototypes/master/default + option: main_LPF_Cutoff_Freq + section: main + type: int + value: sampRate - 10000 + writeback: None + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [760, 156.0] + rotation: 0 + state: true +- name: main_Network_Stream_Address_Str + id: variable_config + parameters: + comment: '' + config_file: /home/stanislavb/sdr_prototypes/master/default + option: main_Network_Stream_Address + section: main + type: string + value: 127.0.0.1 + writeback: None + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [2376, 12.0] + rotation: 0 + state: true +- name: main_Network_Stream_Port_Int + id: variable_config + parameters: + comment: '' + config_file: /home/stanislavb/sdr_prototypes/master/default + option: main_Network_Stream_Port + section: main + type: int + value: '8080' + writeback: None + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [2568, 12.0] + rotation: 0 + state: true +- name: main_Result_File_Prefix_Str + id: variable_config + parameters: + comment: '' + config_file: /home/stanislavb/sdr_prototypes/master/default + option: main_Result_File_Prefix + section: main + type: string + value: ERROR_PREFIX + writeback: None + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [440, 12.0] + rotation: 0 + state: true +- name: modulation_AFSK_Audio_Carrier_Freq_Int + id: variable_config + parameters: + comment: '' + config_file: /home/stanislavb/sdr_prototypes/master/default + option: modulation_AFSK_Audio_Carrier_Freq + section: modulation + type: int + value: '3600' + writeback: None + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [1256, 156.0] + rotation: 0 + state: true +- name: modulation_AFSK_Deviation_Int + id: variable_config + parameters: + comment: '' + config_file: /home/stanislavb/sdr_prototypes/master/default + option: modulation_AFSK_Deviation + section: modulation + type: int + value: '-1200' + writeback: None + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [1424, 156.0] + rotation: 0 + state: true +- name: modulation_BPSK_Differential_Bool + id: variable_config + parameters: + comment: '' + config_file: /home/stanislavb/sdr_prototypes/master/default + option: modulation_BPSK_Differential + section: modulation + type: bool + value: 'True' + writeback: None + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [1600, 156.0] + rotation: 0 + state: true +- name: modulation_BPSK_Manchester_Bool + id: variable_config + parameters: + comment: '' + config_file: /home/stanislavb/sdr_prototypes/master/default + option: modulation_BPSK_Manchester + section: modulation + type: bool + value: 'False' + writeback: None + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [1784, 12.0] + rotation: 0 + state: true +- name: modulation_Baud_Rate_Int + id: variable_config + parameters: + comment: '' + config_file: /home/stanislavb/sdr_prototypes/master/default + option: modulation_Baud_Rate + section: modulation + type: int + value: '9600' + writeback: None + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [1416, 12.0] + rotation: 0 + state: true +- name: modulation_Deframer_Type_Int + id: variable_config + parameters: + comment: '' + config_file: /home/stanislavb/sdr_prototypes/master/default + option: modulation_Deframer_Type + section: modulation + type: int + value: '0' + writeback: None + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [1768, 156.0] + rotation: 0 + state: true +- name: modulation_FSK_Sub_Audio_Bool + id: variable_config + parameters: + comment: '' + config_file: /home/stanislavb/sdr_prototypes/master/default + option: modulation_FSK_Sub_Audio + section: modulation + type: bool + value: 'False' + writeback: None + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [1600, 12.0] + rotation: 0 + state: true +- name: modulation_Type_Int + id: variable_config + parameters: + comment: '' + config_file: /home/stanislavb/sdr_prototypes/master/default + option: modulation_Type + section: modulation + type: int + value: '0' + writeback: None + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [1256, 12.0] + rotation: 0 + state: true +- name: sampRate + id: variable + parameters: + comment: '' + value: '480000' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [192, 12.0] + rotation: 0 + state: enabled +- name: sdr_BB_Gain_Int + id: variable_config + parameters: + comment: '' + config_file: /home/stanislavb/sdr_prototypes/master/default + option: sdr_BB_Gain + section: sdr + type: int + value: '40' + writeback: None + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [1080, 12.0] + rotation: 0 + state: true +- name: sdr_Freq_Int + id: variable_config + parameters: + comment: '' + config_file: /home/stanislavb/sdr_prototypes/master/default + option: sdr_Freq + section: sdr + type: int + value: '145935000' + writeback: None + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [760, 12.0] + rotation: 0 + state: true +- name: sdr_IF_Gain_Int + id: variable_config + parameters: + comment: '' + config_file: /home/stanislavb/sdr_prototypes/master/default + option: sdr_IF_Gain + section: sdr + type: int + value: '40' + writeback: None + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [920, 12.0] + rotation: 0 + state: true +- name: sdr_LNA_Gain_Int + id: variable_config + parameters: + comment: '' + config_file: /home/stanislavb/sdr_prototypes/master/default + option: sdr_LNA_Gain + section: sdr + type: int + value: '14' + writeback: None + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [936, 156.0] + rotation: 0 + state: true +- name: analog_fm_deemph_0 + id: analog_fm_deemph + parameters: + affinity: '' + alias: '' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + samp_rate: sampRate / 10 + tau: 75e-6 + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [1304, 1556.0] + rotation: 0 + state: true +- name: analog_wfm_rcv_0 + id: analog_wfm_rcv + parameters: + affinity: '' + alias: '' + audio_decimation: '1' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + quad_rate: sampRate / 10 + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [672, 1484.0] + rotation: 0 + state: true +- name: blocks_file_sink_0 + id: blocks_file_sink + parameters: + affinity: '' + alias: '' + append: 'False' + comment: '' + file: fileNameRes + type: byte + unbuffered: 'False' + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [1912, 1308.0] + rotation: 0 + state: true +- name: blocks_file_sink_1 + id: blocks_file_sink + parameters: + affinity: '' + alias: '' + append: 'False' + comment: '' + file: fileNameRaw + type: complex + unbuffered: 'False' + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [1400, 568.0] + rotation: 0 + state: enabled +- name: blocks_float_to_complex_0 + id: blocks_float_to_complex + parameters: + affinity: '' + alias: '' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [1432, 864.0] + rotation: 0 + state: enabled +- name: blocks_message_debug_0 + id: blocks_message_debug + parameters: + affinity: '' + alias: '' + comment: '' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [2320, 952.0] + rotation: 0 + state: enabled +- name: blocks_null_source_1 + id: blocks_null_source + parameters: + affinity: '' + alias: '' + bus_structure_source: '[[0,],]' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + num_outputs: '1' + type: float + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [1288, 896.0] + rotation: 0 + state: enabled +- name: blocks_pdu_to_tagged_stream_0 + id: blocks_pdu_to_tagged_stream + parameters: + affinity: '' + alias: '' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + tag: data + type: byte + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [1656, 1228.0] + rotation: 0 + state: enabled +- name: blocks_selector_0 + id: blocks_selector + parameters: + affinity: '' + alias: '' + comment: Modulation + enabled: 'True' + input_index: '0' + maxoutbuf: '0' + minoutbuf: '0' + num_inputs: '1' + num_outputs: '4' + output_index: modulation_Type_Int + showports: 'True' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [1864, 640.0] + rotation: 0 + state: enabled +- name: blocks_selector_1 + id: blocks_selector + parameters: + affinity: '' + alias: '' + comment: For debugging purposes + enabled: 'True' + input_index: '0' + maxoutbuf: '0' + minoutbuf: '0' + num_inputs: '2' + num_outputs: '1' + output_index: '0' + showports: 'True' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [1632, 652.0] + rotation: 0 + state: enabled +- name: blocks_selector_2 + id: blocks_selector + parameters: + affinity: '' + alias: '' + comment: '' + enabled: 'True' + input_index: modulation_Type_Int + maxoutbuf: '0' + minoutbuf: '0' + num_inputs: '4' + num_outputs: '7' + output_index: modulation_Deframer_Type_Int + showports: 'True' + type: float + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [968, 1240.0] + rotation: 0 + state: true +- name: blocks_selector_3 + id: blocks_selector + parameters: + affinity: '' + alias: '' + comment: DC blocker bypass + enabled: 'True' + input_index: '1' + maxoutbuf: '0' + minoutbuf: '0' + num_inputs: '2' + num_outputs: '1' + output_index: '0' + showports: 'True' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [968, 536.0] + rotation: 0 + state: enabled +- name: blocks_udp_sink_0 + id: blocks_udp_sink + parameters: + affinity: '' + alias: '' + comment: '' + eof: 'True' + ipaddr: main_Network_Stream_Address_Str + port: main_Network_Stream_Port_Int + psize: '1472' + type: byte + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [1912, 1204.0] + rotation: 0 + state: enabled +- name: blocks_wavfile_sink_0 + id: blocks_wavfile_sink + parameters: + affinity: '' + alias: '' + bits_per_sample: '8' + comment: '' + file: fileNameRes + nchan: '1' + samp_rate: int(sampRate / 10) + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [1496, 1548.0] + rotation: 0 + state: true +- name: blocks_wavfile_source_0 + id: blocks_wavfile_source + parameters: + affinity: '' + alias: '' + comment: '' + file: /home/stanislavb/satellite-recordings/gomx_1.wav + maxoutbuf: '0' + minoutbuf: '0' + nchan: '1' + repeat: 'True' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [1080, 852.0] + rotation: 0 + state: enabled +- name: dc_blocker_xx_0 + id: dc_blocker_xx + parameters: + affinity: '' + alias: '' + comment: '' + length: '32' + long_form: 'True' + maxoutbuf: '0' + minoutbuf: '0' + type: cc + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [784, 652.0] + rotation: 0 + state: enabled +- name: low_pass_filter_1 + id: low_pass_filter + parameters: + affinity: '' + alias: '' + beta: '6.76' + comment: '' + cutoff_freq: main_LPF_Cutoff_Freq_Int + decim: '10' + gain: '1' + interp: '1' + maxoutbuf: '0' + minoutbuf: '0' + samp_rate: sampRate + type: fir_filter_ccf + width: '1000' + win: firdes.WIN_HAMMING + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [1184, 620.0] + rotation: 0 + state: enabled +- name: note_0 + id: note + parameters: + alias: '' + comment: '' + note: File names config + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [440, 324.0] + rotation: 0 + state: true +- name: note_0_0 + id: note + parameters: + alias: '' + comment: '' + note: SDR config + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [864, 324.0] + rotation: 0 + state: true +- name: note_1 + id: note + parameters: + alias: '' + comment: '' + note: Modulation config + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [1528, 324.0] + rotation: 0 + state: true +- name: note_1_0 + id: note + parameters: + alias: '' + comment: '' + note: Deframing config + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [2096, 324.0] + rotation: 0 + state: true +- name: note_1_0_0 + id: note + parameters: + alias: '' + comment: '' + note: Network config + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [2496, 324.0] + rotation: 0 + state: true +- name: osmosdr_source_0 + id: osmosdr_source + parameters: + affinity: '' + alias: '' + ant0: '' + ant1: '' + ant10: '' + ant11: '' + ant12: '' + ant13: '' + ant14: '' + ant15: '' + ant16: '' + ant17: '' + ant18: '' + ant19: '' + ant2: '' + ant20: '' + ant21: '' + ant22: '' + ant23: '' + ant24: '' + ant25: '' + ant26: '' + ant27: '' + ant28: '' + ant29: '' + ant3: '' + ant30: '' + ant31: '' + ant4: '' + ant5: '' + ant6: '' + ant7: '' + ant8: '' + ant9: '' + args: '""' + bb_gain0: sdr_BB_Gain_Int + bb_gain1: '20' + bb_gain10: '20' + bb_gain11: '20' + bb_gain12: '20' + bb_gain13: '20' + bb_gain14: '20' + bb_gain15: '20' + bb_gain16: '20' + bb_gain17: '20' + bb_gain18: '20' + bb_gain19: '20' + bb_gain2: '20' + bb_gain20: '20' + bb_gain21: '20' + bb_gain22: '20' + bb_gain23: '20' + bb_gain24: '20' + bb_gain25: '20' + bb_gain26: '20' + bb_gain27: '20' + bb_gain28: '20' + bb_gain29: '20' + bb_gain3: '20' + bb_gain30: '20' + bb_gain31: '20' + bb_gain4: '20' + bb_gain5: '20' + bb_gain6: '20' + bb_gain7: '20' + bb_gain8: '20' + bb_gain9: '20' + bw0: '0' + bw1: '0' + bw10: '0' + bw11: '0' + bw12: '0' + bw13: '0' + bw14: '0' + bw15: '0' + bw16: '0' + bw17: '0' + bw18: '0' + bw19: '0' + bw2: '0' + bw20: '0' + bw21: '0' + bw22: '0' + bw23: '0' + bw24: '0' + bw25: '0' + bw26: '0' + bw27: '0' + bw28: '0' + bw29: '0' + bw3: '0' + bw30: '0' + bw31: '0' + bw4: '0' + bw5: '0' + bw6: '0' + bw7: '0' + bw8: '0' + bw9: '0' + clock_source0: '' + clock_source1: '' + clock_source2: '' + clock_source3: '' + clock_source4: '' + clock_source5: '' + clock_source6: '' + clock_source7: '' + comment: '' + corr0: '0' + corr1: '0' + corr10: '0' + corr11: '0' + corr12: '0' + corr13: '0' + corr14: '0' + corr15: '0' + corr16: '0' + corr17: '0' + corr18: '0' + corr19: '0' + corr2: '0' + corr20: '0' + corr21: '0' + corr22: '0' + corr23: '0' + corr24: '0' + corr25: '0' + corr26: '0' + corr27: '0' + corr28: '0' + corr29: '0' + corr3: '0' + corr30: '0' + corr31: '0' + corr4: '0' + corr5: '0' + corr6: '0' + corr7: '0' + corr8: '0' + corr9: '0' + dc_offset_mode0: '0' + dc_offset_mode1: '0' + dc_offset_mode10: '0' + dc_offset_mode11: '0' + dc_offset_mode12: '0' + dc_offset_mode13: '0' + dc_offset_mode14: '0' + dc_offset_mode15: '0' + dc_offset_mode16: '0' + dc_offset_mode17: '0' + dc_offset_mode18: '0' + dc_offset_mode19: '0' + dc_offset_mode2: '0' + dc_offset_mode20: '0' + dc_offset_mode21: '0' + dc_offset_mode22: '0' + dc_offset_mode23: '0' + dc_offset_mode24: '0' + dc_offset_mode25: '0' + dc_offset_mode26: '0' + dc_offset_mode27: '0' + dc_offset_mode28: '0' + dc_offset_mode29: '0' + dc_offset_mode3: '0' + dc_offset_mode30: '0' + dc_offset_mode31: '0' + dc_offset_mode4: '0' + dc_offset_mode5: '0' + dc_offset_mode6: '0' + dc_offset_mode7: '0' + dc_offset_mode8: '0' + dc_offset_mode9: '0' + freq0: sdr_Freq_Int + freq1: 100e6 + freq10: 100e6 + freq11: 100e6 + freq12: 100e6 + freq13: 100e6 + freq14: 100e6 + freq15: 100e6 + freq16: 100e6 + freq17: 100e6 + freq18: 100e6 + freq19: 100e6 + freq2: 100e6 + freq20: 100e6 + freq21: 100e6 + freq22: 100e6 + freq23: 100e6 + freq24: 100e6 + freq25: 100e6 + freq26: 100e6 + freq27: 100e6 + freq28: 100e6 + freq29: 100e6 + freq3: 100e6 + freq30: 100e6 + freq31: 100e6 + freq4: 100e6 + freq5: 100e6 + freq6: 100e6 + freq7: 100e6 + freq8: 100e6 + freq9: 100e6 + gain0: sdr_LNA_Gain_Int + gain1: '10' + gain10: '10' + gain11: '10' + gain12: '10' + gain13: '10' + gain14: '10' + gain15: '10' + gain16: '10' + gain17: '10' + gain18: '10' + gain19: '10' + gain2: '10' + gain20: '10' + gain21: '10' + gain22: '10' + gain23: '10' + gain24: '10' + gain25: '10' + gain26: '10' + gain27: '10' + gain28: '10' + gain29: '10' + gain3: '10' + gain30: '10' + gain31: '10' + gain4: '10' + gain5: '10' + gain6: '10' + gain7: '10' + gain8: '10' + gain9: '10' + gain_mode0: 'False' + gain_mode1: 'False' + gain_mode10: 'False' + gain_mode11: 'False' + gain_mode12: 'False' + gain_mode13: 'False' + gain_mode14: 'False' + gain_mode15: 'False' + gain_mode16: 'False' + gain_mode17: 'False' + gain_mode18: 'False' + gain_mode19: 'False' + gain_mode2: 'False' + gain_mode20: 'False' + gain_mode21: 'False' + gain_mode22: 'False' + gain_mode23: 'False' + gain_mode24: 'False' + gain_mode25: 'False' + gain_mode26: 'False' + gain_mode27: 'False' + gain_mode28: 'False' + gain_mode29: 'False' + gain_mode3: 'False' + gain_mode30: 'False' + gain_mode31: 'False' + gain_mode4: 'False' + gain_mode5: 'False' + gain_mode6: 'False' + gain_mode7: 'False' + gain_mode8: 'False' + gain_mode9: 'False' + if_gain0: sdr_IF_Gain_Int + if_gain1: '20' + if_gain10: '20' + if_gain11: '20' + if_gain12: '20' + if_gain13: '20' + if_gain14: '20' + if_gain15: '20' + if_gain16: '20' + if_gain17: '20' + if_gain18: '20' + if_gain19: '20' + if_gain2: '20' + if_gain20: '20' + if_gain21: '20' + if_gain22: '20' + if_gain23: '20' + if_gain24: '20' + if_gain25: '20' + if_gain26: '20' + if_gain27: '20' + if_gain28: '20' + if_gain29: '20' + if_gain3: '20' + if_gain30: '20' + if_gain31: '20' + if_gain4: '20' + if_gain5: '20' + if_gain6: '20' + if_gain7: '20' + if_gain8: '20' + if_gain9: '20' + iq_balance_mode0: '0' + iq_balance_mode1: '0' + iq_balance_mode10: '0' + iq_balance_mode11: '0' + iq_balance_mode12: '0' + iq_balance_mode13: '0' + iq_balance_mode14: '0' + iq_balance_mode15: '0' + iq_balance_mode16: '0' + iq_balance_mode17: '0' + iq_balance_mode18: '0' + iq_balance_mode19: '0' + iq_balance_mode2: '0' + iq_balance_mode20: '0' + iq_balance_mode21: '0' + iq_balance_mode22: '0' + iq_balance_mode23: '0' + iq_balance_mode24: '0' + iq_balance_mode25: '0' + iq_balance_mode26: '0' + iq_balance_mode27: '0' + iq_balance_mode28: '0' + iq_balance_mode29: '0' + iq_balance_mode3: '0' + iq_balance_mode30: '0' + iq_balance_mode31: '0' + iq_balance_mode4: '0' + iq_balance_mode5: '0' + iq_balance_mode6: '0' + iq_balance_mode7: '0' + iq_balance_mode8: '0' + iq_balance_mode9: '0' + maxoutbuf: '0' + minoutbuf: '0' + nchan: '1' + num_mboards: '1' + sample_rate: sampRate + sync: sync + time_source0: '' + time_source1: '' + time_source2: '' + time_source3: '' + time_source4: '' + time_source5: '' + time_source6: '' + time_source7: '' + type: fc32 + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [456, 580.0] + rotation: 0 + state: enabled +- name: satellites_afsk_demodulator_0 + id: satellites_afsk_demodulator + parameters: + af_carrier: modulation_AFSK_Audio_Carrier_Freq_Int + affinity: '' + alias: '' + baudrate: modulation_Baud_Rate_Int + comment: '' + deviation: modulation_AFSK_Deviation_Int + iq: 'True' + maxoutbuf: '0' + minoutbuf: '0' + options: '""' + samp_rate: sampRate / 10 + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [680, 1308.0] + rotation: 0 + state: enabled +- name: satellites_ao40_fec_deframer_0 + id: satellites_ao40_fec_deframer + parameters: + affinity: '' + alias: '' + comment: '' + crc: deframer_CRC16_Bool + maxoutbuf: '0' + minoutbuf: '0' + options: '""' + short_frames: deframer_Short_Frames_Bool + threshold: deframer_Syncword_Threshold_Int + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [1304, 1140.0] + rotation: 0 + state: enabled +- name: satellites_ax100_deframer_0 + id: satellites_ax100_deframer + parameters: + affinity: '' + alias: '' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + mode: '"RS"' + options: '""' + scrambler: '"CCSDS"' + threshold: deframer_Syncword_Threshold_Int + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [1304, 1396.0] + rotation: 0 + state: enabled +- name: satellites_ax100_deframer_0_0 + id: satellites_ax100_deframer + parameters: + affinity: '' + alias: '' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + mode: '"ASM"' + options: '""' + scrambler: '"CCSDS"' + threshold: deframer_Syncword_Threshold_Int + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [1304, 1468.0] + rotation: 0 + state: enabled +- name: satellites_ax25_deframer_1 + id: satellites_ax25_deframer + parameters: + affinity: '' + alias: '' + comment: '' + g3ruh_scrambler: deframer_G3RUH_Bool + maxoutbuf: '0' + minoutbuf: '0' + options: '""' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [1304, 1284.0] + rotation: 0 + state: enabled +- name: satellites_bpsk_demodulator_0 + id: satellites_bpsk_demodulator + parameters: + affinity: '' + alias: '' + baudrate: modulation_Baud_Rate_Int + comment: '' + differential: modulation_BPSK_Differential_Bool + f_offset: freqOffset + iq: 'True' + manchester: modulation_BPSK_Manchester_Bool + maxoutbuf: '0' + minoutbuf: '0' + options: '""' + samp_rate: sampRate / 10 + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [648, 1196.0] + rotation: 0 + state: enabled +- name: satellites_fossasat_deframer_0 + id: satellites_fossasat_deframer + parameters: + affinity: '' + alias: '' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + options: '""' + threshold: deframer_Syncword_Threshold_Int + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [1304, 1340.0] + rotation: 0 + state: enabled +- name: satellites_fsk_demodulator_0 + id: satellites_fsk_demodulator + parameters: + affinity: '' + alias: '' + baudrate: modulation_Baud_Rate_Int + comment: '' + iq: 'True' + maxoutbuf: '0' + minoutbuf: '0' + options: '""' + samp_rate: sampRate / 10 + subaudio: modulation_FSK_Sub_Audio_Bool + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [688, 1404.0] + rotation: 0 + state: enabled +- name: satellites_u482c_deframer_0 + id: satellites_u482c_deframer + parameters: + affinity: '' + alias: '' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + options: '""' + threshold: deframer_Syncword_Threshold_Int + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [1304, 1228.0] + rotation: 0 + state: enabled +- name: virtual_sink_0 + id: virtual_sink + parameters: + alias: '' + comment: '' + stream_id: bpskRaw + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [2088, 612.0] + rotation: 0 + state: enabled +- name: virtual_sink_1 + id: virtual_sink + parameters: + alias: '' + comment: '' + stream_id: afskRaw + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [2088, 668.0] + rotation: 0 + state: enabled +- name: virtual_sink_2 + id: virtual_sink + parameters: + alias: '' + comment: '' + stream_id: fskRaw + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [2088, 724.0] + rotation: 0 + state: enabled +- name: virtual_sink_3 + id: virtual_sink + parameters: + alias: '' + comment: '' + stream_id: debug + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [1656, 1428.0] + rotation: 0 + state: enabled +- name: virtual_sink_6 + id: virtual_sink + parameters: + alias: '' + comment: '' + stream_id: analogFM + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [2088, 780.0] + rotation: 0 + state: true +- name: virtual_source_0 + id: virtual_source + parameters: + alias: '' + comment: '' + stream_id: bpskRaw + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [440, 1228.0] + rotation: 0 + state: enabled +- name: virtual_source_1 + id: virtual_source + parameters: + alias: '' + comment: '' + stream_id: afskRaw + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [472, 1332.0] + rotation: 0 + state: enabled +- name: virtual_source_2 + id: virtual_source + parameters: + alias: '' + comment: '' + stream_id: fskRaw + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [464, 1420.0] + rotation: 0 + state: enabled +- name: virtual_source_5 + id: virtual_source + parameters: + alias: '' + comment: '' + stream_id: debug + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [2104, 1012.0] + rotation: 0 + state: enabled +- name: virtual_source_6 + id: virtual_source + parameters: + alias: '' + comment: '' + stream_id: analogFM + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [432, 1492.0] + rotation: 0 + state: true +- name: xmlrpc_server_0 + id: xmlrpc_server + parameters: + addr: localhost + alias: '' + comment: 'Doppler compensation + + + Receives an updated frequency + + Update from GSC through XMLRPC' + port: '7777' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [192, 76.0] + rotation: 0 + state: enabled + +connections: +- [analog_fm_deemph_0, '0', blocks_wavfile_sink_0, '0'] +- [analog_wfm_rcv_0, '0', blocks_selector_2, '3'] +- [blocks_float_to_complex_0, '0', blocks_selector_1, '1'] +- [blocks_null_source_1, '0', blocks_float_to_complex_0, '1'] +- [blocks_pdu_to_tagged_stream_0, '0', blocks_file_sink_0, '0'] +- [blocks_pdu_to_tagged_stream_0, '0', blocks_udp_sink_0, '0'] +- [blocks_selector_0, '0', virtual_sink_0, '0'] +- [blocks_selector_0, '1', virtual_sink_1, '0'] +- [blocks_selector_0, '2', virtual_sink_2, '0'] +- [blocks_selector_0, '3', virtual_sink_6, '0'] +- [blocks_selector_1, '0', blocks_selector_0, '0'] +- [blocks_selector_2, '0', satellites_ao40_fec_deframer_0, '0'] +- [blocks_selector_2, '1', satellites_u482c_deframer_0, '0'] +- [blocks_selector_2, '2', satellites_ax25_deframer_1, '0'] +- [blocks_selector_2, '3', satellites_fossasat_deframer_0, '0'] +- [blocks_selector_2, '4', satellites_ax100_deframer_0, '0'] +- [blocks_selector_2, '5', satellites_ax100_deframer_0_0, '0'] +- [blocks_selector_2, '6', analog_fm_deemph_0, '0'] +- [blocks_selector_3, '0', low_pass_filter_1, '0'] +- [blocks_wavfile_source_0, '0', blocks_float_to_complex_0, '0'] +- [dc_blocker_xx_0, '0', blocks_selector_3, '1'] +- [low_pass_filter_1, '0', blocks_file_sink_1, '0'] +- [low_pass_filter_1, '0', blocks_selector_1, '0'] +- [osmosdr_source_0, '0', blocks_selector_3, '0'] +- [osmosdr_source_0, '0', dc_blocker_xx_0, '0'] +- [satellites_afsk_demodulator_0, '0', blocks_selector_2, '1'] +- [satellites_ao40_fec_deframer_0, out, blocks_pdu_to_tagged_stream_0, pdus] +- [satellites_ao40_fec_deframer_0, out, virtual_sink_3, '0'] +- [satellites_ax100_deframer_0, out, blocks_pdu_to_tagged_stream_0, pdus] +- [satellites_ax100_deframer_0, out, virtual_sink_3, '0'] +- [satellites_ax100_deframer_0_0, out, blocks_pdu_to_tagged_stream_0, pdus] +- [satellites_ax100_deframer_0_0, out, virtual_sink_3, '0'] +- [satellites_ax25_deframer_1, out, blocks_pdu_to_tagged_stream_0, pdus] +- [satellites_ax25_deframer_1, out, virtual_sink_3, '0'] +- [satellites_bpsk_demodulator_0, '0', blocks_selector_2, '0'] +- [satellites_fossasat_deframer_0, out, blocks_pdu_to_tagged_stream_0, pdus] +- [satellites_fossasat_deframer_0, out, virtual_sink_3, '0'] +- [satellites_fsk_demodulator_0, '0', blocks_selector_2, '2'] +- [satellites_u482c_deframer_0, out, blocks_pdu_to_tagged_stream_0, pdus] +- [satellites_u482c_deframer_0, out, virtual_sink_3, '0'] +- [virtual_source_0, '0', satellites_bpsk_demodulator_0, '0'] +- [virtual_source_1, '0', satellites_afsk_demodulator_0, '0'] +- [virtual_source_2, '0', satellites_fsk_demodulator_0, '0'] +- [virtual_source_5, '0', blocks_message_debug_0, print_pdu] +- [virtual_source_6, '0', analog_wfm_rcv_0, '0'] + +metadata: + file_format: 1 diff --git a/grc/downlink-principal.pdf b/grc/downlink-principal.pdf new file mode 100644 index 0000000..286680c Binary files /dev/null and b/grc/downlink-principal.pdf differ diff --git a/grc/downlink-principal.py b/grc/downlink-principal.py new file mode 100755 index 0000000..0411a68 --- /dev/null +++ b/grc/downlink-principal.py @@ -0,0 +1,524 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# +# SPDX-License-Identifier: GPL-3.0 +# +# GNU Radio Python Flow Graph +# Title: Leanspace + GNU Radio +# GNU Radio version: v3.8.3.1-2-g18f86220 + +from gnuradio import analog +from gnuradio import blocks +from gnuradio import filter +from gnuradio.filter import firdes +from gnuradio import gr +import sys +import signal +from argparse import ArgumentParser +from gnuradio.eng_arg import eng_float, intx +from gnuradio import eng_notation +import osmosdr +import time +import satellites.components.deframers +import satellites.components.demodulators +try: + from xmlrpc.server import SimpleXMLRPCServer +except ImportError: + from SimpleXMLRPCServer import SimpleXMLRPCServer +import threading +try: + import configparser +except ImportError: + import ConfigParser as configparser +try: + import configparser +except ImportError: + import ConfigParser as configparser +try: + import configparser +except ImportError: + import ConfigParser as configparser +try: + import configparser +except ImportError: + import ConfigParser as configparser +try: + import configparser +except ImportError: + import ConfigParser as configparser +try: + import configparser +except ImportError: + import ConfigParser as configparser +try: + import configparser +except ImportError: + import ConfigParser as configparser +try: + import configparser +except ImportError: + import ConfigParser as configparser +try: + import configparser +except ImportError: + import ConfigParser as configparser +try: + import configparser +except ImportError: + import ConfigParser as configparser +try: + import configparser +except ImportError: + import ConfigParser as configparser +try: + import configparser +except ImportError: + import ConfigParser as configparser +try: + import configparser +except ImportError: + import ConfigParser as configparser +try: + import configparser +except ImportError: + import ConfigParser as configparser +try: + import configparser +except ImportError: + import ConfigParser as configparser +try: + import configparser +except ImportError: + import ConfigParser as configparser +try: + import configparser +except ImportError: + import ConfigParser as configparser +try: + import configparser +except ImportError: + import ConfigParser as configparser +try: + import configparser +except ImportError: + import ConfigParser as configparser +try: + import configparser +except ImportError: + import ConfigParser as configparser + + +class fmDemod(gr.top_block): + + def __init__(self): + gr.top_block.__init__(self, "Leanspace + GNU Radio") + + ################################################## + # Variables + ################################################## + self.sampRate = sampRate = 480000 + self._main_Result_File_Prefix_Str_config = configparser.ConfigParser() + self._main_Result_File_Prefix_Str_config.read('/home/stanislavb/sdr_prototypes/master/default') + try: main_Result_File_Prefix_Str = self._main_Result_File_Prefix_Str_config.get('main', 'main_Result_File_Prefix') + except: main_Result_File_Prefix_Str = 'ERROR_PREFIX' + self.main_Result_File_Prefix_Str = main_Result_File_Prefix_Str + self._sdr_LNA_Gain_Int_config = configparser.ConfigParser() + self._sdr_LNA_Gain_Int_config.read('/home/stanislavb/sdr_prototypes/master/default') + try: sdr_LNA_Gain_Int = self._sdr_LNA_Gain_Int_config.getint('sdr', 'sdr_LNA_Gain') + except: sdr_LNA_Gain_Int = 14 + self.sdr_LNA_Gain_Int = sdr_LNA_Gain_Int + self._sdr_IF_Gain_Int_config = configparser.ConfigParser() + self._sdr_IF_Gain_Int_config.read('/home/stanislavb/sdr_prototypes/master/default') + try: sdr_IF_Gain_Int = self._sdr_IF_Gain_Int_config.getint('sdr', 'sdr_IF_Gain') + except: sdr_IF_Gain_Int = 40 + self.sdr_IF_Gain_Int = sdr_IF_Gain_Int + self._sdr_Freq_Int_config = configparser.ConfigParser() + self._sdr_Freq_Int_config.read('/home/stanislavb/sdr_prototypes/master/default') + try: sdr_Freq_Int = self._sdr_Freq_Int_config.getint('sdr', 'sdr_Freq') + except: sdr_Freq_Int = 145935000 + self.sdr_Freq_Int = sdr_Freq_Int + self._sdr_BB_Gain_Int_config = configparser.ConfigParser() + self._sdr_BB_Gain_Int_config.read('/home/stanislavb/sdr_prototypes/master/default') + try: sdr_BB_Gain_Int = self._sdr_BB_Gain_Int_config.getint('sdr', 'sdr_BB_Gain') + except: sdr_BB_Gain_Int = 40 + self.sdr_BB_Gain_Int = sdr_BB_Gain_Int + self._modulation_Type_Int_config = configparser.ConfigParser() + self._modulation_Type_Int_config.read('/home/stanislavb/sdr_prototypes/master/default') + try: modulation_Type_Int = self._modulation_Type_Int_config.getint('modulation', 'modulation_Type') + except: modulation_Type_Int = 0 + self.modulation_Type_Int = modulation_Type_Int + self._modulation_FSK_Sub_Audio_Bool_config = configparser.ConfigParser() + self._modulation_FSK_Sub_Audio_Bool_config.read('/home/stanislavb/sdr_prototypes/master/default') + try: modulation_FSK_Sub_Audio_Bool = self._modulation_FSK_Sub_Audio_Bool_config.getboolean('modulation', 'modulation_FSK_Sub_Audio') + except: modulation_FSK_Sub_Audio_Bool = False + self.modulation_FSK_Sub_Audio_Bool = modulation_FSK_Sub_Audio_Bool + self._modulation_Deframer_Type_Int_config = configparser.ConfigParser() + self._modulation_Deframer_Type_Int_config.read('/home/stanislavb/sdr_prototypes/master/default') + try: modulation_Deframer_Type_Int = self._modulation_Deframer_Type_Int_config.getint('modulation', 'modulation_Deframer_Type') + except: modulation_Deframer_Type_Int = 0 + self.modulation_Deframer_Type_Int = modulation_Deframer_Type_Int + self._modulation_Baud_Rate_Int_config = configparser.ConfigParser() + self._modulation_Baud_Rate_Int_config.read('/home/stanislavb/sdr_prototypes/master/default') + try: modulation_Baud_Rate_Int = self._modulation_Baud_Rate_Int_config.getint('modulation', 'modulation_Baud_Rate') + except: modulation_Baud_Rate_Int = 9600 + self.modulation_Baud_Rate_Int = modulation_Baud_Rate_Int + self._modulation_BPSK_Manchester_Bool_config = configparser.ConfigParser() + self._modulation_BPSK_Manchester_Bool_config.read('/home/stanislavb/sdr_prototypes/master/default') + try: modulation_BPSK_Manchester_Bool = self._modulation_BPSK_Manchester_Bool_config.getboolean('modulation', 'modulation_BPSK_Manchester') + except: modulation_BPSK_Manchester_Bool = False + self.modulation_BPSK_Manchester_Bool = modulation_BPSK_Manchester_Bool + self._modulation_BPSK_Differential_Bool_config = configparser.ConfigParser() + self._modulation_BPSK_Differential_Bool_config.read('/home/stanislavb/sdr_prototypes/master/default') + try: modulation_BPSK_Differential_Bool = self._modulation_BPSK_Differential_Bool_config.getboolean('modulation', 'modulation_BPSK_Differential') + except: modulation_BPSK_Differential_Bool = True + self.modulation_BPSK_Differential_Bool = modulation_BPSK_Differential_Bool + self._modulation_AFSK_Deviation_Int_config = configparser.ConfigParser() + self._modulation_AFSK_Deviation_Int_config.read('/home/stanislavb/sdr_prototypes/master/default') + try: modulation_AFSK_Deviation_Int = self._modulation_AFSK_Deviation_Int_config.getint('modulation', 'modulation_AFSK_Deviation') + except: modulation_AFSK_Deviation_Int = -1200 + self.modulation_AFSK_Deviation_Int = modulation_AFSK_Deviation_Int + self._modulation_AFSK_Audio_Carrier_Freq_Int_config = configparser.ConfigParser() + self._modulation_AFSK_Audio_Carrier_Freq_Int_config.read('/home/stanislavb/sdr_prototypes/master/default') + try: modulation_AFSK_Audio_Carrier_Freq_Int = self._modulation_AFSK_Audio_Carrier_Freq_Int_config.getint('modulation', 'modulation_AFSK_Audio_Carrier_Freq') + except: modulation_AFSK_Audio_Carrier_Freq_Int = 3600 + self.modulation_AFSK_Audio_Carrier_Freq_Int = modulation_AFSK_Audio_Carrier_Freq_Int + self._main_Network_Stream_Port_Int_config = configparser.ConfigParser() + self._main_Network_Stream_Port_Int_config.read('/home/stanislavb/sdr_prototypes/master/default') + try: main_Network_Stream_Port_Int = self._main_Network_Stream_Port_Int_config.getint('main', 'main_Network_Stream_Port') + except: main_Network_Stream_Port_Int = 8080 + self.main_Network_Stream_Port_Int = main_Network_Stream_Port_Int + self._main_Network_Stream_Address_Str_config = configparser.ConfigParser() + self._main_Network_Stream_Address_Str_config.read('/home/stanislavb/sdr_prototypes/master/default') + try: main_Network_Stream_Address_Str = self._main_Network_Stream_Address_Str_config.get('main', 'main_Network_Stream_Address') + except: main_Network_Stream_Address_Str = '127.0.0.1' + self.main_Network_Stream_Address_Str = main_Network_Stream_Address_Str + self._main_LPF_Cutoff_Freq_Int_config = configparser.ConfigParser() + self._main_LPF_Cutoff_Freq_Int_config.read('/home/stanislavb/sdr_prototypes/master/default') + try: main_LPF_Cutoff_Freq_Int = self._main_LPF_Cutoff_Freq_Int_config.getint('main', 'main_LPF_Cutoff_Freq') + except: main_LPF_Cutoff_Freq_Int = sampRate - 10000 + self.main_LPF_Cutoff_Freq_Int = main_LPF_Cutoff_Freq_Int + self.freqOffset = freqOffset = 11000 + self.fileNameRes = fileNameRes = main_Result_File_Prefix_Str + ".dat" + self.fileNameRaw = fileNameRaw = main_Result_File_Prefix_Str + ".raw" + self._deframer_Syncword_Threshold_Int_config = configparser.ConfigParser() + self._deframer_Syncword_Threshold_Int_config.read('/home/stanislavb/sdr_prototypes/master/default') + try: deframer_Syncword_Threshold_Int = self._deframer_Syncword_Threshold_Int_config.getint('deframer', 'deframer_Syncword_Threshold') + except: deframer_Syncword_Threshold_Int = 4 + self.deframer_Syncword_Threshold_Int = deframer_Syncword_Threshold_Int + self._deframer_Short_Frames_Bool_config = configparser.ConfigParser() + self._deframer_Short_Frames_Bool_config.read('/home/stanislavb/sdr_prototypes/master/default') + try: deframer_Short_Frames_Bool = self._deframer_Short_Frames_Bool_config.getboolean('deframer', 'deframer_Short_Frames') + except: deframer_Short_Frames_Bool = False + self.deframer_Short_Frames_Bool = deframer_Short_Frames_Bool + self._deframer_G3RUH_Bool_config = configparser.ConfigParser() + self._deframer_G3RUH_Bool_config.read('/home/stanislavb/sdr_prototypes/master/default') + try: deframer_G3RUH_Bool = self._deframer_G3RUH_Bool_config.getboolean('deframer', 'deframer_G3RUH') + except: deframer_G3RUH_Bool = False + self.deframer_G3RUH_Bool = deframer_G3RUH_Bool + self._deframer_CRC16_Bool_config = configparser.ConfigParser() + self._deframer_CRC16_Bool_config.read('/home/stanislavb/sdr_prototypes/master/default') + try: deframer_CRC16_Bool = self._deframer_CRC16_Bool_config.getboolean('deframer', 'deframer_CRC16') + except: deframer_CRC16_Bool = False + self.deframer_CRC16_Bool = deframer_CRC16_Bool + + ################################################## + # Blocks + ################################################## + self.xmlrpc_server_0 = SimpleXMLRPCServer(('localhost', 7777), allow_none=True) + self.xmlrpc_server_0.register_instance(self) + self.xmlrpc_server_0_thread = threading.Thread(target=self.xmlrpc_server_0.serve_forever) + self.xmlrpc_server_0_thread.daemon = True + self.xmlrpc_server_0_thread.start() + self.satellites_u482c_deframer_0 = satellites.components.deframers.u482c_deframer(syncword_threshold = deframer_Syncword_Threshold_Int, options="") + self.satellites_fsk_demodulator_0 = satellites.components.demodulators.fsk_demodulator(baudrate = modulation_Baud_Rate_Int, samp_rate = sampRate / 10, iq = True, subaudio = modulation_FSK_Sub_Audio_Bool, options="") + self.satellites_fossasat_deframer_0 = satellites.components.deframers.fossasat_deframer(syncword_threshold = deframer_Syncword_Threshold_Int, options="") + self.satellites_bpsk_demodulator_0 = satellites.components.demodulators.bpsk_demodulator(baudrate = modulation_Baud_Rate_Int, samp_rate = sampRate / 10, f_offset = freqOffset, differential = modulation_BPSK_Differential_Bool, manchester = modulation_BPSK_Manchester_Bool, iq = True, options="") + self.satellites_ax25_deframer_1 = satellites.components.deframers.ax25_deframer(g3ruh_scrambler=deframer_G3RUH_Bool, options="") + self.satellites_ax100_deframer_0_0 = satellites.components.deframers.ax100_deframer(mode = "ASM", scrambler = "CCSDS", syncword_threshold = deframer_Syncword_Threshold_Int, options="") + self.satellites_ax100_deframer_0 = satellites.components.deframers.ax100_deframer(mode = "RS", scrambler = "CCSDS", syncword_threshold = deframer_Syncword_Threshold_Int, options="") + self.satellites_ao40_fec_deframer_0 = satellites.components.deframers.ao40_fec_deframer(syncword_threshold = deframer_Syncword_Threshold_Int, short_frames = deframer_Short_Frames_Bool, crc = deframer_CRC16_Bool, options="") + self.satellites_afsk_demodulator_0 = satellites.components.demodulators.afsk_demodulator(baudrate = modulation_Baud_Rate_Int, samp_rate = sampRate / 10, iq = True, af_carrier = modulation_AFSK_Audio_Carrier_Freq_Int, deviation = modulation_AFSK_Deviation_Int, options="") + self.osmosdr_source_0 = osmosdr.source( + args="numchan=" + str(1) + " " + "" + ) + self.osmosdr_source_0.set_time_unknown_pps(osmosdr.time_spec_t()) + self.osmosdr_source_0.set_sample_rate(sampRate) + self.osmosdr_source_0.set_center_freq(sdr_Freq_Int, 0) + self.osmosdr_source_0.set_freq_corr(0, 0) + self.osmosdr_source_0.set_dc_offset_mode(0, 0) + self.osmosdr_source_0.set_iq_balance_mode(0, 0) + self.osmosdr_source_0.set_gain_mode(False, 0) + self.osmosdr_source_0.set_gain(sdr_LNA_Gain_Int, 0) + self.osmosdr_source_0.set_if_gain(sdr_IF_Gain_Int, 0) + self.osmosdr_source_0.set_bb_gain(sdr_BB_Gain_Int, 0) + self.osmosdr_source_0.set_antenna('', 0) + self.osmosdr_source_0.set_bandwidth(0, 0) + self.low_pass_filter_1 = filter.fir_filter_ccf( + 10, + firdes.low_pass( + 1, + sampRate, + main_LPF_Cutoff_Freq_Int, + 1000, + firdes.WIN_HAMMING, + 6.76)) + self.dc_blocker_xx_0 = filter.dc_blocker_cc(32, True) + self.blocks_wavfile_source_0 = blocks.wavfile_source('/home/stanislavb/satellite-recordings/gomx_1.wav', True) + self.blocks_wavfile_sink_0 = blocks.wavfile_sink(fileNameRes, 1, int(sampRate / 10), 8) + self.blocks_udp_sink_0 = blocks.udp_sink(gr.sizeof_char*1, main_Network_Stream_Address_Str, main_Network_Stream_Port_Int, 1472, True) + self.blocks_selector_3 = blocks.selector(gr.sizeof_gr_complex*1,0,0) + self.blocks_selector_3.set_enabled(True) + self.blocks_selector_2 = blocks.selector(gr.sizeof_float*1,modulation_Type_Int,modulation_Deframer_Type_Int) + self.blocks_selector_2.set_enabled(True) + self.blocks_selector_1 = blocks.selector(gr.sizeof_gr_complex*1,0,0) + self.blocks_selector_1.set_enabled(True) + self.blocks_selector_0 = blocks.selector(gr.sizeof_gr_complex*1,0,modulation_Type_Int) + self.blocks_selector_0.set_enabled(True) + self.blocks_pdu_to_tagged_stream_0 = blocks.pdu_to_tagged_stream(blocks.byte_t, 'data') + self.blocks_null_source_1 = blocks.null_source(gr.sizeof_float*1) + self.blocks_message_debug_0 = blocks.message_debug() + self.blocks_float_to_complex_0 = blocks.float_to_complex(1) + self.blocks_file_sink_1 = blocks.file_sink(gr.sizeof_gr_complex*1, fileNameRaw, False) + self.blocks_file_sink_1.set_unbuffered(False) + self.blocks_file_sink_0 = blocks.file_sink(gr.sizeof_char*1, fileNameRes, False) + self.blocks_file_sink_0.set_unbuffered(False) + self.analog_wfm_rcv_0 = analog.wfm_rcv( + quad_rate=sampRate / 10, + audio_decimation=1, + ) + self.analog_fm_deemph_0 = analog.fm_deemph(fs=sampRate / 10, tau=75e-6) + + + ################################################## + # Connections + ################################################## + self.msg_connect((self.satellites_ao40_fec_deframer_0, 'out'), (self.blocks_message_debug_0, 'print_pdu')) + self.msg_connect((self.satellites_ao40_fec_deframer_0, 'out'), (self.blocks_pdu_to_tagged_stream_0, 'pdus')) + self.msg_connect((self.satellites_ax100_deframer_0, 'out'), (self.blocks_message_debug_0, 'print_pdu')) + self.msg_connect((self.satellites_ax100_deframer_0, 'out'), (self.blocks_pdu_to_tagged_stream_0, 'pdus')) + self.msg_connect((self.satellites_ax100_deframer_0_0, 'out'), (self.blocks_message_debug_0, 'print_pdu')) + self.msg_connect((self.satellites_ax100_deframer_0_0, 'out'), (self.blocks_pdu_to_tagged_stream_0, 'pdus')) + self.msg_connect((self.satellites_ax25_deframer_1, 'out'), (self.blocks_message_debug_0, 'print_pdu')) + self.msg_connect((self.satellites_ax25_deframer_1, 'out'), (self.blocks_pdu_to_tagged_stream_0, 'pdus')) + self.msg_connect((self.satellites_fossasat_deframer_0, 'out'), (self.blocks_message_debug_0, 'print_pdu')) + self.msg_connect((self.satellites_fossasat_deframer_0, 'out'), (self.blocks_pdu_to_tagged_stream_0, 'pdus')) + self.msg_connect((self.satellites_u482c_deframer_0, 'out'), (self.blocks_message_debug_0, 'print_pdu')) + self.msg_connect((self.satellites_u482c_deframer_0, 'out'), (self.blocks_pdu_to_tagged_stream_0, 'pdus')) + self.connect((self.analog_fm_deemph_0, 0), (self.blocks_wavfile_sink_0, 0)) + self.connect((self.analog_wfm_rcv_0, 0), (self.blocks_selector_2, 3)) + self.connect((self.blocks_float_to_complex_0, 0), (self.blocks_selector_1, 1)) + self.connect((self.blocks_null_source_1, 0), (self.blocks_float_to_complex_0, 1)) + self.connect((self.blocks_pdu_to_tagged_stream_0, 0), (self.blocks_file_sink_0, 0)) + self.connect((self.blocks_pdu_to_tagged_stream_0, 0), (self.blocks_udp_sink_0, 0)) + self.connect((self.blocks_selector_0, 3), (self.analog_wfm_rcv_0, 0)) + self.connect((self.blocks_selector_0, 1), (self.satellites_afsk_demodulator_0, 0)) + self.connect((self.blocks_selector_0, 0), (self.satellites_bpsk_demodulator_0, 0)) + self.connect((self.blocks_selector_0, 2), (self.satellites_fsk_demodulator_0, 0)) + self.connect((self.blocks_selector_1, 0), (self.blocks_selector_0, 0)) + self.connect((self.blocks_selector_2, 6), (self.analog_fm_deemph_0, 0)) + self.connect((self.blocks_selector_2, 0), (self.satellites_ao40_fec_deframer_0, 0)) + self.connect((self.blocks_selector_2, 4), (self.satellites_ax100_deframer_0, 0)) + self.connect((self.blocks_selector_2, 5), (self.satellites_ax100_deframer_0_0, 0)) + self.connect((self.blocks_selector_2, 2), (self.satellites_ax25_deframer_1, 0)) + self.connect((self.blocks_selector_2, 3), (self.satellites_fossasat_deframer_0, 0)) + self.connect((self.blocks_selector_2, 1), (self.satellites_u482c_deframer_0, 0)) + self.connect((self.blocks_selector_3, 0), (self.low_pass_filter_1, 0)) + self.connect((self.blocks_wavfile_source_0, 0), (self.blocks_float_to_complex_0, 0)) + self.connect((self.dc_blocker_xx_0, 0), (self.blocks_selector_3, 1)) + self.connect((self.low_pass_filter_1, 0), (self.blocks_file_sink_1, 0)) + self.connect((self.low_pass_filter_1, 0), (self.blocks_selector_1, 0)) + self.connect((self.osmosdr_source_0, 0), (self.blocks_selector_3, 0)) + self.connect((self.osmosdr_source_0, 0), (self.dc_blocker_xx_0, 0)) + self.connect((self.satellites_afsk_demodulator_0, 0), (self.blocks_selector_2, 1)) + self.connect((self.satellites_bpsk_demodulator_0, 0), (self.blocks_selector_2, 0)) + self.connect((self.satellites_fsk_demodulator_0, 0), (self.blocks_selector_2, 2)) + + + def get_sampRate(self): + return self.sampRate + + def set_sampRate(self, sampRate): + self.sampRate = sampRate + self.set_main_LPF_Cutoff_Freq_Int(self.sampRate - 10000) + self.low_pass_filter_1.set_taps(firdes.low_pass(1, self.sampRate, self.main_LPF_Cutoff_Freq_Int, 1000, firdes.WIN_HAMMING, 6.76)) + self.osmosdr_source_0.set_sample_rate(self.sampRate) + + def get_main_Result_File_Prefix_Str(self): + return self.main_Result_File_Prefix_Str + + def set_main_Result_File_Prefix_Str(self, main_Result_File_Prefix_Str): + self.main_Result_File_Prefix_Str = main_Result_File_Prefix_Str + self.set_fileNameRaw(self.main_Result_File_Prefix_Str + ".raw") + self.set_fileNameRes(self.main_Result_File_Prefix_Str + ".dat") + + def get_sdr_LNA_Gain_Int(self): + return self.sdr_LNA_Gain_Int + + def set_sdr_LNA_Gain_Int(self, sdr_LNA_Gain_Int): + self.sdr_LNA_Gain_Int = sdr_LNA_Gain_Int + self.osmosdr_source_0.set_gain(self.sdr_LNA_Gain_Int, 0) + + def get_sdr_IF_Gain_Int(self): + return self.sdr_IF_Gain_Int + + def set_sdr_IF_Gain_Int(self, sdr_IF_Gain_Int): + self.sdr_IF_Gain_Int = sdr_IF_Gain_Int + self.osmosdr_source_0.set_if_gain(self.sdr_IF_Gain_Int, 0) + + def get_sdr_Freq_Int(self): + return self.sdr_Freq_Int + + def set_sdr_Freq_Int(self, sdr_Freq_Int): + self.sdr_Freq_Int = sdr_Freq_Int + self.osmosdr_source_0.set_center_freq(self.sdr_Freq_Int, 0) + + def get_sdr_BB_Gain_Int(self): + return self.sdr_BB_Gain_Int + + def set_sdr_BB_Gain_Int(self, sdr_BB_Gain_Int): + self.sdr_BB_Gain_Int = sdr_BB_Gain_Int + self.osmosdr_source_0.set_bb_gain(self.sdr_BB_Gain_Int, 0) + + def get_modulation_Type_Int(self): + return self.modulation_Type_Int + + def set_modulation_Type_Int(self, modulation_Type_Int): + self.modulation_Type_Int = modulation_Type_Int + self.blocks_selector_0.set_output_index(self.modulation_Type_Int) + self.blocks_selector_2.set_input_index(self.modulation_Type_Int) + + def get_modulation_FSK_Sub_Audio_Bool(self): + return self.modulation_FSK_Sub_Audio_Bool + + def set_modulation_FSK_Sub_Audio_Bool(self, modulation_FSK_Sub_Audio_Bool): + self.modulation_FSK_Sub_Audio_Bool = modulation_FSK_Sub_Audio_Bool + + def get_modulation_Deframer_Type_Int(self): + return self.modulation_Deframer_Type_Int + + def set_modulation_Deframer_Type_Int(self, modulation_Deframer_Type_Int): + self.modulation_Deframer_Type_Int = modulation_Deframer_Type_Int + self.blocks_selector_2.set_output_index(self.modulation_Deframer_Type_Int) + + def get_modulation_Baud_Rate_Int(self): + return self.modulation_Baud_Rate_Int + + def set_modulation_Baud_Rate_Int(self, modulation_Baud_Rate_Int): + self.modulation_Baud_Rate_Int = modulation_Baud_Rate_Int + + def get_modulation_BPSK_Manchester_Bool(self): + return self.modulation_BPSK_Manchester_Bool + + def set_modulation_BPSK_Manchester_Bool(self, modulation_BPSK_Manchester_Bool): + self.modulation_BPSK_Manchester_Bool = modulation_BPSK_Manchester_Bool + + def get_modulation_BPSK_Differential_Bool(self): + return self.modulation_BPSK_Differential_Bool + + def set_modulation_BPSK_Differential_Bool(self, modulation_BPSK_Differential_Bool): + self.modulation_BPSK_Differential_Bool = modulation_BPSK_Differential_Bool + + def get_modulation_AFSK_Deviation_Int(self): + return self.modulation_AFSK_Deviation_Int + + def set_modulation_AFSK_Deviation_Int(self, modulation_AFSK_Deviation_Int): + self.modulation_AFSK_Deviation_Int = modulation_AFSK_Deviation_Int + + def get_modulation_AFSK_Audio_Carrier_Freq_Int(self): + return self.modulation_AFSK_Audio_Carrier_Freq_Int + + def set_modulation_AFSK_Audio_Carrier_Freq_Int(self, modulation_AFSK_Audio_Carrier_Freq_Int): + self.modulation_AFSK_Audio_Carrier_Freq_Int = modulation_AFSK_Audio_Carrier_Freq_Int + + def get_main_Network_Stream_Port_Int(self): + return self.main_Network_Stream_Port_Int + + def set_main_Network_Stream_Port_Int(self, main_Network_Stream_Port_Int): + self.main_Network_Stream_Port_Int = main_Network_Stream_Port_Int + + def get_main_Network_Stream_Address_Str(self): + return self.main_Network_Stream_Address_Str + + def set_main_Network_Stream_Address_Str(self, main_Network_Stream_Address_Str): + self.main_Network_Stream_Address_Str = main_Network_Stream_Address_Str + + def get_main_LPF_Cutoff_Freq_Int(self): + return self.main_LPF_Cutoff_Freq_Int + + def set_main_LPF_Cutoff_Freq_Int(self, main_LPF_Cutoff_Freq_Int): + self.main_LPF_Cutoff_Freq_Int = main_LPF_Cutoff_Freq_Int + self.low_pass_filter_1.set_taps(firdes.low_pass(1, self.sampRate, self.main_LPF_Cutoff_Freq_Int, 1000, firdes.WIN_HAMMING, 6.76)) + + def get_freqOffset(self): + return self.freqOffset + + def set_freqOffset(self, freqOffset): + self.freqOffset = freqOffset + + def get_fileNameRes(self): + return self.fileNameRes + + def set_fileNameRes(self, fileNameRes): + self.fileNameRes = fileNameRes + self.blocks_file_sink_0.open(self.fileNameRes) + self.blocks_wavfile_sink_0.open(self.fileNameRes) + + def get_fileNameRaw(self): + return self.fileNameRaw + + def set_fileNameRaw(self, fileNameRaw): + self.fileNameRaw = fileNameRaw + self.blocks_file_sink_1.open(self.fileNameRaw) + + def get_deframer_Syncword_Threshold_Int(self): + return self.deframer_Syncword_Threshold_Int + + def set_deframer_Syncword_Threshold_Int(self, deframer_Syncword_Threshold_Int): + self.deframer_Syncword_Threshold_Int = deframer_Syncword_Threshold_Int + + def get_deframer_Short_Frames_Bool(self): + return self.deframer_Short_Frames_Bool + + def set_deframer_Short_Frames_Bool(self, deframer_Short_Frames_Bool): + self.deframer_Short_Frames_Bool = deframer_Short_Frames_Bool + + def get_deframer_G3RUH_Bool(self): + return self.deframer_G3RUH_Bool + + def set_deframer_G3RUH_Bool(self, deframer_G3RUH_Bool): + self.deframer_G3RUH_Bool = deframer_G3RUH_Bool + + def get_deframer_CRC16_Bool(self): + return self.deframer_CRC16_Bool + + def set_deframer_CRC16_Bool(self, deframer_CRC16_Bool): + self.deframer_CRC16_Bool = deframer_CRC16_Bool + + + + + +def main(top_block_cls=fmDemod, options=None): + tb = top_block_cls() + + def sig_handler(sig=None, frame=None): + tb.stop() + tb.wait() + + sys.exit(0) + + signal.signal(signal.SIGINT, sig_handler) + signal.signal(signal.SIGTERM, sig_handler) + + tb.start() + + while True: + time.sleep(1) + + tb.stop() + tb.wait() + + +if __name__ == '__main__': + main() diff --git a/gsc_notify.sh b/gsc_notify.sh deleted file mode 100755 index 65aba32..0000000 --- a/gsc_notify.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -if [ -z $2 ]; then - exit 1 -fi - -sat_name="$1" -filename="$2" -web_addr="http://172.16.30.52:8000" -sender="gsnotifications38@gmail.com" -recipient="stanislav.barantsev@community.isunet.edu" - -echo -ne "To: ${recipient}\nFrom: ${sender}\nSubject: Tracking done\n\n"\ -"Hello there,\n"\ -"Tracking of ${1} satellite done. Please find the results via link:\n\n"\ -"${web_addr}/${filename}.dat" | msmtp ${recipient} diff --git a/img/antenna-position.png b/img/antenna-position.png new file mode 100644 index 0000000..965e4bd Binary files /dev/null and b/img/antenna-position.png differ diff --git a/img/arch.jpg b/img/arch.jpg new file mode 100644 index 0000000..141f913 Binary files /dev/null and b/img/arch.jpg differ diff --git a/img/configuration.png b/img/configuration.png new file mode 100644 index 0000000..0081788 Binary files /dev/null and b/img/configuration.png differ diff --git a/img/img7.png b/img/debugging.png similarity index 100% rename from img/img7.png rename to img/debugging.png diff --git a/img/funcube-1-bob.png b/img/funcube-1-bob.png new file mode 100644 index 0000000..cb71ae8 Binary files /dev/null and b/img/funcube-1-bob.png differ diff --git a/img/funcube-1-messages.png b/img/funcube-1-messages.png new file mode 100644 index 0000000..e2497d0 Binary files /dev/null and b/img/funcube-1-messages.png differ diff --git a/img/funcube-fitter.png b/img/funcube-fitter.png new file mode 100644 index 0000000..1ff26ff Binary files /dev/null and b/img/funcube-fitter.png differ diff --git a/img/ground-station-statistics.png b/img/ground-station-statistics.png new file mode 100644 index 0000000..53f1cf3 Binary files /dev/null and b/img/ground-station-statistics.png differ diff --git a/img/img1.png b/img/img1.png deleted file mode 100644 index c92d187..0000000 Binary files a/img/img1.png and /dev/null differ diff --git a/img/img10.png b/img/img10.png deleted file mode 100644 index 10ebb97..0000000 Binary files a/img/img10.png and /dev/null differ diff --git a/img/img11.png b/img/img11.png deleted file mode 100644 index a18b7aa..0000000 Binary files a/img/img11.png and /dev/null differ diff --git a/img/img2.png b/img/img2.png deleted file mode 100644 index db1a6e8..0000000 Binary files a/img/img2.png and /dev/null differ diff --git a/img/img3.png b/img/img3.png deleted file mode 100644 index b22c63e..0000000 Binary files a/img/img3.png and /dev/null differ diff --git a/img/img8.png b/img/img8.png deleted file mode 100644 index 3da9bf9..0000000 Binary files a/img/img8.png and /dev/null differ diff --git a/img/img9.PNG b/img/img9.PNG deleted file mode 100644 index 61e864a..0000000 Binary files a/img/img9.PNG and /dev/null differ diff --git a/img/isu-gs-status-progress.png b/img/isu-gs-status-progress.png new file mode 100644 index 0000000..4a2184f Binary files /dev/null and b/img/isu-gs-status-progress.png differ diff --git a/img/nayif-1-asib.png b/img/nayif-1-asib.png new file mode 100644 index 0000000..7b98e1f Binary files /dev/null and b/img/nayif-1-asib.png differ diff --git a/img/notification.png b/img/notification.png new file mode 100644 index 0000000..c55160f Binary files /dev/null and b/img/notification.png differ diff --git a/img/img4.jpg b/img/results_1.jpg similarity index 100% rename from img/img4.jpg rename to img/results_1.jpg diff --git a/img/img5.jpg b/img/results_2.jpg similarity index 100% rename from img/img5.jpg rename to img/results_2.jpg diff --git a/img/img6.jpg b/img/results_3.jpg similarity index 100% rename from img/img6.jpg rename to img/results_3.jpg diff --git a/src/gnuradio.c b/src/gnuradio.c index 27a64df..4cdc4ad 100644 --- a/src/gnuradio.c +++ b/src/gnuradio.c @@ -51,7 +51,7 @@ int sdr_prepare_config(cfg_t *cfg, satellite_t *sat, const char *filename) return -1; } - snprintf(cfg_line, sizeof(cfg_line), "[sdr]\n" + snprintf(cfg_line, sizeof(cfg_line), "[sdr]\n" "sdr_Freq=%d\n" "sdr_IF_Gain=%d\n" "sdr_BB_Gain=%d\n" @@ -63,7 +63,7 @@ int sdr_prepare_config(cfg_t *cfg, satellite_t *sat, const char *filename) fwrite(cfg_line, strlen(cfg_line), 1, fd); - snprintf(cfg_line, sizeof(cfg_line), "[main]\n" + snprintf(cfg_line, sizeof(cfg_line), "[main]\n" "main_LPF_Cutoff_Freq=%d\n" "main_Network_Stream_Address=%s\n" "main_Network_Stream_Port=%d\n" @@ -75,22 +75,20 @@ int sdr_prepare_config(cfg_t *cfg, satellite_t *sat, const char *filename) fwrite(cfg_line, strlen(cfg_line), 1, fd); - snprintf(cfg_line, sizeof(cfg_line), "[modulation]\n" + snprintf(cfg_line, sizeof(cfg_line), "[modulation]\n" "modulation_Type=%d\n" - "modulation_Baud_Rate=%d\n", + "modulation_Deframer_Type=%d\n", sat->modulation, - sat->baudRate); + sat->deframer); fwrite(cfg_line, strlen(cfg_line), 1, fd); - snprintf(cfg_line, sizeof(cfg_line), "modulation_Short_Frames=%d\n" - "modulation_G3RUH=%d\n" - "modulation_CRC16=%d\n", - sat->shortFrames, - sat->g3ruh, - sat->crc16); + if (sat->modulation != MODULATION_FM) { + snprintf(cfg_line, sizeof(cfg_line), "modulation_Baud_Rate=%d\n", + sat->baudRate); - fwrite(cfg_line, strlen(cfg_line), 1, fd); + fwrite(cfg_line, strlen(cfg_line), 1, fd); + } switch (sat->modulation) { case MODULATION_BPSK: @@ -115,8 +113,50 @@ int sdr_prepare_config(cfg_t *cfg, satellite_t *sat, const char *filename) fwrite(cfg_line, strlen(cfg_line), 1, fd); break; + case MODULATION_FM: + /** TODO: handle this */ + break; + default: + LOG_E("Unsupported modulation type"); + fclose(fd); + return -1; }; + snprintf(cfg_line, sizeof(cfg_line), "[deframer]\n"); + fwrite(cfg_line, strlen(cfg_line), 1, fd); + + switch (sat->deframer) { + case DEFRAMER_AO_40: + snprintf(cfg_line, sizeof(cfg_line), "deframer_Short_Frames=%d\n" + "deframer_CRC16=%d\n" + "deframer_Syncword_Threshold=%d\n", + sat->shortFrames, + sat->crc16, + sat->syncwordThreshold); + fwrite(cfg_line, strlen(cfg_line), 1, fd); + break; + case DEFRAMER_AX25: + snprintf(cfg_line, sizeof(cfg_line), "deframer_G3RUH_Bool=%d\n", + sat->g3ruh); + fwrite(cfg_line, strlen(cfg_line), 1, fd); + break; + case DEFRAMER_FOSSASAT: + case DEFRAMER_GOMSPACE_U482C: + case DEFRAMER_GOMSPACE_AX100_RS: + case DEFRAMER_GOMSPACE_AX100_ASM_GOLAY: + snprintf(cfg_line, sizeof(cfg_line), "deframer_Syncword_Threshold=%d\n", + sat->syncwordThreshold); + fwrite(cfg_line, strlen(cfg_line), 1, fd); + break; + case DEFRAMER_DUMMY_FM: + /** do nothing */ + break; + default: + LOG_E("Unsupported deframer selected"); + fclose(fd); + return -1; + } + fclose(fd); return 0; } diff --git a/src/rest_api.c b/src/rest_api.c index bf591c3..6151665 100644 --- a/src/rest_api.c +++ b/src/rest_api.c @@ -347,12 +347,212 @@ static int rest_api_get_observation(char *payload, char **reply_buf, const char return ret; } +static int rest_api_parse_modulation(satellite_t *sat, json_object *modulationObj, const char **error) +{ + int ret = 0; + json_object *valObj; + + if (!json_get_int_by_key(modulationObj, "bandwidth", &sat->bandwidth)) { + *error = "'/observation/satellite/modulation/bandwidth' not specified"; + ret = -1; + goto out; + } + + LOG_V("Bandwidth: [ %d ]", sat->bandwidth); + + const char *satModulation = json_get_string_by_key(modulationObj, "type"); + if (!satModulation) { + *error = "'/observation/satellite/modulation/type' string is not specified!"; + ret = -1; + goto out; + } + + LOG_V("Modulation [ %s ]", satModulation); + + if (streq(satModulation, "bpsk")) { + sat->modulation = MODULATION_BPSK; + if (!json_object_object_get_ex(modulationObj, "bpsk_manchester", &valObj)) { + *error = "'/observation/satellite/modulation/bpsk_manchester' object is missing"; + ret = -1; + goto out; + } + + if (json_object_get_type(valObj) == json_type_boolean) { + sat->bpskManchester = json_object_get_boolean(valObj); + } else { + *error = "'/observation/satellite/modulation/bpsk_manchester' isn't boolean or doesn't exist"; + ret = -1; + goto out; + } + + LOG_V("BPSK Manchester: [ %d ]", !!sat->bpskManchester); + + if (!json_object_object_get_ex(modulationObj, "bpsk_differential", &valObj)) { + *error = "'/observation/satellite/modulation/bpsk_differential' object is missing"; + ret = -1; + goto out; + } + + if (json_object_get_type(valObj) == json_type_boolean) { + sat->bpskDifferential = json_object_get_boolean(valObj); + } else { + *error = "'/observation/satellite/modulation/bpsk_differential' isn't boolean or doesn't exist"; + ret = -1; + goto out; + } + + LOG_V("BPSK Differential: [ %d ]", !!sat->bpskDifferential); + + } else if (streq(satModulation, "afsk")) { + sat->modulation = MODULATION_AFSK; + if (!json_get_int_by_key(modulationObj, "afsk_audio_freq_carrier", &sat->afskAFC)) { + *error = "'/observation/satellite/modulation/afsk_audio_freq_carrier' not specified"; + ret = -1; + goto out; + } + + LOG_V("AFSK AFC: [ %d ]", sat->afskAFC); + + if (!json_get_int_by_key(modulationObj, "afsk_deviation", &sat->afskDeviation)) { + *error = "'/observation/satellite/modulation/afsk_deviation' not specified"; + ret = -1; + goto out; + } + + LOG_V("AFSK Deviation: [ %d ]", sat->afskDeviation); + + } else if (streq(satModulation, "fsk")) { + sat->modulation = MODULATION_FSK; + + if (!json_object_object_get_ex(modulationObj, "fsk_sub_audio", &valObj)) { + *error = "'/observation/satellite/modulation/fsk_sub_audio' object is missing"; + ret = -1; + goto out; + } + + if (json_object_get_type(valObj) == json_type_boolean) { + sat->fskSubAudio = json_object_get_boolean(valObj); + } else { + *error = "'/observation/satellite/modulation/fsk_sub_audio' isn't boolean or doesn't exist"; + ret = -1; + goto out; + } + + LOG_V("FSK subaudio: [ %d ]", !!sat->fskSubAudio); + } else if (streq(satModulation, "fm")) { + sat->modulation = MODULATION_FM; + /** do nothing here */ + } + else { + *error = "'/observation/satellite/modulation/type' only 'bpsk', 'fsk', 'afsk' and 'fm' are supported"; + ret = -1; + goto out; + } + + if (sat->modulation != MODULATION_FM) { + if (!json_get_int_by_key(modulationObj, "baud_rate", &sat->baudRate)) { + *error = "'/observation/satellite/modulation/baud_rate' not specified"; + ret = -1; + goto out; + } + } + + LOG_V("Baud rate: [ %d ]", sat->baudRate); + +out: + return ret; +} + +static int rest_api_parse_deframer(satellite_t *sat, json_object *deframerObj, const char **error) +{ + int ret = 0; + json_object *valObj; + + const char *deframerType = json_get_string_by_key(deframerObj, "type"); + if (!deframerType) { + *error = "'/observation/satellite/deframer/type' string is not specified!"; + ret = -1; + goto out; + } + + LOG_V("Deframer type: [ %s ]", deframerType); + + if (streq(deframerType, "ao-40")) { + sat->deframer = DEFRAMER_AO_40; + + json_object_object_get_ex(deframerObj, "short_frames", &valObj); + + if (json_object_get_type(valObj) == json_type_boolean) { + sat->shortFrames = json_object_get_boolean(valObj); + } else { + *error = "'/observation/satellite/deframer/short_frames' isn't boolean or doesn't exist"; + ret = -1; + goto out; + } + + LOG_V("Short Frames: [ %d ]", !!sat->shortFrames); + + json_object_object_get_ex(deframerObj, "crc16", &valObj); + + if (json_object_get_type(valObj) == json_type_boolean) { + sat->crc16 = json_object_get_boolean(valObj); + } else { + *error = "'/observation/satellite/deframer/short_frames' isn't boolean or doesn't exist"; + ret = -1; + goto out; + } + + LOG_V("CRC16: [ %d ]", !!sat->crc16); + } else if (streq(deframerType, "gomspace-u482c")) { + sat->deframer = DEFRAMER_GOMSPACE_U482C; + } else if (streq(deframerType, "gomspace-ax100-rs")) { + sat->deframer = DEFRAMER_GOMSPACE_AX100_RS; + } else if (streq(deframerType, "gomspace-ax100-asm-golay")) { + sat->deframer = DEFRAMER_GOMSPACE_AX100_ASM_GOLAY; + } else if (streq(deframerType, "ax-25")) { + sat->deframer = DEFRAMER_AX25; + + json_object_object_get_ex(deframerObj, "g3ruh", &valObj); + + if (json_object_get_type(valObj) == json_type_boolean) { + sat->g3ruh = json_object_get_boolean(valObj); + } else { + *error = "'/observation/satellite/deframer/g3ruh' isn't boolean or doesn't exist"; + ret = -1; + goto out; + } + + LOG_V("G3RUH: [ %d ]", !!sat->g3ruh); + } else if (streq(deframerType, "fossasat")) { + sat->deframer = DEFRAMER_FOSSASAT; + } else if (streq(deframerType, "fm")) { + sat->deframer = DEFRAMER_DUMMY_FM; + } else { + *error = "Unsupported deframer, please refer to the valid list"; + ret = -1; + goto out; + } + + /** optional */ + if (json_get_int_by_key(deframerObj, "syncword_threshold", &sat->syncwordThreshold)) { + LOG_V("Syncword Threshold: [ %d ]", sat->syncwordThreshold); + } else { + /** TODO: change to define */ + sat->syncwordThreshold = 4; + LOG_E("Syncword threshold not found, use defaults: [ %d ]", sat->syncwordThreshold); + } + +out: + return ret; +} + static int rest_api_set_observation(char *payload, char **reply_buf, const char **error) { int ret; struct json_object *jObj; struct json_object *observationObj; observation_t *observation; + global_stats_t *stats = stats_get_instance(); ret = 0; @@ -376,20 +576,23 @@ static int rest_api_set_observation(char *payload, char **reply_buf, const char goto out; } + stats->satellites_scheduled = 0; if ((observation = sat_setup_observation()) == NULL) { ret = -1; goto out; } json_object *satellite; - struct json_object *valObj; json_object_object_get_ex(observationObj, "satellite", &satellite); if (satellite) { int i; + int rc; for (i = 0; i < json_object_array_length(satellite); i++) { - json_object *jsatellitePart; + json_object *deframerObj; + json_object *satelliteObj; + json_object *modulationObj; satellite_t *sat = calloc(1, sizeof(satellite_t)); if (!satellite) { @@ -401,14 +604,14 @@ static int rest_api_set_observation(char *payload, char **reply_buf, const char sat->obs = observation; LIST_INSERT_HEAD(&observation->satellites_list, sat, entries); - jsatellitePart = json_object_array_get_idx(satellite, i); - if (!jsatellitePart) { + satelliteObj = json_object_array_get_idx(satellite, i); + if (!satelliteObj) { *error = "'/observation/satellite': couldn't get CG array index"; ret = -1; goto out; } - const char *satName = json_get_string_by_key(jsatellitePart, "name"); + const char *satName = json_get_string_by_key(satelliteObj, "name"); if (!satName) { *error = "'/observation/satellite/name' string is not specified!"; ret = -1; @@ -417,14 +620,10 @@ static int rest_api_set_observation(char *payload, char **reply_buf, const char LOG_V("satellite name: [ %s ]", satName); - const char *satModulation = json_get_string_by_key(jsatellitePart, "modulation"); - if (!satModulation) { - *error = "'/observation/satellite/modulation' string is not specified!"; - ret = -1; - goto out; - } + const char *network_addr = json_get_string_by_key(satelliteObj, "network_addr"); + if (network_addr) + sat->network_addr = strdup(network_addr); - sat->network_addr = strdup(json_get_string_by_key(jsatellitePart, "network_addr")); if (!sat->network_addr) { *error = "'/observation/satellite/network_addr' string is not specified!"; ret = -1; @@ -433,7 +632,7 @@ static int rest_api_set_observation(char *payload, char **reply_buf, const char LOG_V("Network stream address: [ %s ]", sat->network_addr); - if (!json_get_int_by_key(jsatellitePart, "network_port", &sat->network_port)) { + if (!json_get_int_by_key(satelliteObj, "network_port", &sat->network_port)) { *error = "'/observation/satellite/network_port' not specified"; ret = -1; goto out; @@ -441,162 +640,91 @@ static int rest_api_set_observation(char *payload, char **reply_buf, const char LOG_V("Network stream port: [ %d ]", sat->network_port); - if (!json_get_int_by_key(jsatellitePart, "baud_rate", &sat->baudRate)) { - *error = "'/observation/satellite/baud_rate' not specified"; + json_object_object_get_ex(satelliteObj, "modulation", &modulationObj); + if (!modulationObj) { + *error = "/observation/satellite/modulation object not found!"; ret = -1; goto out; } - LOG_V("Baud rate: [ %d ]", sat->baudRate); - - if (!json_get_int_by_key(jsatellitePart, "bandwidth", &sat->bandwidth)) { - *error = "'/observation/satellite/bandwidth' not specified"; + if (rest_api_parse_modulation(sat, modulationObj, error) == -1) { ret = -1; goto out; } - LOG_V("Bandwidth: [ %d ]", sat->bandwidth); - - /** optional */ - json_object_object_get_ex(jsatellitePart, "short_frames", &valObj); - - if (json_object_get_type(valObj) == json_type_boolean) { - sat->shortFrames = json_object_get_boolean(valObj); - } else { - sat->shortFrames = false; - } - - LOG_V("Short Frames: [ %d ]", !!sat->shortFrames); - - /** optional */ - json_object_object_get_ex(jsatellitePart, "crc16", &valObj); - - if (json_object_get_type(valObj) == json_type_boolean) { - sat->crc16 = json_object_get_boolean(valObj); - } else { - sat->crc16 = false; - } - - LOG_V("CRC16: [ %d ]", !!sat->crc16); - - /** optional */ - json_object_object_get_ex(jsatellitePart, "g3ruh", &valObj); - - if (json_object_get_type(valObj) == json_type_boolean) { - sat->g3ruh = json_object_get_boolean(valObj); - } else { - sat->g3ruh = false; + json_object_object_get_ex(satelliteObj, "deframer", &deframerObj); + if (!deframerObj) { + *error = "/observation/satellite/deframer object is required for analog modulation!"; + ret = -1; + goto out; } - LOG_V("G3RUH: [ %d ]", !!sat->g3ruh); - - if (streq(satModulation, "bpsk")) { - sat->modulation = MODULATION_BPSK; - if (!json_object_object_get_ex(jsatellitePart, "bpsk_manchester", &valObj)) { - *error = "'/observation/satellite/bpsk_manchester' object is missing"; - ret = -1; - goto out; - } - - if (json_object_get_type(valObj) == json_type_boolean) { - sat->bpskManchester = json_object_get_boolean(valObj); - } else { - *error = "'/observation/satellite/bpsk_manchester' isn't boolean"; - ret = -1; - goto out; - } - - LOG_V("BPSK Manchester: [ %d ]", !!sat->bpskManchester); - - if (!json_object_object_get_ex(jsatellitePart, "bpsk_differential", &valObj)) { - *error = "'/observation/satellite/bpsk_differential' object is missing"; - ret = -1; - goto out; - } - - if (json_object_get_type(valObj) == json_type_boolean) { - sat->bpskDifferential = json_object_get_boolean(valObj); - } else { - *error = "'/observation/satellite/bpsk_differential' isn't boolean"; - ret = -1; - goto out; - } - - LOG_V("BPSK Differential: [ %d ]", !!sat->bpskDifferential); - - } else if (streq(satModulation, "afsk")) { - sat->modulation = MODULATION_AFSK; - if (!json_get_int_by_key(jsatellitePart, "afsk_audio_freq_carrier", &sat->afskAFC)) { - *error = "'/observation/satellite/afsk_audio_freq_carrier' not specified"; - ret = -1; - goto out; - } - - LOG_V("AFSK AFC: [ %d ]", sat->afskAFC); - - if (!json_get_int_by_key(jsatellitePart, "afsk_deviation", &sat->afskDeviation)) { - *error = "'/observation/satellite/afsk_deviation' not specified"; - ret = -1; - goto out; - } - - LOG_V("AFSK Deviation: [ %d ]", sat->afskDeviation); - - } else if (streq(satModulation, "fsk")) { - sat->modulation = MODULATION_FSK; - - if (!json_object_object_get_ex(jsatellitePart, "fsk_sub_audio", &valObj)) { - *error = "'/observation/satellite/fsk_sub_audio' object is missing"; - ret = -1; - goto out; - } - - if (json_object_get_type(valObj) == json_type_boolean) { - sat->fskSubAudio = json_object_get_boolean(valObj); - } else { - *error = "'/observation/satellite/fsk_sub_audio' isn't boolean"; - ret = -1; - goto out; - } - - LOG_V("FSK subaudio: [ %d ]", !!sat->fskSubAudio); - } - else { - *error = "'/observation/satellite/modulation' only 'bpsk', 'fsk' and 'afsk' are supported"; + if (rest_api_parse_deframer(sat, deframerObj, error) == -1) { ret = -1; goto out; } - LOG_V("satellite modulation: [ %s ]", satModulation); - strncpy(sat->name, satName, sizeof(sat->name) - 1); - if (!json_get_int_by_key(jsatellitePart, "frequency", &sat->frequency)) { + if (!json_get_int_by_key(satelliteObj, "frequency", &sat->frequency)) { *error = "'/observation/satellite/frequency' not specified"; ret = -1; goto out; } - LOG_V("satellite frequency: [ %d ]", sat->frequency); + LOG_V("Satellite frequency: [ %d ]", sat->frequency); - if (!json_get_double_by_key(jsatellitePart, "min_elevation", &sat->min_elevation)) { + if (!json_get_double_by_key(satelliteObj, "min_elevation", &sat->min_elevation)) { *error = "'/observation/satellite/min_elevation' not specified"; ret = -1; goto out; } - LOG_V("satellite min. elevation: [ %f ]", sat->min_elevation); + LOG_V("Satellite min. elevation: [ %f ]", sat->min_elevation); - if (!json_get_int_by_key(jsatellitePart, "priority", &sat->priority)) { + if (!json_get_int_by_key(satelliteObj, "priority", &sat->priority)) { *error = "'/observation/satellite/priority' not specified"; ret = -1; goto out; } - LOG_V("satellite priority: [ %d ]", sat->priority); + LOG_V("Satellite priority: [ %d ]", sat->priority); + + stats->satellites_scheduled++; + + rc = sat_setup(sat); + + switch (rc) { + case SAT_SET_RC_OK: + LOG_I("Satellite %s set up successfully", sat->name); + break; + case SAT_SET_RC_NOT_FOUND: + *error = "Satellite not found"; + LOG_E("Rejected: satellite not found"); + break; + case SAT_SET_RC_GEOSTATIONARY: + *error = "Satellite is geostationary"; + LOG_E("Rejected: the satellite is geostationary"); + break; + case SAT_SET_RC_PREDICT: + *error = "Cannot predict satellite"; + LOG_E("Rejected: error during prediction of the satellite"); + break; + case SAT_SET_RC_PRIORITY: + *error = "Satellite priority is not unique"; + LOG_E("Rejected: satellite priority is not unique"); + break; + case SAT_SET_RC_UNKNOWN: + *error = "Unknown error"; + LOG_E("Rejected: unknown reason"); + break; + default: + /** do nothing */ + break; + } - if (sat_setup(sat) == -1) { - *error = "Satellite not found"; + if (rc != SAT_SET_RC_OK) { + sat_clear_all(observation); ret = -1; goto out; } @@ -636,6 +764,11 @@ static int rest_api_set_antenna_position(char *payload, char **reply_buf, const return -1; } + if (stats->state != GSC_STATE_WAITING) { + *error = "Calibration, parking, or tracking in progress"; + return -1; + } + LOG_V("Set antenna position REST API started"); LOG_V("Parsing JSON request..."); @@ -668,7 +801,7 @@ static int rest_api_set_antenna_position(char *payload, char **reply_buf, const LOG_I("Moving antenna to az: %f, el: %f", azimuth, elevation); - rotctl_send_and_wait(observation, azimuth, elevation); + rotctl_park_and_wait(observation, azimuth, elevation); LOG_V("Set antenna position done"); out: @@ -690,6 +823,7 @@ static int rest_api_set_calibration(char *payload, char **reply_buf, const char struct json_object *calibrationObj; struct json_object *valObj; observation_t *observation; + global_stats_t *stats = stats_get_instance(); ret = 0; @@ -700,6 +834,11 @@ static int rest_api_set_calibration(char *payload, char **reply_buf, const char return -1; } + if (stats->state != GSC_STATE_WAITING) { + *error = "Calibration, parking, or tracking in progress"; + return -1; + } + LOG_V("Parsing JSON request..."); jObj = json_tokener_parse(payload); if (!jObj) { diff --git a/src/rotctl.c b/src/rotctl.c index 9b160de..d5a2d90 100644 --- a/src/rotctl.c +++ b/src/rotctl.c @@ -33,6 +33,116 @@ #include "stats.h" #include "rotctl.h" +pthread_t az_thread; +pthread_t el_thread; + +typedef struct pos_t { + void *obs; + double val; + rot_type_t type; +} pos_t; + +static int rotctl_flush_socket(observation_t *obs, rot_type_t type) +{ + int fd; + int rv; + int ret; + fd_set set; + char *rxbuf = NULL; + struct timeval timeout; + + ret = 0; + + if (obs == NULL) + return -1; + + if (type == ROT_TYPE_NONE) + return -1; + + /** TODO: replace with a relevant define */ + rxbuf = calloc(8192, 1); + if (!rxbuf) + return -1; + + fd = (type == ROT_TYPE_AZ) ? obs->cfg->cli.azimuth_conn_fd : obs->cfg->cli.elevation_conn_fd; + + FD_ZERO(&set); + FD_SET(fd, &set); + + timeout.tv_sec = 0; + timeout.tv_usec = 10000; + + rv = select(fd + 1, &set, NULL, NULL, &timeout); + if (rv > 0) { + recv(fd, rxbuf, 8192, 0); + printf("Flushing the old data\n"); + } + + LOG_V("rotctl_flush_socket() command done"); + + free(rxbuf); + return ret; +} + +static int rotctl_send_recv_or_timeout(observation_t *obs, rot_type_t type, double val) +{ + int fd; + int rv; + int ret; + fd_set set; + char *rxbuf = NULL; + char val_buf[64] = { 0 }; + struct timeval timeout; + + ret = 0; + + if (obs == NULL) + return -1; + + if (type == ROT_TYPE_NONE) + return -1; + + /** TODO: replace with a relevant define */ + rxbuf = calloc(8192, 1); + if (!rxbuf) + return -1; + + fd = (type == ROT_TYPE_AZ) ? obs->cfg->cli.azimuth_conn_fd : obs->cfg->cli.elevation_conn_fd; + + rotctl_flush_socket(obs, type); + + FD_ZERO(&set); + FD_SET(fd, &set); + + timeout.tv_sec = 120; + timeout.tv_usec = 0; + + snprintf(val_buf, sizeof(val_buf), "w " "%s" "%.02f\n", (type == ROT_TYPE_AZ) ? "A" : "E", val); + write(fd, val_buf, strlen(val_buf)); + + rv = select(fd + 1, &set, NULL, NULL, &timeout); + + if(rv == -1) { + ret = -1; + goto out; + } else if(rv == 0) { + LOG_V("select() timeout"); + ret = 0; + goto out; + } else { + /** TODO: replace with a relevant define */ + int received = recv(fd, rxbuf, 8192, 0); + if (received < 0) + goto out; + } + +out: + LOG_V("rotctl_send_recv_or_timeout() command done"); + + free(rxbuf); + return ret; +} + int rotctl_open(observation_t *obs, rot_type_t type) { int ret = 0; @@ -177,8 +287,6 @@ float rotctl_get_azimuth(observation_t *obs) snprintf(az_buf, sizeof(az_buf), "w A\n"); - /* while (read(obs->cfg->cli.azimuth_conn_fd, rxbuf, sizeof(rxbuf)) > 0) */ - write(obs->cfg->cli.azimuth_conn_fd, az_buf, strlen(az_buf)); read(obs->cfg->cli.azimuth_conn_fd, rxbuf, sizeof(rxbuf)); @@ -195,23 +303,28 @@ float rotctl_get_elevation(observation_t *obs) snprintf(el_buf, sizeof(el_buf), "w E\n"); - /* while (read(obs->cfg->cli.azimuth_conn_fd, rxbuf, sizeof(rxbuf)) > 0) */ - write(obs->cfg->cli.elevation_conn_fd, el_buf, strlen(el_buf)); read(obs->cfg->cli.elevation_conn_fd, rxbuf, sizeof(rxbuf)); return rotctl_extract_value(rxbuf); } +static void *rotctl_park(void *opt) +{ + pos_t *pos = (pos_t *) opt; + + rotctl_send_recv_or_timeout(pos->obs, pos->type, pos->val); + return NULL; +} -int rotctl_send_and_wait(observation_t *obs, double az, double el) +int rotctl_park_and_wait(observation_t *obs, double az, double el) { int ret; - char az_buf[32] = { 0 }; - char el_buf[32] = { 0 }; - char rxbuf[4096] = { 0 }; global_stats_t *stats; + pos_t pos_az = {obs, az, ROT_TYPE_AZ}; + pos_t pos_el = {obs, el, ROT_TYPE_EL}; + stats = stats_get_instance(); stats->last_azimuth = az; stats->last_elevation = el; @@ -221,42 +334,16 @@ int rotctl_send_and_wait(observation_t *obs, double az, double el) if (obs == NULL) return -1; - snprintf(az_buf, sizeof(az_buf), "w A%.02f\n", az); - snprintf(el_buf, sizeof(el_buf), "w E%.02f\n", el); - - /* while (read(obs->cfg->cli.azimuth_conn_fd, rxbuf, sizeof(rxbuf)) > 0) */ + pthread_create(&az_thread, NULL, rotctl_park, &pos_az); + pthread_create(&el_thread, NULL, rotctl_park, &pos_el); - write(obs->cfg->cli.azimuth_conn_fd, az_buf, strlen(az_buf)); - write(obs->cfg->cli.elevation_conn_fd, el_buf, strlen(el_buf)); - read(obs->cfg->cli.azimuth_conn_fd, rxbuf, sizeof(rxbuf)); - read(obs->cfg->cli.elevation_conn_fd, rxbuf, sizeof(rxbuf)); + pthread_join(az_thread, NULL); + pthread_join(el_thread, NULL); LOG_V("rotctl_send_and_wait() command done"); return ret; } -static int rotctl_send(observation_t *obs, bool az, double val) -{ - int fd; - int ret; - char val_buf[32] = { 0 }; - char rxbuf[4096] = { 0 }; - - ret = 0; - - if (obs == NULL) - return -1; - - fd = az ? obs->cfg->cli.azimuth_conn_fd : obs->cfg->cli.elevation_conn_fd; - snprintf(val_buf, sizeof(val_buf), "w " "%s" "%.02f\n", az ? "A" : "E", val); - - write(fd, val_buf, strlen(val_buf)); - read(fd, rxbuf, sizeof(rxbuf)); - - LOG_V("rotctl_send() command done"); - return ret; -} - int rotctl_send_az(observation_t *obs, double az) { global_stats_t *stats; @@ -264,7 +351,7 @@ int rotctl_send_az(observation_t *obs, double az) stats = stats_get_instance(); stats->last_azimuth = az; - return rotctl_send(obs, true, az); + return rotctl_send_recv_or_timeout(obs, ROT_TYPE_AZ, az); } int rotctl_send_el(observation_t *obs, double el) @@ -274,6 +361,6 @@ int rotctl_send_el(observation_t *obs, double el) stats = stats_get_instance(); stats->last_elevation = el; - return rotctl_send(obs, false, el); + return rotctl_send_recv_or_timeout(obs, ROT_TYPE_EL, el); } diff --git a/src/rotctl.h b/src/rotctl.h index 546d26a..cbce7c4 100644 --- a/src/rotctl.h +++ b/src/rotctl.h @@ -32,7 +32,7 @@ int rotctl_open(observation_t *obs, rot_type_t type); int rotctl_close(observation_t *obs, rot_type_t type); int rotctl_send_az(observation_t *obs, double az); int rotctl_send_el(observation_t *obs, double el); -int rotctl_send_and_wait(observation_t *obs, double az, double el); +int rotctl_park_and_wait(observation_t *obs, double az, double el); int rotctl_calibrate(observation_t *obs, bool azimuth, bool elevation); float rotctl_get_azimuth(observation_t *obs); float rotctl_get_elevation(observation_t *obs); diff --git a/src/sat.c b/src/sat.c index 29f9da7..407ca99 100644 --- a/src/sat.c +++ b/src/sat.c @@ -158,7 +158,7 @@ static double sat_fix_azimuth(double az) static void *sat_tracking_az(void *opt) { - int time_delay = 50000; + int time_delay = 1000000; time_t current_time; observation_t *obs; struct predict_position orbit; @@ -217,7 +217,7 @@ static void *sat_tracking_az(void *opt) static void *sat_tracking_el(void *opt) { - int time_delay = 50000; + int time_delay = 1000000; time_t current_time; observation_t *obs; struct predict_position orbit; @@ -295,7 +295,9 @@ static void *sat_tracking_doppler(void *opt) if (obs->cfg->dry_run == false) { LOG_I("Doppler compensation: %f Hz\n", shift); - if (obs->active->modulation != MODULATION_FSK) + if (obs->active->modulation != MODULATION_FSK && + obs->active->modulation != MODULATION_FM) + /** TODO: fix this terrible frequency offset */ sdr_set_freq(obs->active->frequency + shift - 12000); else /** TODO: This is terrible and needs to be fixed */ @@ -331,7 +333,9 @@ static void *sat_scheduler(void *opt) LOG_I("Current elevation: %f", stats->last_elevation); LOG_I("Scheduler started"); - fflush(stdout); /** just to avoid mixing up the output: it happens sometimes */ + /** just to avoid mixing up the + * output: it happens sometimes */ + fflush(stdout); /** the default state */ stats->state = GSC_STATE_WAITING; @@ -368,9 +372,9 @@ static void *sat_scheduler(void *opt) LOG_V("curr time = %ld, aos time = %ld", current_time, sat->next_aos); if (!sat->zero_transition) - rotctl_send_and_wait(obs, sat->aos_az, 0); + rotctl_park_and_wait(obs, sat->aos_az, 0); else - rotctl_send_and_wait(obs, sat->aos_az, 180); + rotctl_park_and_wait(obs, sat->aos_az, 180); stats->state = GSC_STATE_WAITING; LOG_I("Parking done"); @@ -523,6 +527,23 @@ static int sat_fetch_tle(const char *name, char *tle1, char *tle2) return ret; } +static bool sat_confirm_unique_priority(observation_t *obs, satellite_t *sat) +{ + satellite_t *iter; + int priority = sat->priority; + + LIST_FOREACH(iter, &obs->satellites_list, entries) { + if (iter == sat) + continue; + + if (iter->priority == priority) { + return false; + } + } + + return true; +} + int sat_predict(satellite_t *sat) { int ret; @@ -546,7 +567,7 @@ int sat_predict(satellite_t *sat) if (sat->obs->sim_time) current_time += sat->obs->sim_time; - LOG_I("SCHEDULE: current time=%ld", current_time); + LOG_V("SCHEDULE: current time=%ld", current_time); predict_julian_date_t start_time = predict_to_julian(current_time); @@ -651,14 +672,11 @@ int sat_setup(satellite_t *sat) int ret; char tle1[MAX_TLE_LEN] = { 0 }; char tle2[MAX_TLE_LEN] = { 0 }; - global_stats_t *stats; - /** always valid */ - stats = stats_get_instance(); + ret = SAT_SET_RC_OK; - ret = 0; - - if ((ret = sat_fetch_tle(sat->name, tle1, tle2)) == -1) { + if (sat_fetch_tle(sat->name, tle1, tle2) == -1) { + ret = SAT_SET_RC_NOT_FOUND; goto out; } @@ -666,12 +684,24 @@ int sat_setup(satellite_t *sat) strcpy(sat->tle2, tle2); sat->orbital_elements = predict_parse_tle(sat->tle1, sat->tle2); + if (predict_is_geosynchronous(sat->orbital_elements)) { + ret = SAT_SET_RC_GEOSTATIONARY; + goto out; + } + + if (!sat_confirm_unique_priority(sat->obs, sat)) { + ret = SAT_SET_RC_PRIORITY; + goto out; + } + LOG_I("Satellite found in the TLE list: [%s]", sat->name); LOG_V("TLE1: [%s]", tle1); LOG_V("TLE2: [%s]", tle2); - stats->satellites_scheduled++; - sat_predict(sat); + if (sat_predict(sat) == -1) { + ret = SAT_SET_RC_PREDICT; + goto out; + } out: return ret; @@ -713,7 +743,7 @@ static observation_t *sat_alloc_observation_data(void) return obs; } -static int sat_clear_all(observation_t *obs) +int sat_clear_all(observation_t *obs) { satellite_t *sat; global_stats_t *stats; @@ -727,7 +757,10 @@ static int sat_clear_all(observation_t *obs) while (!LIST_EMPTY(&obs->satellites_list)) { sat = LIST_FIRST(&obs->satellites_list); predict_destroy_orbital_elements(sat->orbital_elements); - free((void *) sat->network_addr); + + if (sat->network_addr) + free((void *) sat->network_addr); + LIST_REMOVE(sat, entries); free(sat); } @@ -738,7 +771,7 @@ static int sat_clear_all(observation_t *obs) memset(stats, 0, sizeof(global_stats_t)); predict_destroy_observer(obs->observer); - free(obs); + sat_destroy_observation(); return 0; } @@ -762,6 +795,14 @@ observation_t *sat_get_observation(void) return _observation; } +void sat_destroy_observation(void) +{ + if (_observation) { + free(_observation); + _observation = NULL; + } +} + int sat_reschedule_all() { satellite_t *iter; diff --git a/src/sat.h b/src/sat.h index e80df3f..42e3d16 100644 --- a/src/sat.h +++ b/src/sat.h @@ -38,9 +38,29 @@ typedef enum modulation_t { MODULATION_BPSK, MODULATION_AFSK, - MODULATION_FSK + MODULATION_FSK, + MODULATION_FM } modulation_t; +typedef enum deframer_t { + DEFRAMER_AO_40, + DEFRAMER_GOMSPACE_U482C, + DEFRAMER_AX25, + DEFRAMER_FOSSASAT, + DEFRAMER_GOMSPACE_AX100_RS, + DEFRAMER_GOMSPACE_AX100_ASM_GOLAY, + DEFRAMER_DUMMY_FM +} deframer_t; + +typedef enum sat_set_rc { + SAT_SET_RC_OK, + SAT_SET_RC_NOT_FOUND, + SAT_SET_RC_GEOSTATIONARY, + SAT_SET_RC_PRIORITY, + SAT_SET_RC_PREDICT, + SAT_SET_RC_UNKNOWN +} sat_set_rc; + typedef struct observation_t observation_t; typedef struct satellite_t { @@ -48,8 +68,9 @@ typedef struct satellite_t { char tle1[MAX_TLE_LEN]; char tle2[MAX_TLE_LEN]; - /** modulation */ modulation_t modulation; + deframer_t deframer; + const char *network_addr; int network_port; int baudRate; @@ -66,8 +87,7 @@ typedef struct satellite_t { bool fskSubAudio; /** deframing */ - /** TODO: implement */ - int syncword_threshold; + int syncwordThreshold; bool shortFrames; bool g3ruh; bool crc16; @@ -104,8 +124,10 @@ typedef struct observation_t { int sat_reschedule_all(void); int sat_setup(satellite_t *sat); +int sat_clear_all(observation_t *obs); observation_t *sat_get_observation(void); observation_t *sat_setup_observation(void); +void sat_destroy_observation(void); void sat_move_to_observation(void); satellite_t *sat_find_next(void);