Commit eee1f599 authored by Brice Gossin's avatar Brice Gossin

Upload New File

parent ad0b9984
/*******************************************************************************
*
* Copyright (c) 2018 Dragino
*
* http://www.dragino.com
*
*******************************************************************************/
#include <fstream>
#include <string>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <sys/time.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <wiringPi.h>
#include <wiringPiSPI.h>
#include <unistd.h>
#include <ctype.h>
#include <math.h>
#include <string.h>
#include <sys/errno.h>
#include <sys/errno.h>
#include <netdb.h>
#include <curl/curl.h>
#define DEBUG if(debug)
#define MEGABYTE ( 1024 * 1024 ) /* USed as the default buffer sizes */
int debug = 0; /* 0=off, 1=on basic, 2=trace like output */
char influx_hostname[1024 + 1] = { 0 };/* details of the influxdb server or telegraf */
char influx_ip[16 + 1] = { 0 };
long influx_port = 0;
char influx_database[256+1]; /* the influxdb database */
char influx_username[64+1]; /* optional for influxdb access */
char influx_password[64+1]; /* optional for influxdb access */
char *output; /* all the stats must fit in this buffer */
long output_size = 0;
long output_char = 0;
char *influx_tags; /* saved tags for every influxdb line protocol mesurement */
int subended = 0; /* stop ic_subend and ic_measureend both enig the measure */
int first_sub = 0; /* need to remove the ic_measure measure before adding ic_sub measure */
char saved_section[64];
char saved_sub[64];
int sockfd;
// #############################################
// #############################################
#define REG_FIFO 0x00
#define REG_OPMODE 0x01
#define REG_FIFO_ADDR_PTR 0x0D
#define REG_FIFO_TX_BASE_AD 0x0E
#define REG_FIFO_RX_BASE_AD 0x0F
#define REG_RX_NB_BYTES 0x13
#define REG_FIFO_RX_CURRENT_ADDR 0x10
#define REG_IRQ_FLAGS 0x12
#define REG_DIO_MAPPING_1 0x40
#define REG_DIO_MAPPING_2 0x41
#define REG_MODEM_CONFIG 0x1D
#define REG_MODEM_CONFIG2 0x1E
#define REG_MODEM_CONFIG3 0x26
#define REG_SYMB_TIMEOUT_LSB 0x1F
#define REG_PKT_SNR_VALUE 0x19
#define REG_PAYLOAD_LENGTH 0x22
#define REG_IRQ_FLAGS_MASK 0x11
#define REG_MAX_PAYLOAD_LENGTH 0x23
#define REG_HOP_PERIOD 0x24
#define REG_SYNC_WORD 0x39
#define REG_VERSION 0x42
#define PAYLOAD_LENGTH 0x40
// LOW NOISE AMPLIFIER
#define REG_LNA 0x0C
#define LNA_MAX_GAIN 0x23
#define LNA_OFF_GAIN 0x00
#define LNA_LOW_GAIN 0x20
#define RegDioMapping1 0x40 // common
#define RegDioMapping2 0x41 // common
#define RegPaConfig 0x09 // common
#define RegPaRamp 0x0A // common
#define RegPaDac 0x5A // common
#define SX72_MC2_FSK 0x00
#define SX72_MC2_SF7 0x70
#define SX72_MC2_SF8 0x80
#define SX72_MC2_SF9 0x90
#define SX72_MC2_SF10 0xA0
#define SX72_MC2_SF11 0xB0
#define SX72_MC2_SF12 0xC0
#define SX72_MC1_LOW_DATA_RATE_OPTIMIZE 0x01 // mandated for SF11 and SF12
// sx1276 RegModemConfig1
#define SX1276_MC1_BW_125 0x70
#define SX1276_MC1_BW_250 0x80
#define SX1276_MC1_BW_500 0x90
#define SX1276_MC1_CR_4_5 0x02
#define SX1276_MC1_CR_4_6 0x04
#define SX1276_MC1_CR_4_7 0x06
#define SX1276_MC1_CR_4_8 0x08
#define SX1276_MC1_IMPLICIT_HEADER_MODE_ON 0x01
// sx1276 RegModemConfig2
#define SX1276_MC2_RX_PAYLOAD_CRCON 0x04
// sx1276 RegModemConfig3
#define SX1276_MC3_LOW_DATA_RATE_OPTIMIZE 0x08
#define SX1276_MC3_AGCAUTO 0x04
// preamble for lora networks (nibbles swapped)
#define LORA_MAC_PREAMBLE 0x34
#define RXLORA_RXMODE_RSSI_REG_MODEM_CONFIG1 0x0A
#ifdef LMIC_SX1276
#define RXLORA_RXMODE_RSSI_REG_MODEM_CONFIG2 0x70
#elif LMIC_SX1272
#define RXLORA_RXMODE_RSSI_REG_MODEM_CONFIG2 0x74
#endif
// FRF
#define REG_FRF_MSB 0x06
#define REG_FRF_MID 0x07
#define REG_FRF_LSB 0x08
#define FRF_MSB 0xD9 // 868.1 Mhz
#define FRF_MID 0x06
#define FRF_LSB 0x66
// ----------------------------------------
// Constants for radio registers
#define OPMODE_LORA 0x80
#define OPMODE_MASK 0x07
#define OPMODE_SLEEP 0x00
#define OPMODE_STANDBY 0x01
#define OPMODE_FSTX 0x02
#define OPMODE_TX 0x03
#define OPMODE_FSRX 0x04
#define OPMODE_RX 0x05
#define OPMODE_RX_SINGLE 0x06
#define OPMODE_CAD 0x07
// ----------------------------------------
// Bits masking the corresponding IRQs from the radio
#define IRQ_LORA_RXTOUT_MASK 0x80
#define IRQ_LORA_RXDONE_MASK 0x40
#define IRQ_LORA_CRCERR_MASK 0x20
#define IRQ_LORA_HEADER_MASK 0x10
#define IRQ_LORA_TXDONE_MASK 0x08
#define IRQ_LORA_CDDONE_MASK 0x04
#define IRQ_LORA_FHSSCH_MASK 0x02
#define IRQ_LORA_CDDETD_MASK 0x01
// DIO function mappings D0D1D2D3
#define MAP_DIO0_LORA_RXDONE 0x00 // 00------
#define MAP_DIO0_LORA_TXDONE 0x40 // 01------
#define MAP_DIO1_LORA_RXTOUT 0x00 // --00----
#define MAP_DIO1_LORA_NOP 0x30 // --11----
#define MAP_DIO2_LORA_NOP 0xC0 // ----11--
// #############################################
// #############################################
//
typedef bool boolean;
typedef unsigned char byte;
static const int CHANNEL = 0;
char message[256];
bool sx1272 = true;
byte receivedbytes;
enum sf_t { SF7=7, SF8, SF9, SF10, SF11, SF12 };
/*******************************************************************************
*
* Configure these values!
*
*******************************************************************************/
// SX1272 - Raspberry connections
int ssPin = 6;
int dio0 = 7;
int RST = 0;
// Set spreading factor (SF7 - SF12)
sf_t sf = SF12;
// Set center frequency
uint32_t freq = 868100000; // in Mhz! (868.1)
byte hello[32] = "HELLO";
void die(const char *s)
{
perror(s);
exit(1);
}
void selectreceiver()
{
digitalWrite(ssPin, LOW);
}
void unselectreceiver()
{
digitalWrite(ssPin, HIGH);
}
byte readReg(byte addr)
{
unsigned char spibuf[2];
selectreceiver();
spibuf[0] = addr & 0x7F;
spibuf[1] = 0x00;
wiringPiSPIDataRW(CHANNEL, spibuf, 2);
unselectreceiver();
return spibuf[1];
}
void writeReg(byte addr, byte value)
{
unsigned char spibuf[2];
spibuf[0] = addr | 0x80;
spibuf[1] = value;
selectreceiver();
wiringPiSPIDataRW(CHANNEL, spibuf, 2);
unselectreceiver();
}
static void opmode (uint8_t mode)
{
writeReg(REG_OPMODE, (readReg(REG_OPMODE) & ~OPMODE_MASK) | mode);
}
static void opmodeLora()
{
uint8_t u = OPMODE_LORA;
if (sx1272 == false)
u |= 0x8; // TBD: sx1276 high freq
writeReg(REG_OPMODE, u);
}
void SetupLoRa()
{
digitalWrite(RST, HIGH);
delay(100);
digitalWrite(RST, LOW);
delay(100);
byte version = readReg(REG_VERSION);
if (version == 0x22) {
// sx1272
printf("SX1272 detected, starting.\n");
sx1272 = true;
} else {
// sx1276?
digitalWrite(RST, LOW);
delay(100);
digitalWrite(RST, HIGH);
delay(100);
version = readReg(REG_VERSION);
if (version == 0x12) {
// sx1276
printf("SX1276 detected, starting.\n");
sx1272 = false;
} else {
printf("Unrecognized transceiver.\n");
//printf("Version: 0x%x\n",version);
exit(1);
}
}
opmode(OPMODE_SLEEP);
//opmodeLora();
// set frequency
uint64_t frf = ((uint64_t)freq << 19) / 32000000;
writeReg(REG_FRF_MSB, (uint8_t)(frf>>16) );
writeReg(REG_FRF_MID, (uint8_t)(frf>> 8) );
writeReg(REG_FRF_LSB, (uint8_t)(frf>> 0) );
writeReg(REG_SYNC_WORD, 0x34); // LoRaWAN public sync word
if (sx1272) {
if (sf == SF11 || sf == SF12) {
writeReg(REG_MODEM_CONFIG,0x0B);
} else {
writeReg(REG_MODEM_CONFIG,0x0A);
}
writeReg(REG_MODEM_CONFIG2,(sf<<4) | 0x04);
} else {
if (sf == SF11 || sf == SF12) {
writeReg(REG_MODEM_CONFIG3,0x0C);
} else {
writeReg(REG_MODEM_CONFIG3,0x04);
}
writeReg(REG_MODEM_CONFIG,0x72);
writeReg(REG_MODEM_CONFIG2,(sf<<4) | 0x04);
}
if (sf == SF10 || sf == SF11 || sf == SF12) {
writeReg(REG_SYMB_TIMEOUT_LSB,0x05);
} else {
writeReg(REG_SYMB_TIMEOUT_LSB,0x08);
}
writeReg(REG_MAX_PAYLOAD_LENGTH,0x80);
writeReg(REG_PAYLOAD_LENGTH,PAYLOAD_LENGTH);
writeReg(REG_HOP_PERIOD,0xFF);
writeReg(REG_FIFO_ADDR_PTR, readReg(REG_FIFO_RX_BASE_AD)); //IMPORTANT
writeReg(REG_LNA, LNA_MAX_GAIN);
}
boolean receive(char *payload) {
byte irqflags = readReg(REG_IRQ_FLAGS); // read the IRQ flags first
// clear rxDone AFTER reading the IRQ flags
writeReg(REG_IRQ_FLAGS, 0x40);
// payload crc: 0x20
if((irqflags & 0x20) == 0x20)
{
printf("CRC error\n");
writeReg(REG_IRQ_FLAGS, 0x20);
return false;
} else {
byte currentAddr = readReg(REG_FIFO_RX_CURRENT_ADDR);
byte receivedCount = readReg(REG_RX_NB_BYTES);
receivedbytes = receivedCount;
writeReg(REG_FIFO_ADDR_PTR, currentAddr);
for(int i = 0; i < receivedCount; i++)
{
payload[i] = (char)readReg(REG_FIFO);
}
}
return true;
}
void sendDataToInfluxDB(const char* message) {
const char* influxDBHost = "localhost";
const int influxDBPort = 8086;
const char* influxDBDatabase = "LoRa_data";
//const char* influxDBMeasurement = "mesure1";
CURL *curl; //Variable de type curl utilisée pour représenter une session CURL qu'on va configurer avec des options spécifiques
CURLcode res; //stocke le code de résultat de l'opération CURL
//initialisation de CURL
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
// Build the InfluxDB URL
char url[256];
snprintf(url, sizeof(url), "http://%s:%d/write?db=%s", influxDBHost, influxDBPort, influxDBDatabase);
// Set cURL options
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, message);
// Perform the HTTP POST request
res = curl_easy_perform(curl);
// Check for errors
if(res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
// Cleanup cURL
curl_easy_cleanup(curl);
}}
void createInfluxDBMessage(const char* input, char* output) {
char mvmt[20], rtc[20], s_temp[20], o_temp[20], hum[20], lum[20], coordx[20], coordy[20], coordz[20], photo[20]=""; //Variables pour stocker les données
int result = sscanf(input, "%19[^;];%19[^;];%19[^;];%19[^;];%19[^;];%19[^;];%19[^;];%19[^;];%19[^;];%19[^;]", mvmt, rtc, s_temp, o_temp, hum, lum, coordx, coordy, coordz, photo); //Première mise en forme des données + stockage dans la variable result
if (result == 10) {
// Concaténation dans le format InfluxDB
sprintf(output, "LoRa_sensors_data,Transmission=OK Mouvement=%s,RTC=%s,System_temperature=%s,Outside_temperature=%s,Humidity=%s,Luminosity=%s,c_x=%s,c_y=%s,c_z=%s,Photo=%s", mvmt, rtc, s_temp, o_temp, hum, lum, coordx, coordy, coordz, photo);
} else {
// Gestion d'une erreur de format d'entrée
printf("Erreur de format d'entrée.\n");
}
}
void receivepacket() {
long int SNR;
int rssicorr;
if(digitalRead(dio0) == 1)
{
if(receive(message)) {
byte value = readReg(REG_PKT_SNR_VALUE);
if( value & 0x80 ) // The SNR sign bit is 1
{
// Invert and divide by 4
value = ( ( ~value + 1 ) & 0xFF ) >> 2;
SNR = -value;
}
else
{
// Divide by 4
SNR = ( value & 0xFF ) >> 2;
}
if (sx1272) {
rssicorr = 139;
} else {
rssicorr = 157;
}
printf("Packet RSSI: %d, ", readReg(0x1A)-rssicorr);
printf("RSSI: %d, ", readReg(0x1B)-rssicorr);
printf("SNR: %li, ", SNR);
printf("Length: %i", (int)receivedbytes);
printf("\n");
printf("Payload: %s\n", message);
/*
FILE *fichier;
fichier=fopen("Data.txt","w");
if (fichier!=NULL)
{
fprintf(fichier, "%s", message);
fclose(fichier);
printf("Le message a été écrit dans le fichier\n");
}
else
{
printf("Erreur");
}*/
time_t now = time(0); //Writing the message into a CSV file
char* datetime = ctime(&now);
datetime[strlen(datetime) - 1] = '\0'; // Removing the '\n' character from the end
// Opening the CSV file for writing
std::ofstream file;
file.open("data.csv", std::ios_base::app); // Add to end of file mode
// Checking if the file was successfully opened
if (!file.is_open()) {
printf("Failed to open CSV file for writing.\n");
return;
}
// Writing time and message to file
file << datetime << "," << message<< "\n";
file.close();
//Le message qu'on reçoit tel quel est de la forme X;Y;Z
//On doit segmenter chaque valeur de capteur et rajouter des champs/tags pour faire une input influxdb (fonction createinfluxdbmessage)
char influxdbmessage[1000];
createInfluxDBMessage(message, influxdbmessage);
sendDataToInfluxDB(influxdbmessage);
/* //Writing the message into an influxDB database
const char host_cst[] = "localhost";
long port = 8086;
const char db_cst[]= "LoRa_data"; //on rentre les informations en const char pour les convertir après en char*
const char user_cst[] = "user1";
const char pw_cst[] = "password";
char host[100], db[100], user[100], pw[100];
strcpy (host, host_cst);
strcpy (db, db_cst);
strcpy (user, user_cst);
strcpy (pw, pw_cst);
ic_debug(2);
ic_influx_database(host, port, db);
ic_influx_userpw(user, pw);
char txt_measure[100];
strcpy(txt_measure, "data1 :");
ic_measure(txt_measure);
char nom_serie[100];
strcpy(nom_serie, "Série en string");
char* new_message = message;
ic_string(nom_serie, new_message);
ic_measureend();
ic_push();
*/
} // received a message
}
}
static void configPower (int8_t pw) {
if (sx1272 == false) {
// no boost used for now
if(pw >= 17) {
pw = 17;
} else if(pw < 2) {
pw = 2;
}
// check board type for BOOST pin
writeReg(RegPaConfig, (uint8_t)(0x80|(pw&0xf)));
writeReg(RegPaDac, readReg(RegPaDac)|0x4);
} else {
// set PA config (2-17 dBm using PA_BOOST)
if(pw > 17) {
pw = 17;
} else if(pw < 2) {
pw = 2;
}
writeReg(RegPaConfig, (uint8_t)(0x80|(pw-2)));
}
}
static void writeBuf(byte addr, byte *value, byte len) {
unsigned char spibuf[256];
spibuf[0] = addr | 0x80;
for (int i = 0; i < len; i++) {
spibuf[i + 1] = value[i];
}
selectreceiver();
wiringPiSPIDataRW(CHANNEL, spibuf, len + 1);
unselectreceiver();
}
void txlora(byte *frame, byte datalen) {
// set the IRQ mapping DIO0=TxDone DIO1=NOP DIO2=NOP
writeReg(RegDioMapping1, MAP_DIO0_LORA_TXDONE|MAP_DIO1_LORA_NOP|MAP_DIO2_LORA_NOP);
// clear all radio IRQ flags
writeReg(REG_IRQ_FLAGS, 0xFF);
// mask all IRQs but TxDone
writeReg(REG_IRQ_FLAGS_MASK, ~IRQ_LORA_TXDONE_MASK);
// initialize the payload size and address pointers
writeReg(REG_FIFO_TX_BASE_AD, 0x00);
writeReg(REG_FIFO_ADDR_PTR, 0x00);
writeReg(REG_PAYLOAD_LENGTH, datalen);
// download buffer to the radio FIFO
writeBuf(REG_FIFO, frame, datalen);
// now we actually start the transmission
opmode(OPMODE_TX);
printf("send: %s\n", frame);
}
int main (int argc, char *argv[]) {
if (argc < 2) {
printf ("Usage: argv[0] sender|rec [message]\n");
exit(1);
}
wiringPiSetup () ;
pinMode(ssPin, OUTPUT);
pinMode(dio0, INPUT);
pinMode(RST, OUTPUT);
wiringPiSPISetup(CHANNEL, 500000);
SetupLoRa();
if (!strcmp("sender", argv[1])) {
//opmodeLora();
// enter standby mode (required for FIFO loading))
opmode(OPMODE_STANDBY);
writeReg(RegPaRamp, (readReg(RegPaRamp) & 0xF0) | 0x08); // set PA ramp-up time 50 uSec IMPORTANT
configPower(23);
printf("Send packets at SF%i on %.6lf Mhz.\n", sf,(double)freq/1000000);
printf("------------------\n");
if (argc > 2)
strncpy((char *)hello, argv[2], sizeof(hello));
while(1) {
txlora(hello, strlen((char *)hello));
delay(5000);
}
} else {
// radio init
opmodeLora();
opmode(OPMODE_STANDBY);
opmode(OPMODE_RX);
printf("Listening at SF%i on %.6lf Mhz.\n", sf,(double)freq/1000000);
printf("------------------\n");
while(1) {
receivepacket();
delay(1);
}
}
return (0);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment