• Bonsoir, je me rends juste compte que les notifications des nouveaux messages étaient limitées aux membres actifs dans les 30 derniers jours. Donc, j'ai supprimé cette option. En espérant que vous aurez bien les notifications attendues. Merci pour votre patience. Yves

lecteur portable low cost balise de signalement électronique

yves.morele

Membre Sénior
Bonjour,

je me suis dit que pour vérifier réellement le fonctionnement d'une balise de signalement il faut lire et décoder la trame émise par celle-ci. il existe des scanners autonome (pas donnés) ou des soft sur PC ou autre mais pour moi le plus simple est d'avoir ça dans une poche et sans contrainte.

j'ai donc fait un système a base de nodemcu ESP8266 avec écran oled SSD1306 le tout pour moins de 20€.

sur l'affichage on retrouve l'identifiant de la balise, les coordonnées latitude et longitude ainsi que la hauteur.

pour l'instant pas de data log des données. c'est du brut possible d'améliorer (led etc....)

IMG_20210809_164213_4.jpgIMG_20210809_164156_9.jpg
 

Fichiers joints

  • IMG_20210809_164213_4.jpg
    IMG_20210809_164213_4.jpg
    555,8 KB · Vues: 101
  • IMG_20210809_164156_9.jpg
    IMG_20210809_164156_9.jpg
    605,3 KB · Vues: 102
Bonjour
le câblage et le code (provisoire)
Yves

cablage nodemcu.jpg
/*
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.


This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.


You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
/*
Packet sniffer


Reçoit et décode les données émises par une balise et les affiche dans la console.


Fonctionne avec n'importe quelle carte à base ESP32 et https://github.com/esp8266/Arduino


* ** Limitation du SDK : la trame ne peut être décodée en totalité (ID, LAT, LONG et AlT si ssid court) **
*/
/**
Bibliothéque
*/
#include <Arduino.h>
#include <Wire.h> // Only needed for Arduino 1.6.5 and earlier
#include "SSD1306Ascii.h"
#include "SSD1306AsciiWire.h"
#include <user_interface.h>
/**
ecran oled
*/


#define I2C_ADDRESS 0x3C
SSD1306AsciiWire oled;


/**
variable
*/
int idbalise = 0;
int ecranacceuil = 0;
int incomingByte = 0;




extern "C" {
}


#define DATA_LENGTH 112
#define TYPE_MANAGEMENT 0x00
#define TYPE_CONTROL 0x01
#define TYPE_DATA 0x02
#define SUBTYPE_PROBE_REQUEST 0x04


struct RxControl {
signed rssi: 8; // signal intensity of packet
unsigned rate: 4;
unsigned is_group: 1;
unsigned: 1;
unsigned sig_mode: 2; // 0:is 11n packet; 1:is not 11n packet;
unsigned legacy_length: 12; // if not 11n packet, shows length of packet.
unsigned damatch0: 1;
unsigned damatch1: 1;
unsigned bssidmatch0: 1;
unsigned bssidmatch1: 1;
unsigned MCS: 7; // if is 11n packet, shows the modulation and code used (range from 0 to 76)
unsigned CWB: 1; // if is 11n packet, shows if is HT40 packet or not
unsigned HT_length: 16; // if is 11n packet, shows length of packet.
unsigned Smoothing: 1;
unsigned Not_Sounding: 1;
unsigned: 1;
unsigned Aggregation: 1;
unsigned STBC: 2;
unsigned FEC_CODING: 1; // if is 11n packet, shows if is LDPC packet or not.
unsigned SGI: 1;
unsigned rxend_state: 8;
unsigned ampdu_cnt: 8;
unsigned channel: 6; //which channel this packet in.
unsigned: 12;
};


struct SnifferPacket {
struct RxControl rx_ctrl;
uint8_t data[DATA_LENGTH];
uint16_t cnt;
uint16_t len;
};


/**
Enumeration des types de données à envoyer
*/
enum DATA_TYPE : uint8_t {
RESERVED = 0,
PROTOCOL_VERSION = 1,
ID_FR = 2,
ID_ANSI_CTA = 3,
LATITUDE = 4, // In WS84 in degree * 1e5
LONGITUDE = 5, // In WS84 in degree * 1e5
ALTITUDE = 6, // In MSL in m
HEIGTH = 7, // From Home in m
HOME_LATITUDE = 8, // In WS84 in degree * 1e5
HOME_LONGITUDE = 9, // In WS84 in degree * 1e5
GROUND_SPEED = 10, // In m/s
HEADING = 11, // Heading in degree from north 0 to 359.
NOT_DEFINED_END = 12,
};


