Merge remote-tracking branch 'refs/remotes/origin/main'

This commit is contained in:
PaulVua
2025-01-14 14:37:08 +01:00
5 changed files with 45 additions and 46 deletions

View File

@@ -1,5 +1,13 @@
''' '''
Script to set the URL for a HTTP request Script to set the URL for a HTTP request
Ex:
/usr/bin/python3 /var/www/nebuleair_pro_4g/SARA/sara_setURL.py ttyAMA2 data.nebuleair.fr
To do: need to add profile id as parameter
First profile id:
AT+UHTTP=0,1,"data.nebuleair.fr"
Second profile id:
AT+UHTTP=1,1,"api-prod.uspot.probesys.net"
''' '''
import serial import serial

View File

@@ -27,13 +27,13 @@
}, },
{ {
"connected": false, "connected": false,
"port": "ttyAMA2", "port": "ttyAMA3",
"name": "no2", "name": "no2",
"coefficient" : 1 "coefficient" : 1
}, },
{ {
"connected": false, "connected": false,
"port": "ttyAMA1", "port": "ttyAMA2",
"name": "o3", "name": "o3",
"coefficient" : 1 "coefficient" : 1
} }

View File

@@ -5,13 +5,13 @@ import sys
parameter = sys.argv[1:] # Exclude the script name parameter = sys.argv[1:] # Exclude the script name
#print("Parameters received:") #print("Parameters received:")
port='/dev/'+parameter[0] port='/dev/'+parameter[0]
coefficient = int(parameter[1])
coefficient = 4 #coefficient = 4
def read_cairsens(port, baudrate=9600, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, databits=serial.EIGHTBITS, timeout=1): def read_cairsens(port, baudrate=9600, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, databits=serial.EIGHTBITS, timeout=1):
""" """
Lit les données de la sonde CAIRSENS via UART. Lit les données de la sonde CAIRSENS via UART.
/usr/bin/python3 /var/www/nebuleair_pro_4g/envea/read_value.py ttyAMA4 /usr/bin/python3 /var/www/nebuleair_pro_4g/envea/read_value.py ttyAMA4 4
:param port: Le port série utilisé (ex: 'COM1' ou '/dev/ttyAMA0'). :param port: Le port série utilisé (ex: 'COM1' ou '/dev/ttyAMA0').

View File

