636 lines
24 KiB
Python
Executable File
636 lines
24 KiB
Python
Executable File
"""
|
||
Main loop to gather data from sensor:
|
||
* NPM
|
||
* Envea
|
||
* I2C BME280
|
||
* Noise sensor
|
||
and send it to AirCarto servers via SARA R4 HTTP post requests
|
||
|
||
CSV PAYLOAD (AirCarto Servers)
|
||
Endpoint:
|
||
data.nebuleair.fr
|
||
/pro_4G/data.php?sensor_id={device_id}
|
||
|
||
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}
|
||
0 -> PM1
|
||
1 -> PM25
|
||
2 -> PM10
|
||
3 -> temp
|
||
4 -> hum
|
||
5 -> press
|
||
6 -> avg_noise
|
||
7 -> max_noise
|
||
8 -> min_noise
|
||
9 -> envea_no2
|
||
10 -> envea_h2s
|
||
11 -> envea_o3
|
||
12 -> 4G signal quality
|
||
|
||
JSON PAYLOAD (Micro-Spot Servers)
|
||
Same as NebuleAir wifi
|
||
Endpoint:
|
||
api-prod.uspot.probesys.net
|
||
nebuleair?token=2AFF6dQk68daFZ
|
||
port 443
|
||
|
||
{"nebuleairid": "82D25549434",
|
||
"software_version": "ModuleAirV2-V1-042022",
|
||
"sensordatavalues":
|
||
[
|
||
{"value_type":"NPM_P0","value":"1.54"},
|
||
{"value_type":"NPM_P1","value":"1.54"},
|
||
{"value_type":"NPM_P2","value":"1.54"},
|
||
{"value_type":"NPM_N1","value":"0.02"},
|
||
{"value_type":"NPM_N10","value":"0.02"},
|
||
{"value_type":"NPM_N25","value":"0.02"},
|
||
{"value_type":"MHZ16_CO2","value":"793.00"},
|
||
{"value_type":"SGP40_VOC","value":"29915.00"},
|
||
{"value_type":"samples","value":"134400"},
|
||
{"value_type":"min_micro","value":"137"},
|
||
{"value_type":"max_micro","value":"155030"},
|
||
{"value_type":"interval","value":"145000"},
|
||
{"value_type":"signal","value":"-80"},
|
||
{"value_type":"latitude","value":"43.2964"},
|
||
{"value_type":"longitude","value":"5.36978"},
|
||
{"value_type":"state_npm","value":"State: 00000000"},
|
||
{"value_type":"BME280_temperature","value":"28.47"},
|
||
{"value_type":"BME280_humidity","value":"28.47"},
|
||
{"value_type":"BME280_pressure","value":"28.47"},
|
||
{"value_type":"CAIRSENS_NO2","value":"54"},
|
||
{"value_type":"CAIRSENS_H2S","value":"54"},
|
||
{"value_type":"CAIRSENS_O3","value":"54"}
|
||
]
|
||
}
|
||
"""
|
||
import board
|
||
import json
|
||
import serial
|
||
import time
|
||
import busio
|
||
import re
|
||
import os
|
||
import traceback
|
||
import sys
|
||
|
||
import RPi.GPIO as GPIO
|
||
from adafruit_bme280 import basic as adafruit_bme280
|
||
|
||
# Record the start time of the script
|
||
start_time_script = time.time()
|
||
|
||
# Check system uptime
|
||
with open('/proc/uptime', 'r') as f:
|
||
uptime_seconds = float(f.readline().split()[0])
|
||
|
||
# Skip execution if uptime is less than 2 minutes (120 seconds)
|
||
if uptime_seconds < 120:
|
||
print(f"System just booted ({uptime_seconds:.2f} seconds uptime), skipping execution.")
|
||
sys.exit()
|
||
|
||
url_nebuleair="data.nebuleair.fr"
|
||
payload_csv = [None] * 20
|
||
payload_json = {
|
||
"nebuleairid": "82D25549434",
|
||
"software_version": "ModuleAirV2-V1-042022",
|
||
"sensordatavalues": [] # Empty list to start with
|
||
}
|
||
|
||
aircarto_profile_id = 0
|
||
uSpot_profile_id = 1
|
||
# Set up GPIO mode (for Blue LED: network status)
|
||
GPIO.setwarnings(False)
|
||
GPIO.setmode(GPIO.BCM) # Use Broadcom pin numbering
|
||
GPIO.setup(23, GPIO.OUT) # Set GPIO23 as an output pin
|
||
|
||
#get data from config
|
||
def load_config(config_file):
|
||
try:
|
||
with open(config_file, 'r') as file:
|
||
config_data = json.load(file)
|
||
return config_data
|
||
except Exception as e:
|
||
print(f"Error loading config file: {e}")
|
||
return {}
|
||
|
||
#Fonction pour mettre à jour le JSON de configuration
|
||
def update_json_key(file_path, key, value):
|
||
"""
|
||
Updates a specific key in a JSON file with a new value.
|
||
|
||
:param file_path: Path to the JSON file.
|
||
:param key: The key to update in the JSON file.
|
||
:param value: The new value to assign to the key.
|
||
"""
|
||
try:
|
||
# Load the existing data
|
||
with open(file_path, "r") as file:
|
||
data = json.load(file)
|
||
|
||
# Check if the key exists in the JSON file
|
||
if key in data:
|
||
data[key] = value # Update the key with the new value
|
||
else:
|
||
print(f"Key '{key}' not found in the JSON file.")
|
||
return
|
||
|
||
# Write the updated data back to the file
|
||
with open(file_path, "w") as file:
|
||
json.dump(data, file, indent=2) # Use indent for pretty printing
|
||
|
||
print(f"updating '{key}' to '{value}'.")
|
||
except Exception as e:
|
||
print(f"Error updating the JSON file: {e}")
|
||
|
||
# Define the config file path
|
||
config_file = '/var/www/nebuleair_pro_4g/config.json'
|
||
|
||
# Load the configuration data
|
||
config = load_config(config_file)
|
||
baudrate = config.get('SaraR4_baudrate', 115200) #baudrate du sara R4
|
||
device_id = config.get('deviceID', '').upper() #device ID en maj
|
||
need_to_log = config.get('loop_log', False) #inscription des logs
|
||
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 ()
|
||
|
||
envea_sondes = config.get('envea_sondes', [])
|
||
connected_envea_sondes = [sonde for sonde in envea_sondes if sonde.get('connected', False)]
|
||
selected_networkID = config.get('SARA_R4_neworkID', '')
|
||
|
||
#update device id in the payload json
|
||
payload_json["nebuleairid"] = device_id
|
||
|
||
ser_sara = serial.Serial(
|
||
port='/dev/ttyAMA2',
|
||
baudrate=baudrate, #115200 ou 9600
|
||
parity=serial.PARITY_NONE, #PARITY_NONE, PARITY_EVEN or PARITY_ODD
|
||
stopbits=serial.STOPBITS_ONE,
|
||
bytesize=serial.EIGHTBITS,
|
||
timeout = 2
|
||
)
|
||
|
||
ser_NPM = serial.Serial(
|
||
port='/dev/ttyAMA5',
|
||
baudrate=115200,
|
||
parity=serial.PARITY_EVEN,
|
||
stopbits=serial.STOPBITS_ONE,
|
||
bytesize=serial.EIGHTBITS,
|
||
timeout = 1
|
||
)
|
||
|
||
serial_connections = {}
|
||
|
||
# Sondes Envea
|
||
if connected_envea_sondes:
|
||
# Pour chacune des sondes
|
||
for device in connected_envea_sondes:
|
||
port = device.get('port', 'Unknown')
|
||
name = device.get('name', 'Unknown')
|
||
connected = device.get('connected', False)
|
||
|
||
serial_connections[name] = serial.Serial(
|
||
port=f'/dev/{port}', # Format the port string
|
||
baudrate=9600,
|
||
parity=serial.PARITY_NONE,
|
||
stopbits=serial.STOPBITS_ONE,
|
||
bytesize=serial.EIGHTBITS,
|
||
timeout = 1
|
||
)
|
||
|
||
|
||
|
||
def read_complete_response(serial_connection, timeout=2, end_of_response_timeout=2, wait_for_line=None):
|
||
response = bytearray()
|
||
serial_connection.timeout = timeout
|
||
end_time = time.time() + end_of_response_timeout
|
||
start_time = time.time()
|
||
|
||
while True:
|
||
elapsed_time = time.time() - start_time # Time since function start
|
||
if serial_connection.in_waiting > 0:
|
||
data = serial_connection.read(serial_connection.in_waiting)
|
||
response.extend(data)
|
||
end_time = time.time() + end_of_response_timeout # Reset timeout on new data
|
||
|
||
# Decode and check for the specific line
|
||
if wait_for_line:
|
||
decoded_response = response.decode('utf-8', errors='replace')
|
||
if wait_for_line in decoded_response:
|
||
print(f"[DEBUG] 🔎Found target line: {wait_for_line}")
|
||
break
|
||
elif time.time() > end_time:
|
||
print(f"[DEBUG] Timeout reached. No more data received.")
|
||
break
|
||
time.sleep(0.1) # Short sleep to prevent busy waiting
|
||
# Final response and debug output
|
||
total_elapsed_time = time.time() - start_time
|
||
print(f"[DEBUG] ⏱️ elapsed time: {total_elapsed_time:.2f}s. ⏱️")
|
||
# Check if the elapsed time exceeded 10 seconds
|
||
if total_elapsed_time > 10:
|
||
print(f"[ALERT] 🚨 The operation took too long: {total_elapsed_time:.2f}s. 🚨")
|
||
print('<span style="color: red;font-weight: bold;"></span>')
|
||
print(f"{total_elapsed_time:.2f}s")
|
||
print('</span>')
|
||
|
||
return response.decode('utf-8', errors='replace')
|
||
|
||
# Open and read the JSON file
|
||
try:
|
||
# Send the command to request data (e.g., data for 60 seconds)
|
||
print('<h3>START LOOP</h3>')
|
||
print("Getting NPM values")
|
||
ser_NPM.write(b'\x81\x12\x6D')
|
||
|
||
# Read the response
|
||
byte_data = ser_NPM.readline()
|
||
|
||
#if npm is disconnected byte_data is empty
|
||
|
||
# Extract the state byte and PM data from the response
|
||
state_byte = int.from_bytes(byte_data[2:3], byteorder='big')
|
||
state_bits = [int(bit) for bit in bin(state_byte)[2:].zfill(8)]
|
||
|
||
PM1 = int.from_bytes(byte_data[9:11], 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
|
||
|
||
#Add data to payload CSV
|
||
payload_csv[0] = PM1
|
||
payload_csv[1] = PM25
|
||
payload_csv[2] = PM10
|
||
#Add data to payload JSON
|
||
payload_json["sensordatavalues"].append({"value_type": "NPM_P0", "value": str(PM1)})
|
||
payload_json["sensordatavalues"].append({"value_type": "NPM_P1", "value": str(PM10)})
|
||
payload_json["sensordatavalues"].append({"value_type": "NPM_P2", "value": str(PM25)})
|
||
|
||
# Sonde BME280 connected
|
||
if bme_280_config:
|
||
print("Getting BME280 values")
|
||
#on récupère les infos du BME280 et on les ajoute au payload_csv
|
||
i2c = busio.I2C(board.SCL, board.SDA)
|
||
bme280 = adafruit_bme280.Adafruit_BME280_I2C(i2c, address=0x76)
|
||
bme280.sea_level_pressure = 1013.25 # Update this value for your location
|
||
|
||
payload_csv[3] = round(bme280.temperature, 2)
|
||
payload_csv[4] = round(bme280.humidity, 2)
|
||
payload_csv[5] = round(bme280.pressure, 2)
|
||
|
||
payload_json["sensordatavalues"].append({"value_type": "BME280_temperature", "value": f"{round(bme280.temperature, 2)}"})
|
||
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)}"})
|
||
|
||
|
||
# Sonde Bruit connected
|
||
if i2C_sound_config:
|
||
#on récupère les infos de sound_metermoving et on les ajoute au message
|
||
file_path_data_noise = "/var/www/nebuleair_pro_4g/sound_meter/moving_avg_minute.txt"
|
||
# Read the file and extract the numbers
|
||
try:
|
||
with open(file_path_data_noise, "r") as file:
|
||
content = file.read().strip()
|
||
avg_noise, max_noise, min_noise = map(int, content.split())
|
||
|
||
# Append the variables to the payload_csv
|
||
payload_csv[6] = avg_noise
|
||
payload_csv[7] = max_noise
|
||
payload_csv[8] = min_noise
|
||
|
||
except FileNotFoundError:
|
||
print(f"Error: File {file_path} not found.")
|
||
except ValueError:
|
||
print("Error: File content is not valid numbers.")
|
||
|
||
# Sondes Envea
|
||
if connected_envea_sondes:
|
||
# Pour chacune des sondes
|
||
for device in connected_envea_sondes:
|
||
port = device.get('port', 'Unknown')
|
||
name = device.get('name', 'Unknown')
|
||
coefficient = device.get('coefficient', 'Unknown')
|
||
|
||
print(f"Connected envea Sonde: {name} on port {port} and coefficient {coefficient} ")
|
||
|
||
if name in serial_connections:
|
||
serial_connection = serial_connections[name]
|
||
|
||
try:
|
||
# Write data to the device
|
||
serial_connection.write(
|
||
b"\xFF\x02\x13\x30\x01\x02\x03\x04\x05\x06\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x12\xAF\x88\x03"
|
||
)
|
||
|
||
# Read data from the device
|
||
data_envea = serial_connection.readline()
|
||
if len(data_envea) >= 20:
|
||
byte_20 = data_envea[19]
|
||
byte_20 = byte_20 * coefficient
|
||
|
||
# Update payload CSV based on device type
|
||
if name == "h2s":
|
||
payload_csv[10] = byte_20
|
||
payload_json["sensordatavalues"].append({"value_type": "CAIRSENS_H2S", "value": str(byte_20)})
|
||
if name == "no2":
|
||
payload_csv[9] = byte_20
|
||
payload_json["sensordatavalues"].append({"value_type": "CAIRSENS_NO2", "value": str(byte_20)})
|
||
if name == "o3":
|
||
payload_csv[11] = byte_20
|
||
payload_json["sensordatavalues"].append({"value_type": "CAIRSENS_O3", "value": str(byte_20)})
|
||
|
||
|
||
print(f"Data from envea {name}: {byte_20}")
|
||
else:
|
||
print(f"Données reçues insuffisantes pour {name} pour extraire le 20ème octet.")
|
||
|
||
except serial.SerialException as e:
|
||
print(f"Error communicating with {name}: {e}")
|
||
else:
|
||
print(f"No serial connection for {name}")
|
||
|
||
# Getting the LTE Signal
|
||
print("-> Getting LTE signal <-")
|
||
ser_sara.write(b'AT+CSQ\r')
|
||
response2 = read_complete_response(ser_sara, wait_for_line="OK")
|
||
print('<p class="text-danger-emphasis">')
|
||
print(response2)
|
||
print("</p>")
|
||
match = re.search(r'\+CSQ:\s*(\d+),', response2)
|
||
if match:
|
||
signal_quality = int(match.group(1))
|
||
payload_csv[12]=signal_quality
|
||
time.sleep(1)
|
||
|
||
# On vérifie si le signal n'est pas à 99 pour déconnexion
|
||
# si c'est le cas on essaie de se reconnecter
|
||
if signal_quality == 99:
|
||
print('<span style="color: red;font-weight: bold;">⚠️ATTENTION: Signal Quality indicates no signal (99)⚠️</span>')
|
||
print("TRY TO RECONNECT:")
|
||
command = f'AT+COPS=1,2,"{selected_networkID}"\r'
|
||
ser_sara.write(command.encode('utf-8'))
|
||
responseReconnect = read_complete_response(ser_sara, timeout=20, end_of_response_timeout=20)
|
||
print('<p class="text-danger-emphasis">')
|
||
print(responseReconnect)
|
||
print("</p>")
|
||
|
||
print('🛑STOP LOOP🛑')
|
||
print("<hr>")
|
||
|
||
#on arrete le script pas besoin de continuer
|
||
sys.exit()
|
||
else:
|
||
print("Signal Quality:", signal_quality)
|
||
|
||
|
||
#print(payload_json)
|
||
|
||
'''
|
||
SEND TO AIRCARTO
|
||
'''
|
||
|
||
# Write Data to saraR4
|
||
# 1. Open sensordata_csv.json (with correct data size)
|
||
csv_string = ','.join(str(value) if value is not None else '' for value in payload_csv)
|
||
size_of_string = len(csv_string)
|
||
print("Open JSON:")
|
||
command = f'AT+UDWNFILE="sensordata_csv.json",{size_of_string}\r'
|
||
ser_sara.write(command.encode('utf-8'))
|
||
response_SARA_1 = read_complete_response(ser_sara, wait_for_line=">")
|
||
print(response_SARA_1)
|
||
time.sleep(1)
|
||
|
||
#2. Write to shell
|
||
print("Write data to memory:")
|
||
ser_sara.write(csv_string.encode())
|
||
response_SARA_2 = read_complete_response(ser_sara, wait_for_line="OK")
|
||
print(response_SARA_2)
|
||
|
||
#3. Send to endpoint (with device ID)
|
||
print("Send data (POST REQUEST):")
|
||
command= f'AT+UHTTPC={aircarto_profile_id},4,"/pro_4G/data.php?sensor_id={device_id}","server_response.txt","sensordata_csv.json",4\r'
|
||
ser_sara.write(command.encode('utf-8'))
|
||
|
||
response_SARA_3 = read_complete_response(ser_sara, timeout=5, end_of_response_timeout=120, wait_for_line="+UUHTTPCR")
|
||
|
||
print('<p class="text-danger-emphasis">')
|
||
print(response_SARA_3)
|
||
print("</p>")
|
||
|
||
# Wait for the +UUHTTPCR response
|
||
#print("Waiting for +UUHTTPCR response...")
|
||
#response_received = False
|
||
#while not response_received:
|
||
# response_SARA_3 = read_complete_response(ser_sara, timeout=5)
|
||
# print(response_SARA_3.strip())
|
||
# if "+UUHTTPCR" in response_SARA_3:
|
||
# response_received = True
|
||
|
||
if "+UUHTTPCR" in response_SARA_3:
|
||
print("✅ Received +UUHTTPCR response.")
|
||
|
||
# Les types de réponse
|
||
|
||
# 1.La commande n'a pas fonctionné
|
||
# +CME ERROR: No connection to phone
|
||
# +CME ERROR: Operation not allowed
|
||
|
||
# 2.La commande fonctionne: elle renvoie un code
|
||
# +UUHTTPCR: <profile_id>,<http_command>,<http_result>
|
||
# <http_result>: 1 pour sucess et 0 pour fail
|
||
# +UUHTTPCR: 0,4,1 -> OK
|
||
# +UUHTTPCR: 0,4,0 -> error
|
||
|
||
# Split response into lines
|
||
lines = response_SARA_3.strip().splitlines()
|
||
|
||
# 1.Vérifier si la réponse contient un message d'erreur CME
|
||
if "+CME ERROR" in lines[-1]:
|
||
print("*****")
|
||
print('<span style="color: red;font-weight: bold;">ATTENTION: CME ERROR</span>')
|
||
print("error:", lines[-1])
|
||
print("*****")
|
||
#update status
|
||
update_json_key(config_file, "SARA_R4_network_status", "disconnected")
|
||
|
||
# Gestion de l'erreur spécifique
|
||
if "No connection to phone" in lines[-1]:
|
||
print("No connection to the phone. Retrying or reset may be required.")
|
||
# Actions spécifiques pour ce type d'erreur (par exemple, réinitialiser ou tenter de reconnecter)
|
||
# need to reconnect to network
|
||
# and reset HTTP profile (AT+UHTTP=0) -> ne fonctionne pas..
|
||
# tester un reset avec CFUN 15
|
||
# 1.Reconnexion au réseau (AT+COPS)
|
||
command = f'AT+COPS=1,2,"{selected_networkID}"\r'
|
||
ser_sara.write(command.encode('utf-8'))
|
||
responseReconnect = read_complete_response(ser_sara)
|
||
print("Response reconnect:")
|
||
print(responseReconnect)
|
||
print("End response reconnect")
|
||
|
||
elif "Operation not allowed" in lines[-1]:
|
||
print("Operation not allowed. This may require a different configuration.")
|
||
# Actions spécifiques pour ce type d'erreur
|
||
|
||
# Clignotement LED en cas d'erreur
|
||
GPIO.output(23, GPIO.LOW) # Éteindre la LED définitivement
|
||
for _ in range(4):
|
||
GPIO.output(23, GPIO.HIGH) # Allumer la LED
|
||
time.sleep(0.1)
|
||
GPIO.output(23, GPIO.LOW) # Éteindre la LED
|
||
time.sleep(0.1)
|
||
GPIO.output(23, GPIO.LOW) # Turn off the LED
|
||
|
||
else:
|
||
# 2.Si la réponse contient une réponse HTTP valide
|
||
# Extract HTTP response code from the last line
|
||
# ATTENTION: lines[-1] renvoie l'avant dernière ligne et il peut y avoir un soucis avec le OK
|
||
# rechercher plutot
|
||
http_response = lines[-1] # "+UUHTTPCR: 0,4,0"
|
||
parts = http_response.split(',')
|
||
|
||
# 2.1 code 0 (HTTP failed)
|
||
if len(parts) == 3 and parts[-1] == '0': # The third value indicates success
|
||
print("*****")
|
||
print('<span style="color: red;font-weight: bold;">ATTENTION: HTTP operation failed</span>')
|
||
update_json_key(config_file, "SARA_R4_network_status", "disconnected")
|
||
print("*****")
|
||
print("resetting the URL (domain name):")
|
||
print("Turning off the blue LED...")
|
||
for _ in range(4): # Faire clignoter 4 fois
|
||
GPIO.output(23, GPIO.HIGH) # Allumer la LED
|
||
time.sleep(0.1) # Attendre 100 ms
|
||
GPIO.output(23, GPIO.LOW) # Éteindre la LED
|
||
time.sleep(0.1) # Attendre 100 ms
|
||
GPIO.output(23, GPIO.LOW) # Turn off the LED
|
||
command = f'AT+UHTTP={aircarto_profile_id},1,"{url_nebuleair}"\r'
|
||
ser_sara.write(command.encode('utf-8'))
|
||
response_SARA_31 = read_complete_response(ser_sara)
|
||
if need_to_log:
|
||
print(response_SARA_31)
|
||
|
||
# 2.2 code 1 (HHTP succeded)
|
||
else:
|
||
# Si la commande HTTP a réussi
|
||
print('<span class="badge text-bg-success">HTTP operation successful.</span>')
|
||
update_json_key(config_file, "SARA_R4_network_status", "connected")
|
||
print("Turning on the blue LED...")
|
||
for _ in range(4): # Faire clignoter 4 fois
|
||
GPIO.output(23, GPIO.HIGH) # Allumer la LED
|
||
time.sleep(0.1) # Attendre 100 ms
|
||
GPIO.output(23, GPIO.LOW) # Éteindre la LED
|
||
time.sleep(0.1) # Attendre 100 ms
|
||
GPIO.output(23, GPIO.HIGH) # Turn on the LED
|
||
#4. Read reply from server
|
||
print("Reply from server:")
|
||
ser_sara.write(b'AT+URDFILE="server_response.txt"\r')
|
||
response_SARA_4 = read_complete_response(ser_sara, wait_for_line="OK")
|
||
print('<p class="text-success">')
|
||
print(response_SARA_4)
|
||
print('</p>')
|
||
else:
|
||
print('<span style="color: red;font-weight: bold;">No UUHTTPCR response</span>')
|
||
|
||
#5. empty json
|
||
print("Empty SARA memory:")
|
||
ser_sara.write(b'AT+UDELFILE="sensordata_csv.json"\r')
|
||
response_SARA_5 = read_complete_response(ser_sara, wait_for_line="OK")
|
||
print(response_SARA_5)
|
||
|
||
'''
|
||
SEND TO MICRO SPOT
|
||
'''
|
||
if send_uSpot:
|
||
print(">>>>>>>>")
|
||
print(">>>>>>>>")
|
||
print(">>>>>>>>")
|
||
print("SEND TO MICRO SPOT (HTTP):")
|
||
|
||
#step 4: set url (op_code = 1)
|
||
print("****")
|
||
print("SET URL")
|
||
command = f'AT+UHTTP={uSpot_profile_id},1,"api-prod.uspot.probesys.net"\r'
|
||
ser_sara.write((command + '\r').encode('utf-8'))
|
||
response_SARA_5 = read_complete_response(ser_sara, wait_for_line="OK")
|
||
print(response_SARA_5)
|
||
time.sleep(1)
|
||
|
||
#step 4: set url to SSL (op_code = 6) (http_secure = 1 for HTTPS)(USECMNG_PROFILE = 2)
|
||
print("****")
|
||
print("SET SSL")
|
||
command = f'AT+UHTTP={uSpot_profile_id},6,0\r'
|
||
ser_sara.write(command.encode('utf-8'))
|
||
response_SARA_5 = read_complete_response(ser_sara, wait_for_line="OK")
|
||
print(response_SARA_5)
|
||
time.sleep(1)
|
||
|
||
#step 4: set PORT (op_code = 5)
|
||
print("****")
|
||
print("SET PORT")
|
||
command = f'AT+UHTTP={uSpot_profile_id},5,81\r'
|
||
ser_sara.write((command + '\r').encode('utf-8'))
|
||
response_SARA_55 = read_complete_response(ser_sara, wait_for_line="OK")
|
||
print(response_SARA_55)
|
||
time.sleep(1)
|
||
|
||
|
||
# Write Data to saraR4
|
||
|
||
|
||
# 1. Open sensordata_json.json (with correct data size)
|
||
print("Open JSON:")
|
||
payload_string = json.dumps(payload_json) # Convert dict to JSON string
|
||
size_of_string = len(payload_string)
|
||
command = f'AT+UDWNFILE="sensordata_json.json",{size_of_string}\r'
|
||
ser_sara.write((command + '\r').encode('utf-8'))
|
||
response_SARA_1 = read_complete_response(ser_sara, wait_for_line=">")
|
||
print(response_SARA_1)
|
||
time.sleep(1)
|
||
|
||
#2. Write to shell
|
||
print("Write to memory:")
|
||
ser_sara.write(payload_string.encode())
|
||
response_SARA_2 = read_complete_response(ser_sara, wait_for_line="OK")
|
||
print(response_SARA_2)
|
||
|
||
#step 4: trigger the request (http_command=1 for GET and http_command=1 for POST)
|
||
print("****")
|
||
print("Trigger POST REQUEST")
|
||
command = f'AT+UHTTPC={uSpot_profile_id},4,"/nebuleair?token=2AFF6dQk68daFZ","http.resp","sensordata_json.json",4\r'
|
||
ser_sara.write(command.encode('utf-8'))
|
||
|
||
|
||
response_SARA_3 = read_complete_response(ser_sara, timeout=5, end_of_response_timeout=30, wait_for_line="+UUHTTPCR")
|
||
print('<p class="text-danger-emphasis">')
|
||
print(response_SARA_3)
|
||
print("</p>")
|
||
|
||
#READ REPLY
|
||
print("****")
|
||
print("Read reply from server")
|
||
ser_sara.write(b'AT+URDFILE="http.resp"\r')
|
||
response_SARA_7 = read_complete_response(ser_sara, wait_for_line="OK")
|
||
print('<p class="text-success">')
|
||
print(response_SARA_7)
|
||
print('</p>')
|
||
|
||
|
||
#5. empty json
|
||
print("Empty SARA memory:")
|
||
ser_sara.write(b'AT+UDELFILE="sensordata_json.json"\r')
|
||
response_SARA_8 = read_complete_response(ser_sara, wait_for_line="OK")
|
||
print(response_SARA_8)
|
||
|
||
|
||
|
||
|
||
# Calculate and print the elapsed time
|
||
elapsed_time = time.time() - start_time_script
|
||
print(f"Elapsed time: {elapsed_time:.2f} seconds")
|
||
print("<hr>")
|
||
|
||
|
||
|
||
|
||
except Exception as e:
|
||
print("An error occurred:", e)
|
||
traceback.print_exc() # This prints the full traceback |