/**
Tableau TLV (TYPE, LENGTH, VALUE) avec les tailles attendu des différents type données.
*/
static constexpr uint8_t TLV_LENGTH[] {
0, // [DATA_TYPE::RESERVED]
1, // [DATA_TYPE::pROTOCOL_VERSION]
30, // [DATA_TYPE::ID_FR]
0, // [DATA_TYPE::ID_ANSI_CTA]
4, // [DATA_TYPE::LATITUDE]
4, // [DATA_TYPE::LONGITUDE]
2, // [DATA_TYPE::ALTITUDE]
2, // [DATA_TYPE::HEIGTH]
4, // [DATA_TYPE::HOME_LATITUDE]
4, // [DATA_TYPE::HOME_LONGITUDE]
1, // [DATA_TYPE::GROUND_SPEED]
2, // [DATA_TYPE::HEADING]
};




void showMetadata(SnifferPacket *snifferPacket) {


unsigned int frameControl = ((unsigned int)snifferPacket->data[1] << 8) + snifferPacket->data[0];
uint8_t frameType = (frameControl & 0b0000000000001100) >> 2;
uint8_t frameSubType = (frameControl & 0b0000000011110000) >> 4;
uint8_t SSID_length = snifferPacket->data[40 - 4];
uint8_t offset_OUI = 41 - 4 + SSID_length + 1;


const uint8_t FRAME_OUI[3] = {0x6A, 0x5C, 0x35};


// Filter OUI from 6A:5C:35
if (snifferPacket->data[offset_OUI + 1] != FRAME_OUI[0] && snifferPacket->data[offset_OUI + 2] != FRAME_OUI[1] && snifferPacket->data[offset_OUI + 3] != FRAME_OUI[2])
return;






char addr[] = "00:00:00:00:00:00";
getMAC(addr, snifferPacket->data, 10);


// Informations supplémentaires
Serial.print(" RSSI: "); Serial.print(snifferPacket->rx_ctrl.rssi, DEC);
Serial.print(" Ch: "); Serial.print(wifi_get_channel());
//Serial.print(" MAC: "); Serial.print(addr);
Serial.print(" AP: "); printDataSpan(41 - 4, SSID_length, snifferPacket->data);


// ID balise
Serial.print(" ID: "); printDataSpan(offset_OUI + 4 + 6, TLV_LENGTH[ID_FR] , snifferPacket->data);
uint16_t offset = offset_OUI + 4 + 6 + TLV_LENGTH[ID_FR] + 2; // +2 : Type + Lenght


idbalise = (ID_FR);
// Latitude
Serial.print(" LAT: "); printCoordinatesLAT(offset, TLV_LENGTH[LATITUDE] , snifferPacket->data);
offset += TLV_LENGTH[LATITUDE] + 2;


// Longitude
Serial.print(" LON: "); printCoordinatesLONG(offset, TLV_LENGTH[LONGITUDE] , snifferPacket->data); //Serial.println();
offset += TLV_LENGTH[LONGITUDE] + 2;


//Altitude msl
Serial.print(" ALTmsl: "); printAltitude(offset, TLV_LENGTH[ALTITUDE] , snifferPacket->data); //Serial.println();
offset += TLV_LENGTH[ALTITUDE] + 2;
// Serial.print(" AltHome: "); printAltitude(offset, TLV_LENGTH[HEIGTH] , snifferPacket->data); //Serial.println();
offset += TLV_LENGTH[HEIGTH] + 2;


Serial.println();

}


/**
Callback for promiscuous mode
*/


void ICACHE_FLASH_ATTR sniffer_callback(uint8_t *buffer, uint16_t length) {
struct SnifferPacket *snifferPacket = (struct SnifferPacket*) buffer;
showMetadata(snifferPacket);
}


void printDataSpan(uint16_t start, uint16_t size, uint8_t* data) {
for (uint16_t i = start+10; i < DATA_LENGTH && i < start + size; i++) {
Serial.write(data);
oled.write(data);



}
oled.println();
}


