from flask import Flask, jsonify, render_template
from pysolarmanv5 import PySolarmanV5
import config

app = Flask(__name__)

def get_inverter_data():
    """
    Connects to the inverter and reads voltage registers.
    Returns a dictionary with the data.
    """
    try:
        inverter = PySolarmanV5(
            config.INVERTER_IP,
            config.INVERTER_SERIAL,
            port=config.INVERTER_PORT,
            mb_slave_id=config.INVERTER_SLAVE_ID,
            verbose=False
        )
        
        # Reading blocks:
        # Block 1: 150 - 216 (67 registers) - Voltages, Currents, Battery, PV, Control
        # Block 2: 600 - 627 (28 registers) - BMS Data
        # Block 3: 245 (1 register) - Max Grid Output
        # Block 4: 292 - 293 (2 registers) - Peak Shaving
        # Block 5: 314 - 325 (12 registers) - Advanced Limits
        
        block1 = inverter.read_holding_registers(register_addr=150, quantity=67)
        block2 = inverter.read_holding_registers(register_addr=600, quantity=28)
        block3 = inverter.read_holding_registers(register_addr=245, quantity=1)
        block4 = inverter.read_holding_registers(register_addr=292, quantity=2)
        block5 = inverter.read_holding_registers(register_addr=314, quantity=12)
        
        def to_signed(val):
            return val if val < 32768 else val - 65536

        data = {}
        
        # Block 1 Parsing (150-216)
        data["input_voltage"] = round(block1[0] * 0.1, 1)      # 150
        data["output_voltage"] = round(block1[4] * 0.1, 1)     # 154
        data["load_voltage"] = round(block1[7] * 0.1, 1)       # 157
        
        data["grid_current"] = round(to_signed(block1[10]) * 0.01, 2)       # 160
        data["grid_clamp_current"] = round(to_signed(block1[12]) * 0.01, 2) # 162
        data["output_current"] = round(to_signed(block1[14]) * 0.01, 2)     # 164
        
        data["load_current"] = round(to_signed(block1[29]) * 0.01, 2)       # 179
        
        data["batt_temp"] = round(to_signed(block1[32]) * 0.1, 1)           # 182
        data["batt_voltage"] = round(block1[33] * 0.01, 2)                  # 183
        data["batt_soc"] = block1[34]                                       # 184
        data["batt_charge_status"] = block1[35]                             # 185
        data["pv1_power"] = block1[36]                                      # 186
        data["pv2_power"] = block1[37]                                      # 187
        
        data["batt_power"] = to_signed(block1[40])                          # 190
        data["batt_current"] = round(to_signed(block1[41]) * 0.01, 2)       # 191
        
        data["grid_relay_status"] = block1[44]                              # 194
        data["gen_relay_status"] = block1[45]                               # 195
        
        data["max_charge_current"] = block1[60]                             # 210
        data["max_discharge_current"] = block1[61]                          # 211
        data["batt_charge_efficiency"] = block1[66]                         # 216
        
        # Block 2 Parsing (BMS 600-627)
        data["bms1_soc"] = block2[3]                                        # 603
        data["bms1_charge_voltage"] = round(block2[6] * 0.01, 2)            # 606
        data["bms1_charge_current"] = round(block2[7] * 0.1, 1)             # 607
        
        data["bms2_soc"] = block2[17]                                       # 617
        data["bms2_charge_voltage"] = round(block2[20] * 0.01, 2)           # 620
        data["bms2_charge_current"] = round(block2[21] * 0.1, 1)            # 621

        # Block 3 Parsing (245)
        data["max_grid_output_power"] = block3[0]                           # 245

        # Block 4 Parsing (292-293)
        data["gen_peak_shaving_power"] = block4[0]                          # 292
        data["grid_peak_shaving_power"] = block4[1]                         # 293

        # Block 5 Parsing (314-325)
        data["discharge_voltage"] = round(block5[0] * 0.01, 2)              # 314
        data["charge_current_limit"] = block5[1]                            # 315
        data["discharge_current_limit"] = block5[2]                         # 316
        data["real_time_capacity"] = block5[3]                              # 317
        data["real_time_voltage"] = round(block5[4] * 0.01, 2)              # 318
        # 319 skipped
        data["max_charge_current_limit"] = block5[6]                        # 320
        data["max_discharge_current_limit"] = block5[7]                     # 321
        # 322-324 skipped
        data["lithium_battery_type"] = block5[11]                           # 325

        inverter.disconnect()
        
        data["status"] = "success"
        return data
        
    except Exception as e:
        return {
            "status": "error",
            "message": str(e)
        }

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/api/data')
def api_data():
    data = get_inverter_data()
    return jsonify(data)

if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0')
