'''
Loop to run every minutes
* * * * * /usr/bin/python3 /var/www/nebuleair_pro_4g/NPM/get_data_modbus_loop.py ttyAMA5

saves data to a json file /var/www/nebuleair_pro_4g/NPM/data/data.json

first time running the script?
sudo mkdir /var/www/nebuleair_pro_4g/NPM/data
sudo touch /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()