@@ -290,7 +290,7 @@ window.onload = function() {
ENVEA_sensors.forEach((sensor, index) => { ENVEA_sensors.forEach((sensor, index) => {
const port = sensor.port; // Port from the sensor object const port = sensor.port; // Port from the sensor object
const name = sensor.name; // Port from the sensor object const name = sensor.name; // Port from the sensor object
const coefficient = sensor.coefficient;
const cardHTML = ` const cardHTML = `
<div class="col-sm-3"> <div class="col-sm-3">
<div class="card"> <div class="card">
@@ -300,7 +300,7 @@ window.onload = function() {
<div class="card-body"> <div class="card-body">
<h5 class="card-title">Sonde Envea ${name}</h5> <h5 class="card-title">Sonde Envea ${name}</h5>
<p class="card-text">Capteur gas.</p> <p class="card-text">Capteur gas.</p>
<button class="btn btn-primary" onclick="getENVEA_values('${port}','${name}')">Get Data</button> <button class="btn btn-primary" onclick="getENVEA_values('${port}','${name}','${coefficient}')">Get Data</button>
<div id="loading_envea${name}" class="spinner-border spinner-border-sm" style="display: none;" role="status"></div> <div id="loading_envea${name}" class="spinner-border spinner-border-sm" style="display: none;" role="status"></div>
<table class="table table-striped-columns"> <table class="table table-striped-columns">
<tbody id="data-table-body_envea${name}"></tbody> <tbody id="data-table-body_envea${name}"></tbody>

View File

@@ -6,7 +6,11 @@ Main loop to gather data from sensor:
* Noise sensor * Noise sensor
and send it to AirCarto servers via SARA R4 HTTP post requests and send it to AirCarto servers via SARA R4 HTTP post requests
CSV PAYLOAD CSV PAYLOAD (AirCarto Servers)
Endpoint:
data.nebuleair.fr
/pro_4G/data.php?sensor_id={device_id}
ATTENTION : do not change order ! ATTENTION : do not change order !
{PM1},{PM25},{PM10},{temp},{hum},{press},{avg_noise},{max_noise},{min_noise},{envea_no2},{envea_h2s},{envea_o3},{4g_signal_quality} {PM1},{PM25},{PM10},{temp},{hum},{press},{avg_noise},{max_noise},{min_noise},{envea_no2},{envea_h2s},{envea_o3},{4g_signal_quality}
0 -> PM1 0 -> PM1
@@ -23,8 +27,13 @@ CSV PAYLOAD
11 -> envea_o3 11 -> envea_o3
12 -> 4G signal quality 12 -> 4G signal quality
JSON PAYLOAD JSON PAYLOAD (Micro-Spot Servers)
Same as NebuleAir wifi Same as NebuleAir wifi
Endpoint:
api-prod.uspot.probesys.net
nebuleair?token=2AFF6dQk68daFZ
port 443
{"nebuleairid": "82D25549434", {"nebuleairid": "82D25549434",
"software_version": "ModuleAirV2-V1-042022", "software_version": "ModuleAirV2-V1-042022",
"sensordatavalues": "sensordatavalues":
@@ -46,9 +55,8 @@ JSON PAYLOAD
{"value_type":"longitude","value":"5.36978"}, {"value_type":"longitude","value":"5.36978"},
{"value_type":"state_npm","value":"State: 00000000"}, {"value_type":"state_npm","value":"State: 00000000"},
{"value_type":"th_npm","value":"28.47 / 37.54"} {"value_type":"th_npm","value":"28.47 / 37.54"}
]} ]
}
""" """
import board import board
import json import json
@@ -82,6 +90,7 @@ def load_config(config_file):
print(f"Error loading config file: {e}") print(f"Error loading config file: {e}")
return {} return {}
#Fonction pour mettre à jour le JSON de configuration
def update_json_key(file_path, key, value): def update_json_key(file_path, key, value):
""" """
Updates a specific key in a JSON file with a new value. Updates a specific key in a JSON file with a new value.
@@ -115,17 +124,19 @@ config_file = '/var/www/nebuleair_pro_4g/config.json'
# Load the configuration data # Load the configuration data
config = load_config(config_file) config = load_config(config_file)
# Access the shared variables
baudrate = config.get('SaraR4_baudrate', 115200) #baudrate du sara R4 baudrate = config.get('SaraR4_baudrate', 115200) #baudrate du sara R4
device_id = config.get('deviceID', '').upper() #device ID en maj device_id = config.get('deviceID', '').upper() #device ID en maj
need_to_log = config.get('loop_log', False) #inscription des logs need_to_log = config.get('loop_log', False) #inscription des logs
bme_280_config = config.get('i2c_BME', False) #présence du BME280 bme_280_config = config.get('i2c_BME', False) #présence du BME280
i2C_sound_config = config.get('i2C_sound', False) #présence du capteur son i2C_sound_config = config.get('i2C_sound', False) #présence du capteur son
send_aircarto = config.get('send_aircarto', True) #envoi sur AirCarto (data.nebuleair.fr)
send_uSpot = config.get('send_uSpot', False) #envoi sur MicroSpot ()
envea_sondes = config.get('envea_sondes', []) envea_sondes = config.get('envea_sondes', [])
connected_envea_sondes = [sonde for sonde in envea_sondes if sonde.get('connected', False)] connected_envea_sondes = [sonde for sonde in envea_sondes if sonde.get('connected', False)]
selected_networkID = config.get('SARA_R4_neworkID', '') selected_networkID = config.get('SARA_R4_neworkID', '')
ser_sara = serial.Serial( ser_sara = serial.Serial(
port='/dev/ttyAMA2', port='/dev/ttyAMA2',
baudrate=baudrate, #115200 ou 9600 baudrate=baudrate, #115200 ou 9600
@@ -187,19 +198,10 @@ try:
PM1 = int.from_bytes(byte_data[9:11], byteorder='big') / 10 PM1 = int.from_bytes(byte_data[9:11], byteorder='big') / 10
PM25 = int.from_bytes(byte_data[11:13], byteorder='big') / 10 PM25 = int.from_bytes(byte_data[11:13], byteorder='big') / 10
PM10 = int.from_bytes(byte_data[13:15], byteorder='big') / 10 PM10 = int.from_bytes(byte_data[13:15], byteorder='big') / 10
# Create a dictionary with the parsed data payload[0] = PM1
data = { payload[1] = PM25
'sondeID': device_id, payload[2] = PM10
'PM1': PM1,
'PM25': PM25,
'PM10': PM10
}
message = f"{data['PM1']},{data['PM25']},{data['PM10']}"
payload[0] = data['PM1']
payload[1] = data['PM25']
payload[2] = data['PM10']
# Sonde BME280 connected # Sonde BME280 connected
if bme_280_config: if bme_280_config:
@@ -207,13 +209,10 @@ try:
i2c = busio.I2C(board.SCL, board.SDA) i2c = busio.I2C(board.SCL, board.SDA)
bme280 = adafruit_bme280.Adafruit_BME280_I2C(i2c, address=0x76) bme280 = adafruit_bme280.Adafruit_BME280_I2C(i2c, address=0x76)
bme280.sea_level_pressure = 1013.25 # Update this value for your location bme280.sea_level_pressure = 1013.25 # Update this value for your location
data['temp'] = round(bme280.temperature, 2)
data['hum'] = round(bme280.humidity, 2) payload[3] = round(bme280.temperature, 2)
data['press'] = round(bme280.pressure, 2) payload[4] = round(bme280.humidity, 2)
message += f",{data['temp']},{data['hum']},{data['press']}" payload[5] = round(bme280.pressure, 2)
payload[3] = data['temp']
payload[4] = data['hum']
payload[5] = data['press']
# Sonde Bruit connected # Sonde Bruit connected
if i2C_sound_config: if i2C_sound_config:
@@ -225,18 +224,10 @@ try:
content = file.read().strip() content = file.read().strip()
avg_noise, max_noise, min_noise = map(int, content.split()) avg_noise, max_noise, min_noise = map(int, content.split())
# Append the variables to the JSON and to the message # Append the variables to the payload
data['avg_noise'] = avg_noise payload[6] = avg_noise
data['max_noise'] = max_noise payload[7] = max_noise
data['min_noise'] = min_noise payload[8] = min_noise
#get BME280 data (SAFE: it returns none if the key do not exist)
message = f"{data.get('PM1', '')},{data.get('PM25', '')},{data.get('PM10', '')},{data.get('temp', '')},{data.get('hum', '')},{data.get('press', '')},{avg_noise},{max_noise},{min_noise}"
payload[6] = data['avg_noise']
payload[7] = data['max_noise']
payload[8] = data['min_noise']
print(message) # Display the message or send it further
except FileNotFoundError: except FileNotFoundError:
print(f"Error: File {file_path} not found.") print(f"Error: File {file_path} not found.")