update
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -9,4 +9,6 @@ config.json
|
||||
sound_meter/moving_avg_minute.txt
|
||||
wifi_list.csv
|
||||
envea/data/*.txt
|
||||
NPM/data/*.txt
|
||||
NPM/data/*.json
|
||||
*.lock
|
||||
0
NPM/firmware_version.py
Normal file → Executable file
0
NPM/firmware_version.py
Normal file → Executable file
2
NPM/get_data_modbus.py
Normal file → Executable file
2
NPM/get_data_modbus.py
Normal file → Executable file
@@ -14,7 +14,7 @@ Request
|
||||
\x01 Slave Address (slave device address)
|
||||
\x03 Function code (read multiple holding registers)
|
||||
\x00\x80 Starting Address (The request starts reading from holding register address 0x80 or 128)
|
||||
\x00\x0A Quantity of Registers (Requests to read 0x0A or 10 consecutive registers starting from address 50)
|
||||
\x00\x0A Quantity of Registers (Requests to read 0x0A or 10 consecutive registers starting from address 128)
|
||||
\xE4\x1E Cyclic Redundancy Check (checksum )
|
||||
|
||||
'''
|
||||
|
||||
122
NPM/get_data_modbus_loop.py
Normal file
122
NPM/get_data_modbus_loop.py
Normal file
@@ -0,0 +1,122 @@
|
||||
'''
|
||||
Loop to run every minutes
|
||||
* * * * * /usr/bin/python3 /var/www/nebuleair_pro_4g/NPM/get_data_modbus_loop.py
|
||||
|
||||
saves data to a json file /var/www/nebuleair_pro_4g/NPM/data/data.json
|
||||
'''
|
||||
|
||||
import serial
|
||||
import sys
|
||||
import crcmod
|
||||
import time
|
||||
import json
|
||||
import os
|
||||
|
||||
# Ensure a port argument is provided
|
||||
if len(sys.argv) < 2:
|
||||
print("Usage: python3 get_data_modbus.py <serial_port>")
|
||||
sys.exit(1)
|
||||
|
||||
port = '/dev/' + sys.argv[1]
|
||||
|
||||
# Initialize serial communication
|
||||
try:
|
||||
ser = serial.Serial(
|
||||
port=port,
|
||||
baudrate=115200,
|
||||
parity=serial.PARITY_EVEN,
|
||||
stopbits=serial.STOPBITS_ONE,
|
||||
bytesize=serial.EIGHTBITS,
|
||||
timeout=0.5
|
||||
)
|
||||
except Exception as e:
|
||||
print(f"Error opening serial port {port}: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
# Define Modbus CRC-16 function
|
||||
crc16 = crcmod.predefined.mkPredefinedCrcFun('modbus')
|
||||
|
||||
# Request frame without CRC
|
||||
data = b'\x01\x03\x00\x80\x00\x0A'
|
||||
|
||||
# Calculate CRC
|
||||
crc = crc16(data)
|
||||
crc_low = crc & 0xFF
|
||||
crc_high = (crc >> 8) & 0xFF
|
||||
|
||||
# Append CRC to the frame
|
||||
request = data + bytes([crc_low, crc_high])
|
||||
|
||||
# Log request frame
|
||||
print(f"Request frame: {request.hex()}")
|
||||
|
||||
# Initialize storage for averaging
|
||||
num_samples = 6
|
||||
channel_sums = [0] * 5 # 5 channels
|
||||
|
||||
# Loop 6 times to collect data every 10 seconds
|
||||
for i in range(num_samples):
|
||||
print(f"\nIteration {i+1}/{num_samples}")
|
||||
ser.write(request)
|
||||
|
||||
try:
|
||||
byte_data = ser.readline()
|
||||
formatted = ''.join(f'\\x{byte:02x}' for byte in byte_data)
|
||||
print(f"Raw Response: {formatted}")
|
||||
|
||||
if len(byte_data) < 23:
|
||||
print("Incomplete response, skipping this sample.")
|
||||
time.sleep(10)
|
||||
continue
|
||||
|
||||
# Extract and process the 5 channels
|
||||
channels = []
|
||||
for j in range(5):
|
||||
lsw = int.from_bytes(byte_data[3 + j*4 : 5 + j*4], byteorder='little')
|
||||
msw = int.from_bytes(byte_data[5 + j*4 : 7 + j*4], byteorder='little')
|
||||
raw_value = (msw << 16) | lsw
|
||||
channels.append(raw_value)
|
||||
|
||||
# Accumulate sum for each channel
|
||||
for j in range(5):
|
||||
channel_sums[j] += channels[j]
|
||||
|
||||
# Print collected values
|
||||
for j in range(5):
|
||||
print(f"Channel {j+1}: {channels[j]}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error reading data: {e}")
|
||||
|
||||
# Wait 10 seconds before next reading
|
||||
time.sleep(10)
|
||||
|
||||
# Compute the average values
|
||||
channel_means = [int(s / num_samples) for s in channel_sums]
|
||||
|
||||
# Create JSON structure
|
||||
data_json = {
|
||||
"channel_1": channel_means[0],
|
||||
"channel_2": channel_means[1],
|
||||
"channel_3": channel_means[2],
|
||||
"channel_4": channel_means[3],
|
||||
"channel_5": channel_means[4]
|
||||
}
|
||||
|
||||
# Print final JSON data
|
||||
print("\nFinal JSON Data (Averaged over 6 readings):")
|
||||
print(json.dumps(data_json, indent=4))
|
||||
|
||||
# Define JSON file path
|
||||
output_file = "/var/www/nebuleair_pro_4g/NPM/data/data.json"
|
||||
|
||||
# Write results to a JSON file
|
||||
try:
|
||||
with open(output_file, "w") as f:
|
||||
json.dump(data_json, f, indent=4)
|
||||
print(f"\nAveraged JSON data saved to {output_file}")
|
||||
except Exception as e:
|
||||
print(f"Error writing to file: {e}")
|
||||
|
||||
# Close serial connection
|
||||
ser.close()
|
||||
0
SARA/SSL/test_22.py
Normal file → Executable file
0
SARA/SSL/test_22.py
Normal file → Executable file
0
SARA/SSL/test_33.py
Normal file → Executable file
0
SARA/SSL/test_33.py
Normal file → Executable file
@@ -8,6 +8,7 @@
|
||||
"NextPM_ports": [
|
||||
"ttyAMA5"
|
||||
],
|
||||
"NextPM_5channels": false,
|
||||
"i2C_sound": false,
|
||||
"i2c_BME": false,
|
||||
"sshTunnel_port": 59228,
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
"""
|
||||
Main loop to gather data from envea Sensors
|
||||
/usr/bin/python3 /var/www/nebuleair_pro_4g/envea/read_value_loop.py
|
||||
|
||||
Save data to .txt file inside /var/www/nebuleair_pro_4g/envea/data/
|
||||
"""
|
||||
import json
|
||||
import serial
|
||||
|
||||
@@ -12,10 +12,11 @@ CSV PAYLOAD (AirCarto Servers)
|
||||
/pro_4G/data.php?sensor_id={device_id}
|
||||
|
||||
ATTENTION : do not change order !
|
||||
CSV size: 18
|
||||
{PM1},{PM25},{PM10},{temp},{hum},{press},{avg_noise},{max_noise},{min_noise},{envea_no2},{envea_h2s},{envea_o3},{4g_signal_quality}
|
||||
0 -> PM1
|
||||
1 -> PM25
|
||||
2 -> PM10
|
||||
0 -> PM1 (μg/m3)
|
||||
1 -> PM25 (μg/m3)
|
||||
2 -> PM10 (μg/m3)
|
||||
3 -> temp
|
||||
4 -> hum
|
||||
5 -> press
|
||||
@@ -25,7 +26,12 @@ CSV PAYLOAD (AirCarto Servers)
|
||||
9 -> envea_no2
|
||||
10 -> envea_h2s
|
||||
11 -> envea_o3
|
||||
12 -> 4G signal quality
|
||||
12 -> 4G signal quality,
|
||||
13 -> PM 0.2μm to 0.5μm quantity (Nb/L)
|
||||
14 -> PM 0.5μm to 1.0μm quantity (Nb/L)
|
||||
15 -> PM 1.0μm to 2.5μm quantity (Nb/L)
|
||||
16 -> PM 2.5μm to 5.0μm quantity (Nb/L)
|
||||
17 -> PM 5.0μm to 10μm quantity (Nb/L)
|
||||
|
||||
JSON PAYLOAD (Micro-Spot Servers)
|
||||
Same as NebuleAir wifi
|
||||
@@ -178,6 +184,7 @@ 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
|
||||
send_aircarto = config.get('send_aircarto', True) #envoi sur AirCarto (data.nebuleair.fr)
|
||||
send_uSpot = config.get('send_uSpot', False) #envoi sur MicroSpot ()
|
||||
npm_5channel = config.get('NextPM_5channels', False) #5 canaux du NPM
|
||||
|
||||
envea_sondes = config.get('envea_sondes', [])
|
||||
connected_envea_sondes = [sonde for sonde in envea_sondes if sonde.get('connected', False)]
|
||||
@@ -307,6 +314,44 @@ try:
|
||||
payload_json["sensordatavalues"].append({"value_type": "BME280_humidity", "value": f"{round(bme280.humidity, 2)}"})
|
||||
payload_json["sensordatavalues"].append({"value_type": "BME280_pressure", "value": f"{round(bme280.pressure, 2)}"})
|
||||
|
||||
# NPM sur 5 cannaux
|
||||
if npm_5channel:
|
||||
print("Getting NPM 5 Channels")
|
||||
# Define the path to the JSON file
|
||||
json_file_path_npm = "/var/www/nebuleair_pro_4g/NPM/data/data.json"
|
||||
# Read the JSON file
|
||||
try:
|
||||
with open(json_file_path_npm, "r") as file:
|
||||
data = json.load(file) # Load JSON into a dictionary
|
||||
|
||||
# Extract values
|
||||
channel_1 = data.get("channel_1", 0)
|
||||
channel_2 = data.get("channel_2", 0)
|
||||
channel_3 = data.get("channel_3", 0)
|
||||
channel_4 = data.get("channel_4", 0)
|
||||
channel_5 = data.get("channel_5", 0)
|
||||
|
||||
# Print extracted values
|
||||
print(f"Channel 1: {channel_1}")
|
||||
print(f"Channel 2: {channel_2}")
|
||||
print(f"Channel 3: {channel_3}")
|
||||
print(f"Channel 4: {channel_4}")
|
||||
print(f"Channel 5: {channel_5}")
|
||||
|
||||
#add to CSV
|
||||
payload_csv[13] = channel_1
|
||||
payload_csv[14] = channel_2
|
||||
payload_csv[15] = channel_3
|
||||
payload_csv[16] = channel_4
|
||||
payload_csv[17] = channel_5
|
||||
|
||||
|
||||
except FileNotFoundError:
|
||||
print(f"Error: JSON file not found at {json_file_path_npm}")
|
||||
except json.JSONDecodeError:
|
||||
print("Error: JSON file is not formatted correctly")
|
||||
except Exception as e:
|
||||
print(f"Unexpected error: {e}")
|
||||
|
||||
# Sonde Bruit connected
|
||||
if i2C_sound_config:
|
||||
@@ -324,7 +369,7 @@ try:
|
||||
payload_csv[8] = min_noise
|
||||
|
||||
except FileNotFoundError:
|
||||
print(f"Error: File {file_path} not found.")
|
||||
print(f"Error: File {file_path_data_noise} not found.")
|
||||
except ValueError:
|
||||
print("Error: File content is not valid numbers.")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user