void printDataSpanID(uint16_t start, uint16_t size, uint8_t* data) {
for (uint16_t i = start; i < DATA_LENGTH && i < start + size; i++) {
Serial.write(data);
incomingByte = Serial.read();
}
}
void printCoordinatesLAT(uint16_t start, uint16_t size, uint8_t* data) {
uint8_t count = size - 1;
int data_value = 0;
//Serial.print(" data_value="); Serial.print(data_value); Serial.print(" neg=");
bool neg_number = data[start] > 0x7F;
//Serial.print(neg_number);Serial.print(" ");


for (uint16_t i = start; i < DATA_LENGTH && i < start + size; i++) {
//Serial.print(count); Serial.print("-");
data_value += (data) << (8 * count);
count--;
}


if (neg_number) {
data_value = (0xFFFFFFFF & ~data_value) + 1;
data_value *= -1;
}


Serial.print(double(data_value) * 0.00001 , 5);

oled.print( "LAT :");


oled.println( String(double(data_value) * 0.00001 , 5));
oled.println();
}




void printCoordinatesLONG(uint16_t start, uint16_t size, uint8_t* data) {
uint8_t count = size - 1;
int data_value = 0;
//Serial.print(" data_value="); Serial.print(data_value); Serial.print(" neg=");
bool neg_number = data[start] > 0x7F;
//Serial.print(neg_number);Serial.print(" ");


for (uint16_t i = start; i < DATA_LENGTH && i < start + size; i++) {
//Serial.print(count); Serial.print("-");
data_value += (data) << (8 * count);
count--;
}


if (neg_number) {
data_value = (0xFFFFFFFF & ~data_value) + 1;
data_value *= -1;
}


Serial.print(double(data_value) * 0.00001 , 5);

oled.print( "LONG :");


oled.println( String(double(data_value) * 0.00001 , 5));
oled.println();
}




void printAltitude(uint16_t start, uint16_t size, uint8_t* data) {
uint8_t count = size - 1;
int data_value = 0;
bool neg_number = data[start] > 0x7F;
//Serial.print(neg_number);Serial.print(" ");


for (uint16_t i = start; i < DATA_LENGTH && i < start + size; i++) {
//Serial.print(count); Serial.print("-");
data_value += (data) << (8 * count);
count--;
}


if (neg_number) {
data_value = (0xFFFF & ~data_value) + 1;
data_value *= -1;
}


Serial.print(data_value);
oled.print( "Altitude :");


oled.println(data_value);
}
void getMAC(char *addr, uint8_t* data, uint16_t offset) {
sprintf(addr, "%02x:%02x:%02x:%02x:%02x:%02x", data[offset + 0], data[offset + 1], data[offset + 2], data[offset + 3], data[offset + 4], data[offset + 5]);
}




#define DISABLE 0
#define ENABLE 1


void setup() {
// set the WiFi chip to "promiscuous" mode aka monitor mode
Serial.begin(115200);
Serial.print("début sniffer");
delay(10);
Wire.begin();
oled.begin(&Adafruit128x64, I2C_ADDRESS);
oled.setFont(Adafruit5x7);
oled.setScrollMode(SCROLL_MODE_AUTO);
if (ecranacceuil == 0) {
affiche ();
}


Serial.print("début sniffer");




wifi_set_opmode(STATION_MODE);
wifi_set_channel(6);
wifi_promiscuous_enable(DISABLE);
delay(10);
wifi_set_promiscuous_rx_cb(sniffer_callback);
delay(10);
wifi_promiscuous_enable(ENABLE);
}


void loop() {
void showMetadata(SnifferPacket * snifferPacket);




//void affichedata ();
delay(2000);
// oled.clear();
}


void affiche () {
if (ecranacceuil == 0) {
oled.clear();
oled.set2X();


oled.println("SCANNER");
oled.setCursor(1, 200);
oled.print("BALISE DGAC");

delay(2000);
oled.clear();
oled.set1X();


}
else {


oled.clear();


}
ecranacceuil = 1;
}


void affichedata () {


oled.clear();
oled.set2X();
oled.println("id drone");


Serial.println("affichage data");
}
 

Fichiers joints

  • cablage nodemcu.jpg
    cablage nodemcu.jpg
    101,6 KB · Vues: 90
Haut