asif-coder commited on
Commit
9088dcb
·
verified ·
1 Parent(s): 43cdd32

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +75 -106
app.py CHANGED
@@ -1,126 +1,95 @@
1
  import gradio as gr
2
  import pandas as pd
3
  import numpy as np
4
- from sklearn.linear_model import LinearRegression
5
- from PIL import Image
6
  import datetime
 
7
 
8
- # --- 2026 DYNAMIC MARKET DATA & CONFIG ---
9
- MARKET_DATA = {
10
- "panel_pkr_per_watt": 32, # Tier-1 N-Type/Bifacial
11
- "avg_sun_hours": 5.2, # Pakistan Yearly Average
12
- "import_rate": 55.0, # PKR/unit including taxes
13
- "export_rate": 11.0, # NEPRA Prosumer Regs 2026
14
- "li_battery_pkr_kwh": 48000, # LiFePO4 pricing
15
- "installation_fee": 0.15, # 15% markup for BOS
16
- "bank_rate": 0.14 # 14% Solar Financing Rate
17
  }
18
 
19
- APPLIANCES = {
20
- "LED Bulb (12W)": 12, "Ceiling Fan (80W)": 80, "Inverter AC (1.5 Ton)": 1500,
21
- "Refrigerator": 250, "Water Pump (1HP)": 746, "Washing Machine": 500
22
- }
23
-
24
- # --- MODULE 1: ML-BASED LOAD PREDICTION (V2) ---
25
- def predict_seasonal_load(avg_monthly_units):
26
- """Simple ML model to predict peak summer load based on average units."""
27
- # Dummy data: Training correlation between avg units and peak monthly units
28
- X = np.array([[200], [400], [600], [800], [1000]])
29
- y = np.array([[310], [580], [890], [1150], [1400]]) # Summer peaks
30
- model = LinearRegression().fit(X, y)
31
- prediction = model.predict([[avg_monthly_units]])
32
- return float(prediction[0][0])
33
 
34
- # --- MODULE 2: CORE ENGINEERING LOGIC ---
35
- def calculate_solar_system(selected_apps, app_counts, system_type, backup_hrs, units_input):
36
- # Calculate Load
37
- total_watts = sum([APPLIANCES[app] * count for app, count in zip(selected_apps, app_counts) if app])
38
- daily_kwh = (total_watts * 8) / 1000 # Default 8h usage if no bill provided
 
39
 
40
- if units_input > 0:
41
- peak_monthly = predict_seasonal_load(units_input)
42
- daily_kwh = peak_monthly / 30
43
-
44
- # System Size (20% losses)
45
- required_kw = (daily_kwh / MARKET_DATA["avg_sun_hours"]) * 1.2
46
- required_kw = round(max(required_kw, 3.0), 1) # Min 3kW for net billing logic
 
 
 
 
 
47
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48
  # Financials
49
- panel_cost = required_kw * 1000 * MARKET_DATA["panel_pkr_per_watt"]
50
- inverter_costs = {"On-Grid": 150000, "Hybrid": 280000, "Off-Grid": 220000}
51
- inv_cost = inverter_costs[system_type] * (required_kw / 5) # Scaled to 5kW base
 
 
52
 
53
- battery_cost = (daily_kwh * (backup_hrs/24) * MARKET_DATA["li_battery_pkr_kwh"]) if backup_hrs > 0 else 0
54
 
55
- total_investment = (panel_cost + inv_cost + battery_cost) * (1 + MARKET_DATA["installation_fee"])
56
 
57
- # ROI (Net Billing Logic)
58
- # Savings = (Generated Units * Grid Rate) - (Adjustment for Export rate diff)
59
- annual_gen = required_kw * MARKET_DATA["avg_sun_hours"] * 365
60
- annual_savings = annual_gen * (MARKET_DATA["import_rate"] * 0.7 + MARKET_DATA["export_rate"] * 0.3)
61
- payback = total_investment / annual_savings
62
-
63
- # EMI (5 Year Tenure)
64
- p = total_investment * 0.8 # 20% Downpayment
65
- r = MARKET_DATA["bank_rate"] / 12
66
- n = 60
67
- emi = p * (r * (1+r)**n) / ((1+r)**n - 1)
68
-
69
- return total_watts, required_kw, int(total_investment), round(payback, 1), int(emi)
70
-
71
- # --- MODULE 3: ADMIN & OCR (STUBS) ---
72
- def ocr_bill(image):
73
- return 450 # Mocking 450 units detected from bill image
74
 
