Browse Source

With more channel support

Per Mårtensson 2 weeks ago
parent
commit
31cd808e87
8 changed files with 254 additions and 47 deletions
  1. 1 1
      CMakeLists.txt
  2. 8 4
      rtl_airband.conf
  3. 18 0
      src/CMakeLists.txt
  4. 14 0
      src/CMakeModules/FindJSON.cmake
  5. 8 0
      src/CMakeModules/Findpaho.cmake
  6. 3 0
      src/config.cpp
  7. 195 41
      src/rtl_airband.cpp
  8. 7 1
      src/rtl_airband.h

+ 1 - 1
CMakeLists.txt

@@ -25,7 +25,7 @@ endif(NOT CMAKE_BUILD_TYPE)
 
 # TODO: flags to add: -Wfloat-equal -Wconversion -Wstrict-overflow=5 -Waggregate-return -Wpedantic -Wcast-align
 # TODO: these could be added except for gtest: -Wswitch-enum -Wundef -Wswitch-default
-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wshadow -Wdate-time -Wpointer-arith -Wwrite-strings -Wcast-qual  -Wunreachable-code -Werror")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wshadow -Wdate-time -Wpointer-arith -Wwrite-strings -Wcast-qual -Wunreachable-code -Werror")
 set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Og -DDEBUG")
 
 if(DEBUG_SQUELCH)

+ 8 - 4
rtl_airband.conf

@@ -5,6 +5,10 @@ bel_prolong_time = 600;
 bel_wave_out_level = 0.1;
 bel_wave_in_level = 10.0;
 bel_blink_time = 60;
