Графический nrf сканер на raspberry pi.

Тема в разделе "Raspberry Pi", создана пользователем Un_ka, 14 май 2020.

?

Добавить глушилку по нажатию на столбик?

  1. Да

    100,0%
  2. Нет

    0 голосов
    0,0%
  1. Un_ka

    Un_ka Гуру

    Существует простенький код на c/c++ сканера частот nrf, представленный в этой статье.
    Однажды я подумал, что не плохо было бы как-то визуализировать бездушные цифры, не помещающиеся в строку консоли. Тем более я приглядел графическую, мультифункциональную библиотеку sfml.
    Выглядит программа вот так:
    Screenshot_2020-05-13-12-53-30.png
    Основная проблема, с которой я столкнулся, заключалась в том, что для работы с шиной SPI на Raspberry требуются права root, которые нельзя дать программе в графической оболочке. Но спустя некоторое время я нашёл решение. Чтобы программа в графической оболочке запускалась под root она должна :
    1. пренадлежать пользователю root
    2. вежливо попросить эти права.
    Первое решается таким вот скриптом:
    Код (Bash):
    #! /bin/bash
    sudo chown root:root $1
    sudo chmod 6775 $1
    (Если хотите единожды использовать его подставте вместо $1 имя вашего исполняемого фаила.
    Второе:
    Код (C++):
    if (setuid(0)==0)
    {

    }else{
    //printf("\n all is bed");
    fail=1;
    while(1);
    }
    Благодаря бесконечному циклу программа не схлопнется при запуске, если вдруг забыт первый пункт.
    Код (C++):
         

    /*
    cd /home/ftp_user/cpp/graf
    sudo g++ -c graf4.cpp
    sudo g++ graf4.o -o graf4e -lsfml-graphics -lsfml-window -lsfml-system

    */

    //#include <unistd.h>
    #include <SFML/Graphics.hpp>
    #include <SFML/System.hpp>
    #include <vector>
    #include <iostream>
    #include <cstdlib>
    #include<time.h>
    #include <fstream>
    #include <sstream>
    #include <string>
    #include <thread>



    /*
    * Конфигурация оборудования
    */






    volatile bool up=1;
    volatile int *general=new volatile int [126];

    void strt(void);

    struct Cand
    {
    int x;
    int y;
    int angle;
    };




    class Button{

    private:

    int Bmx,Bmy;
    int x_pos;
    int y_pos;
    int x_scale;
    int y_scale;
    sf::Font shr;
    sf::String typ;
    sf::Color cb;
      sf::Color ct;

    public:
    sf::RectangleShape bot;
    sf::Text txt;
            // икс  .   игрек  .    размер
    Button( int x_pos1, int y_pos1 ,int x_scale1, int y_scale1,sf::String typ1, sf::Color cb1, sf::Color ct1 , sf::Font shr1 ){
    x_pos= x_pos1;
    y_pos= y_pos1;
    x_scale= x_scale1;
    y_scale= y_scale1;
    typ= typ1;
    cb= cb1;
    cb= cb1;
    shr=shr1;

    }


    void create()
    {

    bot.setSize( sf::Vector2f(x_scale,y_scale));
    bot.setPosition(x_pos,y_pos);
    bot.setFillColor(cb);

    txt.setString(typ);
    txt.setCharacterSize(20);
    txt.setFillColor(ct);
    txt.setFont(shr);
    txt.setPosition(x_pos+(x_scale/10),y_pos+(y_scale/2)-20);

    }
    bool isClick(){

    sf::Event sob;
        if (sob.mouseButton.button == sf::Mouse::Left)
           {
      Bmx=int(abs(sob.mouseButton.x));
      Bmy=int(abs(sob.mouseButton.y));
         
           }
       
        if((Bmx >x_pos && Bmx < ( x_pos+x_scale) )&&(Bmy > y_pos && Bmy < ( y_pos+y_scale) ))
      {
      return 1;
      }else{
      return 0;
      }
     
    }
    void draw( sf::RenderWindow &W ){
    W.draw(bot);
    W.draw(txt);
    }
    };




    const int per0=50; //20 герц
    const int per1=100; //

    sf::Clock gen; // starts the clock
    int milliss()
    {
    float t=gen.getElapsedTime().asMilliseconds();
    //float t=gen.getElapsedTime().asMicroseconds();
    return (int)abs(t);
    }
    //______ГЛАВНАЯ_ФУНКЦИЯ__________
    int main() {
    // stringstream stream;
    //stream << "sudo ./home/dima/graf/nrf_writer_EXE " ;
    // разделитель, отделяющий программу от аргумента << "myargument";
    // system(stream.str().c_str());
    srand(time(NULL));
    int last0,last1, last_val=0,st_st=1,size_bar=0;
    volatile int* val= new volatile int [126];
    std::string s;
    sf::Font font;
    font.loadFromFile("/home/dima/fonts/arial.ttf");

    std::thread thr(strt);
    thr.detach();

    sf::RenderWindow window(sf::VideoMode(1020, 400), "Сканер частот nrf24l01");// x,y
      // sf::Clock clock;
     
       last0=milliss();
       last1=milliss();
         sf::RectangleShape osh(sf::Vector2f(50, 100));
         sf::RectangleShape bar(sf::Vector2f(340, 20));
         sf::RectangleShape fon(sf::Vector2f(500, 24));
    osh.setSize( sf::Vector2f(100,20));
    osh.setPosition(360,200);
    bar.setPosition(2,228);
    fon.setPosition(0,226);
    fon.setFillColor(sf::Color::Yellow);
    bar.setFillColor(sf::Color::Blue);
    Button key(600,100,150,80,L"Кнопка",sf::Color(240,30,45), sf::Color(1,70,95),font );
    key.create();

         while (window.isOpen()) {
         sf::Event event;
       
         if(milliss()-last0>per0){
         while (window.pollEvent(event)) {
          if (event.type == sf::Event::Closed) window.close();
          }
          if(milliss()-last1>per1){
          if(up)
         {
          val=general;
         }

       
       
       
          }
       
       
       
             sf::RectangleShape *ppd=new sf::RectangleShape [126];
    //sf::RectangleShape ppd(sf::Vector2f(50, 100));
          for(int n=0;n<126;n++){
    ppd[n].setSize( sf::Vector2f(7,1+10*val[n]));
    ppd[n].setPosition(1+(8*n),170);
    ppd[n].setRotation(180.f);
       }
    //  ppd.setPosition(50+(100*n),0);
    if(st_st){
    size_bar=0;
    st_st=0;
    }
    size_bar+=5;
    bar.setSize( sf::Vector2f(1+size_bar,20));
       
        // Отрисовка окна
    window.clear(sf::Color::Black);
       for(int n =0;n<126;n++){window.draw(ppd[n]);}
    //window.draw(osh);
    // window.draw(fon);
    //window.draw(bar);
    //key.draw(window);
    window.display();
     
         last0=milliss();

        }}
        return 0;
    }
             
    Код (C++):
    #include <cstdlib>
    #include <iostream>
    #include <stdio.h>
    #include <sys/types.h>
    #include <unistd.h>
    #include <RF24/nRF24L01.h>
    /*
    * Подключаем библиотеку для работы с nRF24L01+
    */

    #include <RF24/RF24.h>



    /*
    * Конфигурация оборудования
    */

    #define BCM_PIN 25
    #define SPI_DEV 0
    #define NUM_CHANNELS 126

    /*
    * Информация о канале
    */



    void strt() {
    uint8_t values[NUM_CHANNELS];
    const int numReps = 100;
    extern volatile int *general;
    extern volatile bool up;
      /*
       * Создаём объект radio для работы с библиотекой RF24,
       * указывая номера вывода CE и SPI порта
       */

       if (setuid(0)==0)
    {

    //printf("My UID is: %d. My GID is: %d\n \t g", getuid() , getgid());
    }else{
    //printf("\n all is bed");
    while(1);
    }
     
     
      RF24 radio(BCM_PIN, SPI_DEV);

      /*
       * Инициируем работу nRF24L01+
       */

      radio.begin();

      radio.setAutoAck(false);

      /*
       * Вход в режиме ожидания
       */

      radio.startListening();
      radio.stopListening();

      /*
       * Дамп конфигурации RF для отладки
       */

      //radio.printDetails();

      /*
       * Распечатка заголовка, верхний и нижний разряд
       */



      while (1) {
        /*
         * Очистка значений измерений
         */

        memset(values, 0, sizeof(values));

        /*
         * Сканирование всех каналов numReps раз
         */

        for (int k = 0; k < numReps; ++k) {
          for (int i = 0; i < NUM_CHANNELS; ++i) {

            /*
             * Выбор канала
             */

            radio.setChannel(i);

            /*
             * Послушать немного
             */

            radio.startListening();
            delayMicroseconds(128);
            radio.stopListening();

            /*
             * Проверка наличия несущей частоты на выбранном канале (частоте).
             */

            if (radio.testCarrier()) {
              ++values[i];
            }
          }
        }
        /*
         * Распечатка измерения канала в одну шестнадцатеричную цифру
         */

         up=0;
        for (int i = 0; i < NUM_CHANNELS; ++i) {
         // printf("%x", min(0xf, (values[i] & 0xf)));
          general[i]= std::min(0xf, (values[i] & 0xf));
        }
        up=1;
      }

    }
    Компиляция этого добра заслуживает отдельного рассказа.
    Всё должно быть в отдельной папке!
    Итак компилируем код для nrf:
    Код (Bash):
    g++ -Ofast -Wall -c rfsc.cpp -lrf24
    И код графической оболочки:
    Код (Bash):
    g++ -c view.cpp
    И собираем:
    Код (Bash):
    g++ *.o -o nrfGUI -lsfml-graphics -lsfml-window -lsfml-system -fopenmp  -lrf24  
    Не забудте про пункт 1!
    Знаю, что копипастить иногда не удобно, поэтому оставляю фаилы во вложениях.
     

    Вложения:

    • view.cpp
      Размер файла:
      3,9 КБ
      Просмотров:
      254
    • rfsc.cpp
      Размер файла:
      2,4 КБ
      Просмотров:
      229
    arkadyf нравится это.
  2. parovoZZ

    parovoZZ Гуру

    Всё хорошо, но только не сказано, что ни один чип nRF24 не умеет измерять УРОВЕНЬ сигнала. Только наличие несущей. Поэтому приведённая гистограмма абсолютно бесполезна для анализа уровня зашумленности выбранного канала. Для такой оценки в диапазоне работы Wi-Fi 2.4 ГГц пользуйтесь утилитой inssider
    insider.png
     
    Igor68 и Un_ka нравится это.
  3. Un_ka

    Un_ka Гуру

    Согласен, но утилита, которую вы рекомендуете доступна только на Windows и ios. Wi-fi есть только на ноутбуках. А вот во всех android смартфонах есть wi-fi и доступные приложения Network Analayzer и analiti. В первом можно ещё ip малины узнать.
     
    Igor68 нравится это.
  4. Из чего это следует? Если владелец программы не root, а при сборке приложения простым пользователем владелец получившегося исполняемого файла - пользователь, и права на исполнение разрешены владельцу группе и всем остальным. Почему-же тогда его нельзя выполнить с правами супер пользователя?

    Собрал простой пример, в котором проверяю на запуск от супер пользователя, если запущен от простого пользователя, то форкаю процесс и в дочернем процессе запускаю то-же приложение уже от супер пользователя.
    В приложении запущенном с правами супер пользователя в графическом окне отображаю PID

    Код (C):
    #include <stdio.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <SFML/Graphics.hpp>

    int main(int argc, char** argv) {
      if (getuid() != 0) {
        pid_t pid;
        if ((pid = fork()) == 0) {
          char* args[] = { "/usr/bin/sudo", "/home/alex/test-sfml", NULL };
          execve(args[0], args, environ);
        } else {
          waitpid(pid, NULL, 0);
        }
      } else {
        // Это тестовый код для отображения графики
        char tmp[64];
        sprintf(tmp, "My pid: %d", getpid());
        sf::RenderWindow window(sf::VideoMode(200, 48), "SFML test");
        sf::Font font;
        font.loadFromFile("/home/alex/arial.ttf");
        sf::Text text;
        text.setFont(font);
        text.setString(tmp);
        text.setCharacterSize(24);
        text.setFillColor(sf::Color::Red);
        text.setPosition(10, 16);
        window.draw(text);
        window.display();
        while (window.isOpen()) {
          sf::Event event;
          while (window.pollEvent(event)) {
            if (event.type == sf::Event::Closed) {
              window.close();
            }
          }
        }
      }
      return 0;
    }
    [​IMG]

    Смотрю в процессах владельца этого процесса.
    Код (Text):
    alex@rpi3b:~$ ps -fp 5309
    UID        PID  PPID  C STIME TTY          TIME CMD
    root      5309  5308 99 16:55 pts/0    00:00:45 /home/alex/test-sfml
     
    Igor68 и Un_ka нравится это.
  5. Igor68

    Igor68 Гуру

    Правда на малине я пользуюсь изменением прав на самом устройстве (просто на вскидку):
    Код (Bash):
    chmod 777 /dev/i2c-1
    chmod 777 /dev/ttyUSB0
    chmod 777 /dev/video0
    прописав в /etc/rc.local. На устройстве я не "засекречиваю" доступ. Но можно и добавлением в группу пользователя. Мне удобнее первое.
     
  6. Un_ka

    Un_ka Гуру

    Я добавлял, там похоже сама библиотека требует, чтобы процесс был запущен от root. После моих манипуляций в консоли программа подсвечивается так:
    IMG_20200522_133319.jpg
     
  7. Igor68

    Igor68 Гуру

    так измените права на сами программные модули... если это не кропотливо.