75
  # --- GRADIO UI ---
76
- with gr.Blocks(theme=gr.themes.Soft()) as demo:
77
- gr.Markdown("# ☀️ SolarExpert PK v2.0 (2026 Edition)\n### AI-Powered Solar Estimation & Net Billing Analysis")
78
 
79
- with gr.Tab("1. Consumption Analysis"):
80
- with gr.Row():
81
- bill_img = gr.Image(label="Upload Last Month's Bill (OCR)", type="pil")
82
- units_in = gr.Number(label="Or Enter Monthly Units (kWh)", value=300)
83
-
84
- app_select = gr.CheckboxGroup(choices=list(APPLIANCES.keys()), label="Select Priority Appliances")
85
- app_counts = gr.Dataframe(headers=["Quantity"], row_count=len(APPLIANCES), col_count=1, interactive=True, value=[[1]]*len(APPLIANCES))
86
-
87
- with gr.Tab("2. System Configuration"):
88
- sys_type = gr.Radio(["On-Grid", "Hybrid", "Off-Grid"], label="System Architecture", value="Hybrid")
89
- backup = gr.Slider(0, 12, step=1, label="Battery Backup (Hours)")
90
- calc_btn = gr.Button("Generate Production Report", variant="primary")
91
-
92
- with gr.Tab("3. Results & Financials"):
93
- with gr.Row():
94
- res_kw = gr.Label(label="Required System Size (kW)")
95
- res_cost = gr.Label(label="Estimated Price (PKR)")
96
- res_emi = gr.Label(label="Monthly EMI (Bank Alfalah/JS)")
97
-
98
- roi_plot = gr.Markdown()
99
-
100
- with gr.Accordion("Admin Dashboard & Installer Contact", open=False):
101
- gr.Markdown("Contacting nearest AEDB Certified Installers...")
102
- name = gr.Textbox(label="Full Name")
103
- phone = gr.Textbox(label="WhatsApp Number")
104
- gr.Button("Request Official Quote")
105
-
106
- # Mapping Logic
107
- def run_engine(img, units, apps, counts, stype, bkp):
108
- if img: units = ocr_bill(img)
109
- counts_list = [row[0] for row in counts]
110
- load, kw, cost, roi, emi = calculate_solar_system(apps, counts_list, stype, bkp, units)
111
-
112
- roi_report = f"""
113
- ### Financial Feasibility
114
- * **Payback Period:** {roi} Years
115
- * **Annual Energy Yield:** ~{int(kw * 1500)} Units
116
- * **Monthly Savings:** PKR {int((kw * 1500 * 45)/12):,}
117
-
118
- > **Note:** Calculations include a 20% system loss factor and 2026 Net Billing buyback rates.
119
- """
120
- return f"{kw} kW", f"PKR {cost:,}", f"PKR {emi:,}/mo", roi_report
121
 
122
- calc_btn.click(run_engine,
123
- inputs=[bill_img, units_in, app_select, app_counts, sys_type, backup],
124
- outputs=[res_kw, res_cost, res_emi, roi_plot])
125
 
126
  demo.launch()
 
1
  import gradio as gr
2
  import pandas as pd
3
  import numpy as np
4
+ from fpdf import FPDF
 
5
  import datetime
6
+ import os
7
 
8
+ # --- 2026 MARKET DATA CONFIG ---
9
+ CONFIG = {
10
+ "panel_pkr_watt": 32,
11
+ "sun_hours": 5.2,
12
+ "grid_rate": 55.0,
13
+ "buyback_rate": 11.0,
14
+ "li_battery_kwh": 48000,
15
+ "markup": 0.15,
 
16
  }
17
 
18
+ # --- MODULE: BANK API INTEGRATION ---
19
+ def fetch_bank_rates():
20
+ """
21
+ Simulated API call to Bank Alfalah/JS Bank for 2026 Solar Financing.
22
+ In production, use: requests.get('https://api.bankalfalah.com/rates')
23
+ """
24
+ return {"interest_rate": 0.14, "tenure_months": 60, "bank_name": "Bank Alfalah"}
 
 
 
 
 
 
 