+bel_mqtt_server = "icecast.westfly.se";
+bel_mqtt_client_id = "0";
+bel_mqtt_user_id = "xxxxx";
+bel_mqtt_password = "xxxxxx";
 pidfile = "/tmp/rtl_airband.pid";
 devices: (
   {
@@ -25,11 +29,11 @@ devices: (
             type = "icecast";
             server = "icecast.westfly.se";
             port = 8000;
-            mountpoint = "ESGF.mp3";
-            name = "ESGF 123.350";
+            mountpoint = "ESXX.mp3";
+            name = "ESXX 121.500";
             genre = "ATC";
-            username = "FBGflyg";
-            password = "FBG74flyg!!!";
+            username = "XX";
+            password = "XXX";
           },  
 	  {
     	    type = "pulse";

+ 18 - 0
src/CMakeLists.txt

@@ -122,6 +122,9 @@ set(WITH_RTLSDR FALSE)
 option(MIRISDR "Enable Mirics support" ON)
 set(WITH_MIRISDR FALSE)
 
+option(PAHO "Enable PAHO support" ON)
+set(WITH_PAHO TRUE)
+
 option(SOAPYSDR "Enable SoapySDR support" ON)
 set(WITH_SOAPYSDR FALSE)
 
@@ -137,6 +140,8 @@ endif()
 if(GPIOD_LIBRARY)
     message(STATUS "libgpiod found")
 endif()
+
+
 if(RTLSDR)
 	find_package(RTLSDR)
 	if(RTLSDR_FOUND)
@@ -147,6 +152,16 @@ if(RTLSDR)
 		set(WITH_RTLSDR TRUE)
 	endif()
 endif()
+find_package(OpenSSL REQUIRED)
+find_library(paho-mqttpp3 NAMES libpaho-mqttpp3.so REQUIRED)
+find_library(paho-mqtt3as NAMES libpaho-mqtt3as.so REQUIRED)
+add_library(pahottpp STATIC IMPORTED)
+set_target_properties(pahottpp PROPERTIES IMPORTED_LOCATION ${paho-mqttpp3})
+
+add_library(pahomqtt3as SHARED IMPORTED)
+set_property(TARGET pahomqtt3as PROPERTY IMPORTED_LOCATION ${paho-mqtt3as})
+
+
 
 if(MIRISDR)
 	find_package(MiriSDR)
@@ -331,6 +346,9 @@ target_link_libraries (rtl_airband
 	pthread
 	${rtl_airband_extra_libs}
 	${GPIOD_LIBRARY}
+	${Jsoncpp_LIBRARY}
+	pahomqtt3as
+	pahottpp
 )
 
 install(TARGETS rtl_airband

+ 14 - 0
src/CMakeModules/FindJSON.cmake

@@ -0,0 +1,14 @@
+
+if(NOT JSON_FOUND)
+
+find_package(jsoncpp REQUIRED)
+link_libraries(${JSONCPP_LIBRARIES})
+link_directories(${CMAKE_CURRENT_SOURCE_DIR}/jsoncpp/lib)
+# target_link_libraries(data_publish paho-mqtt3a paho-mqttpp3)
+#target_link_libraries(data_publish PahoMqttCpp::paho-mqttpp3)
+find_path(Jsoncpp_INCLUDE_DIR
+  NAMES json/features.h
+  PATH_SUFFIXES jsoncpp
+  PATHS ${Jsoncpp_PKGCONF_INCLUDE_DIRS} # /usr/include/jsoncpp/json
+)
+endif(NOT JSON_FOUND)

+ 8 - 0
src/CMakeModules/Findpaho.cmake

@@ -0,0 +1,8 @@
+
+if(NOT PAHO_FOUND)
+
+find_package(PahoMqttCpp REQUIRED)
+
+# target_link_libraries(data_publish paho-mqtt3a paho-mqttpp3)
+#target_link_libraries(data_publish PahoMqttCpp::paho-mqttpp3)
+endif(NOT PAHO_FOUND)

+ 3 - 0
src/config.cpp

@@ -359,6 +359,9 @@ static int parse_channels(libconfig::Setting& chans, device_t* dev, int i) {
                 channel->freqlist[0].label = strdup(chans[j]["label"]);
             }
             channel->freqlist[0].modulation = channel_modulation;
+            if (chans[j].exists("banbel")) {
+                channel->freqlist[0].banbel = 1;
+            }
         } else { /* R_SCAN */
             channel->freq_count = chans[j]["freqs"].getLength();
             if (channel->freq_count < 1) {

+ 195 - 41
src/rtl_airband.cpp

@@ -30,7 +30,7 @@
 #include "hello_fft/gpu_fft.h"
 #include "hello_fft/mailbox.h"
 #endif /* WITH_BCM_VC */
-
+//#define GPIOX
 #include <fcntl.h>
 #include <lame/lame.h>
 #include <ogg/ogg.h>
@@ -65,8 +65,15 @@
 #include "gperftools/profiler.h"
 #endif /* WITH_PROFILING */
 #include <gpiod.h>
+/*#include <ncurses.h>*/
+#include <iomanip>
+#include <fstream>
+#include <string>
+#include <chrono>
+#include "mqtt/async_client.h"
 #include <ncurses.h>
-
+#include <curl/curl.h>
+#include <jsoncpp/json/json.h>
 
 using namespace std;
 using namespace libconfig;
@@ -79,11 +86,15 @@ using namespace libconfig;
 
 #define MAX_BUFFERS 10
 
-sem_t mutex_sem, spooler_sem;
+sem_t mutex_lock_main_thread, mutex_unlock_main_thread;
+sem_t mutex_lock_main_thread_mqtt, mutex_unlock_main_thread_mqtt;
 pthread_mutex_t lock_data; 
+pthread_mutex_t lock_mqtt_data; 
 device_t* devices;
 mixer_t* mixers;
 
+long int start_time;
+long int stop_time;
 int bel_start_on_time = 0;
 int bel_open_time = 0;
 int bel_prolong_time = 0;
@@ -91,6 +102,11 @@ float bel_wave_out_level = 0;
 float bel_wave_in_level = 0;
 int bel_blink_time = 0;
 
+char* bel_mqtt_server; 
+char* bel_mqtt_client_id;
+char* bel_mqtt_user_id;
+char* bel_mqtt_password;
+mqtt_msg_t mqtt_msg;
 int squelch_status = 0;
 int audio_status = 0;
 int status_data = 0;
@@ -167,16 +183,90 @@ void multiply(float ar, float aj, float br, float bj, float* cr, float* cj) {
     *cr = ar * br - aj * bj;
     *cj = aj * br + ar * bj;
 }
+class PublisherCallback : public virtual mqtt::callback
+{
+public:
+    void connection_lost(const std::string& cause) override
+    {
+        std::cout << "Connection lost: " << cause << std::endl;
+    }
+
+    void delivery_complete(mqtt::delivery_token_ptr token) override
+    {
+        token=token;
+        std::cout << "Message delivered" << std::endl;
+    }
+};
+void* mqtt_control_thread(void*){
+    string	address  = bel_mqtt_server,
+			clientID = bel_mqtt_client_id,
+			username  = bel_mqtt_user_id,
+			password  = bel_mqtt_password;
+    const std::string TOPIC1("device/SE0001/sq");
+    const std::string TOPIC2("device/SE0001/light");
+    const int QOS = 1;
+    //const int TIMEOUT = 10000;
+    mqtt::async_client client(address, clientID,mqtt::create_options(MQTTVERSION_5));
+
+    mqtt::connect_options connOpts;
+    mqtt::ssl_options ssl_options;
+
+    connOpts.set_keep_alive_interval(20);
+    connOpts.set_clean_session(true);
+    connOpts.set_user_name(username);
+    connOpts.set_password(password);
+    connOpts.set_ssl(ssl_options);
+    struct timespec ts;
+    try
+    {
+        PublisherCallback callback;
+        client.set_callback(callback);
+
+        mqtt::token_ptr connectionToken = client.connect(connOpts);
+        connectionToken->wait();
+
+        while (true)
+        {
+            int sem_try=0;
+            if (clock_gettime(CLOCK_REALTIME, &ts) == -1 && tui)
+            printf("clock_gettime");
+            ts.tv_sec +=1;
+            mqtt_msg_t temp_mess;
+            sem_try = sem_timedwait(&mutex_lock_main_thread_mqtt, &ts);
+            if (sem_try == 0){
+                temp_mess=mqtt_msg;
+                sem_post(&mutex_unlock_main_thread_mqtt);
+                Json::Value event;
+                event["sq"]=temp_mess.sq;
+                event["freq"]=temp_mess.freq;
+                Json::StreamWriterBuilder builder;
+                mqtt::message_ptr pubMessage = mqtt::make_message(TOPIC1,Json::writeString(builder, event), QOS, false);
+                client.publish(pubMessage)->wait();
+                
+            }
+        }
+
+        mqtt::token_ptr disconnectionToken = client.disconnect();
+        disconnectionToken->wait();
+    }
+    catch (const mqtt::exception& ex)
+    {
+        std::cerr << "MQTT Exception: " << ex.what() << std::endl;
+        return 0;
+    }
+
+    return 0;
+}
 void* belysning_control_thread(void*){
     struct timespec ts;
     struct timeval tv;
-    long int start_time;
-    long int stop_time;
+
     long int sq_start_time=0;
     long int sq_stop_time=0;
     bool sq_status = false;
     long int audio_start_time=0;
     bool active=false;
+    int status_data_temp=0;
     gettimeofday(&tv, 0);
     start_time=tv.tv_sec;
     stop_time=tv.tv_sec+1;
@@ -189,22 +279,24 @@ void* belysning_control_thread(void*){
         if (clock_gettime(CLOCK_REALTIME, &ts) == -1 && tui)
             printf("clock_gettime");
         ts.tv_sec +=1;
-        sem_try = sem_timedwait(&mutex_sem, &ts);
+        sem_try = sem_timedwait(&mutex_lock_main_thread, &ts);
         if (sem_try == 0){
-            if (sq_status == false && (status_data & 1)){
+            status_data_temp=status_data;
+            sem_post(&mutex_unlock_main_thread);
+            if (sq_status == false && (status_data_temp & 1)){
                 sq_start_time = tv.tv_sec;
                 sq_status = true;
             }
-            if (sq_status == true && !(status_data & 1)){
+            if (sq_status == true && !(status_data_temp & 1)){
                 sq_stop_time = tv.tv_sec;
                 sq_status = false;
             }
             //printf("ST %u, %u ",(status_data & 1),(status_data >> 1));
-            if ( (status_data >> 1) ){
+            if ( (status_data_temp >> 1) ){
                 audio_start_time = tv.tv_sec;   
             }
             prolong = true;
-            sem_post(&spooler_sem);
+            
         }
         if (sq_status && sq_start_time < tv.tv_sec){
             prolong = true;
@@ -244,8 +336,10 @@ void* belysning_control_thread(void*){
             if (tui)
                 printf("Stop\n");
         }
+#ifdef GPIOX
         if (active)
             if ((stop_time<tv.tv_sec+bel_blink_time) && tv.tv_sec % 2 && bel_blink_time ){
+
                 gpiod_line_set_value(led_control, 0);  
                 gpiod_line_set_value(relay1, 1); 
             }else{
@@ -256,6 +350,7 @@ void* belysning_control_thread(void*){
             gpiod_line_set_value(led_control, 0); 
             gpiod_line_set_value(relay1, 1);  
         }
+ #endif
     }
     return 0;
 }
@@ -678,26 +773,37 @@ void* demodulate(void* params) {
                             }
                             
                             if ((abs(waveout)>bel_wave_out_level && channel->wavein[j]>bel_wave_in_level) ){
-                                gpiod_line_set_value(led_vox, 1);                                
+#ifdef GPIOX
+                                gpiod_line_set_value(led_vox, 1);     
+#endif                           
                                 audio_status=1;
                             }else{
+#ifdef GPIOX
                                 gpiod_line_set_value(led_vox, 0);
+#endif
                                 audio_status=0;
 
                             }
+                            squelch_status = channel->freqlist[channel->freq_idx].oldstatus & 1;
                             int temp_status = squelch_status + (audio_status << 1);
-                            if (status_data_old !=temp_status){
+
+                            if (channel->freqlist[channel->freq_idx].oldstatus !=temp_status &&  (fparms->banbel)){
                                 pthread_mutex_lock(&lock_data); 
+                                //fprintf(stderr,"HEJ %i,%i,%f,%f\n",channel->freqlist[channel->freq_idx].oldstatus ,temp_status,abs(waveout),channel->wavein[j]);
                                 status_data = temp_status;
-                                if (sem_post (&mutex_sem) == -1) {
-                                    perror ("sem_post: mutex_sem"); exit (1);
+                                if (sem_post (&mutex_lock_main_thread) == -1) {
+                                    perror ("sem_post: mutex_lock_main_thread"); exit (1);
                                 }
-                                if (sem_wait(&spooler_sem) == -1){
-                                    perror ("sem_post: spooler_sem"); exit (1);
+                                if (sem_wait(&mutex_unlock_main_thread) == -1){
+                                    perror ("sem_post: mutex_unlock_main_thread"); exit (1);
                                 }
-                                status_data_old = status_data;
+
+                                //channel->freqlist[channel->freq_idx].oldstatus = temp_status;;
                                 pthread_mutex_unlock(&lock_data); 
+                                
+
                             }
+                            
                         }
 #ifdef NFM
                         else if (fparms->modulation == MOD_NFM) {
@@ -777,26 +883,54 @@ void* demodulate(void* params) {
                         //GOTOXY(i * 10, device_num * 17 + dev->row + 3);
                         //printf("%4.0f/%3.0f%c ", level_to_dBFS(fparms->squelch.signal_level()), level_to_dBFS(fparms->squelch.noise_level()), symbol);
                     }
-                    if (symbol=='*'){
-                        gpiod_line_set_value(led_squ, 1);
-                        squelch_status = 1;
-                    }else{
-                        gpiod_line_set_value(led_squ, 0);
-                        squelch_status = 0;
-                    }
-                    int temp_status = squelch_status + (audio_status << 1);
-                    if (status_data_old !=temp_status){
-                        pthread_mutex_lock(&lock_data); 
-                        status_data = temp_status;
-                        if (sem_post (&mutex_sem) == -1) {
-                            perror ("sem_post: mutex_sem"); exit (1);
+                    //BANBEL
+                    
+                        if (symbol=='*'){
+#ifdef GPIOX
+                            gpiod_line_set_value(led_squ, 1);
+#endif
+                            squelch_status = 1;
+                        }else{
+#ifdef GPIOX
+                            gpiod_line_set_value(led_squ, 0);
+#endif
+                            squelch_status = 0;
                         }
-                        if (sem_wait(&spooler_sem) == -1){
-                            perror ("sem_post: spooler_sem"); exit (1);
+                        int temp_status = squelch_status + (audio_status << 1);
+                        if (channel->freqlist[channel->freq_idx].oldstatus != temp_status){
+                            //fprintf(stderr,"BABEL %i %i\n",fparms->banbel,temp_status);
+                            if (fparms->banbel){
+                                pthread_mutex_lock(&lock_data); 
+                                status_data = temp_status;
+                                if (sem_post (&mutex_lock_main_thread) == -1) {
+                                    perror ("sem_post: mutex_lock_main_thread"); exit (1);
+                                }
+                                
+                                if (sem_wait(&mutex_unlock_main_thread) == -1){
+                                    perror ("sem_post: mutex_unlock_main_thread"); exit (1);
+                                }
+                                pthread_mutex_unlock(&lock_data);
+                            }
+                           
+                            if ((temp_status & 1) != (channel->freqlist[channel->freq_idx].oldstatus & 1)) {
+                                pthread_mutex_lock(&lock_mqtt_data);
+                                if (sem_post (&mutex_lock_main_thread_mqtt) == -1) {
+                                    perror ("sem_post: mutex_lock_main_thread"); exit (1);
+                                }
+                                mqtt_msg.audio =(audio_status << 1);
+                                mqtt_msg.sq = squelch_status;
+                                mqtt_msg.freq = channel->freqlist->frequency;
+
+                                if (sem_wait(&mutex_unlock_main_thread_mqtt) == -1){
+                                    perror ("sem_post: mutex_unlock_main_thread"); exit (1);
+                                }
+                                pthread_mutex_unlock(&lock_mqtt_data);
+                            }
+                            channel->freqlist[channel->freq_idx].oldstatus = temp_status;
+                            //Here for mqtt
+
                         }
-                        status_data_old = status_data;
-                        pthread_mutex_unlock(&lock_data); 
-                    }
+
                     fflush(stdout);
                 }
 
@@ -863,20 +997,25 @@ int main(int argc, char* argv[]) {
 
     // initialization
 
-    sem_init (&mutex_sem, 1, 0);
-    sem_init (&spooler_sem, 1, 0);
+    sem_init (&mutex_lock_main_thread, 1, 0);
+    sem_init (&mutex_unlock_main_thread, 1, 0);
     if (pthread_mutex_init(&lock_data, NULL) != 0) { 
         printf("\n mutex init has failed\n"); 
         return 1; 
     } 
+    if (pthread_mutex_init(&lock_mqtt_data, NULL) != 0) { 
+        printf("\n mutex init has failed\n"); 
+        return 1; 
+    } 
     printf("SEM and locks OPEN\n");
-
+#ifdef GPIOX
 	char const *chipname = "gpiochip0";
 	unsigned int gpio16 = 16;
     unsigned int gpio20 = 20;
     unsigned int gpio26 = 26;
     unsigned int gpio24 = 24;
     unsigned int gpio25 = 25;
+
 	chip = gpiod_chip_open_by_name(chipname);
     if (!chip) {
         perror("gpiod_chip_open_by_name");
@@ -887,6 +1026,8 @@ int main(int argc, char* argv[]) {
     led_control = gpiod_chip_get_line(chip, gpio16);
     relay1 = gpiod_chip_get_line(chip, gpio25);
     relay2 = gpiod_chip_get_line(chip, gpio24);
+#endif
+#ifdef GPIOX
 	gpiod_line_request_output(led_squ, "Consumer1", 0);
 	gpiod_line_set_value(led_squ, 0);
     gpiod_line_request_output(led_vox, "Consumer2", 0);
@@ -897,6 +1038,7 @@ int main(int argc, char* argv[]) {
 	gpiod_line_set_value(relay1, 1);
     gpiod_line_request_output(relay2, "Consumer5", 0);
 	gpiod_line_set_value(relay2, 1);
+#endif
 #pragma GCC diagnostic ignored "-Wwrite-strings"
     char* cfgfile = CFGFILE;
     char* pidfile = PIDFILE;
@@ -1032,6 +1174,16 @@ int main(int argc, char* argv[]) {
             bel_wave_in_level=(float)(root["bel_wave_in_level"]);
         if (root.exists("bel_prolong_time"))
             bel_prolong_time=(int)(root["bel_prolong_time"]);
+        //MQTT    
+        if (root.exists("bel_mqtt_server"))
+           bel_mqtt_server = strdup(root["bel_mqtt_server"]);
+        if (root.exists("bel_mqtt_client_id"))
+           bel_mqtt_client_id = strdup(root["bel_mqtt_client_id"]);
+        if (root.exists("bel_mqtt_user_id"))
+           bel_mqtt_user_id= strdup(root["bel_mqtt_user_id"]);
+        if (root.exists("bel_mqtt_server"))
+           bel_mqtt_password= strdup(root["bel_mqtt_password"]);
+
         Setting& devs = config.lookup("devices");
         device_count = devs.getLength();
         if (device_count < 1) {
@@ -1227,10 +1379,10 @@ int main(int argc, char* argv[]) {
         }
     }
 
-    int timeout = 50;  // 5 seconds
-    while ((devices_running = count_devices_running()) != device_count && timeout > 0) {
+    int timeout_device = 50;  // 5 seconds
+    while ((devices_running = count_devices_running()) != device_count && timeout_device > 0) {
         SLEEP(100);
-        timeout--;
+        timeout_device--;
     }
     if ((devices_running = count_devices_running()) != device_count) {
         log(LOG_ERR, "%d device(s) failed to initialize - aborting\n", device_count - devices_running);
@@ -1253,7 +1405,9 @@ int main(int argc, char* argv[]) {
         }
     }
     THREAD belysning_control_check;
+    THREAD mqtt_control_check;
     pthread_create(&belysning_control_check, NULL, &belysning_control_thread, NULL);
+    pthread_create(&mqtt_control_check, NULL, &mqtt_control_thread, NULL);
     THREAD output_check;
     pthread_create(&output_check, NULL, &output_check_thread, NULL);
 

+ 7 - 1
src/rtl_airband.h

@@ -231,6 +231,7 @@ struct freq_t {
     LowpassFilter lowpass_filter;  // lowpass filter, applied to I/Q after derotation, set at bandwidth/2 to remove out of band noise
     enum modulations modulation;
     int banbel;
+    int oldstatus;
 };
 struct channel_t {
     float wavein[WAVE_LEN];      // FFT output waveform
@@ -261,6 +262,7 @@ struct channel_t {
     int lowpass;             // lowpass filter cutoff
     lame_t lame;             // Context for LAME MP3 encoding if needed
     unsigned char* lamebuf;  // Buffer used by each lame encode
+    int banbel;
 };
 
 enum rec_modes { R_MULTICHANNEL, R_SCAN };
@@ -285,7 +287,11 @@ struct device_t {
     enum rec_modes mode;
     size_t output_overrun_count;
 };
-
+struct mqtt_msg_t {
+    int sq;
+    int audio;
+    int freq;
+};
 struct mixinput_t {
     float* wavein;
     float ampfactor;