25
 
26
+ # --- MODULE: PDF GENERATOR ---
27
+ def generate_report(load, size, cost, emi, roi):
28
+ pdf = FPDF()
29
+ pdf.add_page()
30
+ pdf.set_font("Arial", 'B', 16)
31
+ pdf.cell(200, 10, "Solar Solution Report - Pakistan 2026", ln=True, align='C')
32
 
33
+ pdf.set_font("Arial", size=12)
34
+ pdf.ln(10)
35
+ pdf.cell(200, 10, f"Date: {datetime.datetime.now().strftime('%Y-%m-%d')}", ln=True)
36
+ pdf.cell(200, 10, f"Total Connected Load: {load} Watts", ln=True)
37
+ pdf.cell(200, 10, f"Recommended System Size: {size} kW", ln=True)
38
+ pdf.cell(200, 10, f"Estimated Total Investment: PKR {cost:,}", ln=True)
39
+ pdf.cell(200, 10, f"Monthly EMI Plan: PKR {emi:,}/month", ln=True)
40
+ pdf.cell(200, 10, f"Estimated Payback Period: {roi} Years", ln=True)
41
+
42
+ report_path = "Solar_Report_PK.pdf"
43
+ pdf.output(report_path)
44
+ return report_path
45
 
46
+ # --- CORE LOGIC ---
47
+ def solar_engine(app_selection, counts, sys_type, backup_hrs):
48
+ # Load math (20% losses included)
49
+ watts_map = {"AC": 1500, "Fan": 80, "Fridge": 250, "Lights": 12}
50
+ total_watts = sum([watts_map[k] for k in app_selection])
51
+
52
+ daily_units = (total_watts * 10) / 1000 # Avg 10h usage
53
+ sys_size = round((daily_units / CONFIG["sun_hours"]) * 1.2, 1)
54
+
55
+ panel_cost = sys_size * 1000 * CONFIG["panel_pkr_watt"]
56
+ battery_cost = (daily_units * (backup_hrs/24) * CONFIG["li_battery_kwh"])
57
+
58
+ total_cost = int((panel_cost + battery_cost + 200000) * (1 + CONFIG["markup"]))
59
+
60
  # Financials
61
+ bank = fetch_bank_rates()
62
+ p = total_cost * 0.8
63
+ r = bank["interest_rate"] / 12
64
+ n = bank["tenure_months"]
65
+ emi = int(p * (r * (1+r)**n) / ((1+r)**n - 1))
66
 
67
+ roi = round(total_cost / (daily_units * 365 * 45), 1)
68
 
69
+ pdf_file = generate_report(total_watts, sys_size, total_cost, emi, roi)
70
 
71
+ summary = f"""### 📋 System Insights
72
+ - **Size:** {sys_size} kW
73
+ - **Total Cost:** PKR {total_cost:,}
74
+ - **EMI:** PKR {emi:,}/mo ({bank['bank_name']})
75
+ """
76
+ return summary, pdf_file
 
 
 
 
 
 
 
 
 
 
 
77
 
78
  # --- GRADIO UI ---
79
+ with gr.Blocks(theme=gr.themes.Default()) as demo:
80
+ gr.Markdown("# ☀️ Solar Consultant Pro (Pakistan)")
81
 
82
+ with gr.Row():
83
+ with gr.Column():
84
+ apps = gr.CheckboxGroup(["AC", "Fan", "Fridge", "Lights"], label="Appliances")
85
+ sys = gr.Dropdown(["On-Grid", "Hybrid", "Off-Grid"], label="System Type", value="Hybrid")
86
+ bkp = gr.Slider(0, 12, value=4, label="Battery Backup (Hours)")
87
+ btn = gr.Button("Analyze & Generate PDF", variant="primary")
88
+
89
+ with gr.Column():
90
+ out_md = gr.Markdown()
91
+ out_pdf = gr.File(label="Download Full Report")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
 
93
+ btn.click(solar_engine, inputs=[apps, gr.State(1), sys, bkp], outputs=[out_md, out_pdf])
 
 
94
 
95
  demo.launch()