Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -1,20 +1,29 @@
|
|
1 |
-
import
|
2 |
-
|
|
|
|
|
3 |
import requests
|
|
|
4 |
from bs4 import BeautifulSoup
|
5 |
from flask_caching import Cache
|
6 |
|
7 |
app = Flask(__name__)
|
8 |
|
9 |
-
# Configure caching
|
10 |
-
# In production you might use Redis or another robust backend.
|
11 |
app.config['CACHE_TYPE'] = 'SimpleCache'
|
12 |
app.config['CACHE_DEFAULT_TIMEOUT'] = 300 # Cache responses for 5 minutes
|
13 |
cache = Cache(app)
|
14 |
|
15 |
-
#
|
16 |
-
|
17 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
18 |
|
19 |
# Internal mapping of crops to pests (for the form)
|
20 |
CROP_TO_PESTS = {
|
@@ -46,43 +55,14 @@ CROP_MAPPING = {
|
|
46 |
|
47 |
# Map our internal pest names to external page values per crop.
|
48 |
PEST_MAPPING = {
|
49 |
-
"Cotton": {
|
50 |
-
|
51 |
-
},
|
52 |
-
"
|
53 |
-
|
54 |
-
|
55 |
-
},
|
56 |
-
"
|
57 |
-
"FallArmyWorm": "74"
|
58 |
-
},
|
59 |
-
"Rice": {
|
60 |
-
"Blast": "75",
|
61 |
-
"GallMidge": "76",
|
62 |
-
"YSB": "77",
|
63 |
-
"PlantHopper": "78",
|
64 |
-
"BlueBeetle": "79",
|
65 |
-
"BacterialLeafBlight": "80"
|
66 |
-
},
|
67 |
-
"Soybean": {
|
68 |
-
"Girdlebeetle": "81",
|
69 |
-
"H.armigera": "82",
|
70 |
-
"Semilooper": "83",
|
71 |
-
"Spodoptera": "84",
|
72 |
-
"StemFLy": "85"
|
73 |
-
},
|
74 |
-
"Tur": {
|
75 |
-
"Wilt": "86",
|
76 |
-
"Webbed_Leaves": "87",
|
77 |
-
"Pod_damage": "88"
|
78 |
-
},
|
79 |
-
"Sugarcane": {
|
80 |
-
"FallArmyGrub": "89",
|
81 |
-
"WhiteGrub": "90"
|
82 |
-
},
|
83 |
-
"Sorgum": {
|
84 |
-
"FallArmyWorm": "91"
|
85 |
-
}
|
86 |
}
|
87 |
|
88 |
# Parameter codes and labels for the final image URL
|
@@ -103,13 +83,13 @@ def index():
|
|
103 |
week = request.args.get('week', '')
|
104 |
param = request.args.get('param', '')
|
105 |
|
106 |
-
|
107 |
if crop and pest and year and week and param:
|
108 |
# Build the external image URL (using HTTP)
|
109 |
base_url = f"http://www.icar-crida.res.in:8080/naip/gisimages/{crop}/{year}/{pest}_"
|
110 |
external_image_url = f"{base_url}{param}{week}.jpg"
|
111 |
-
#
|
112 |
-
|
113 |
|
114 |
return render_template('index.html',
|
115 |
crops=list(CROP_TO_PESTS.keys()),
|
@@ -121,8 +101,9 @@ def index():
|
|
121 |
selected_year=year,
|
122 |
selected_week=week,
|
123 |
selected_param=param,
|
124 |
-
|
125 |
|
|
|
126 |
@app.route('/fetch_weeks')
|
127 |
@cache.cached(timeout=300, query_string=True)
|
128 |
def fetch_weeks():
|
@@ -153,48 +134,27 @@ def fetch_weeks():
|
|
153 |
weeks = [str(i) for i in range(1, 53)]
|
154 |
return jsonify({"weeks": weeks})
|
155 |
|
156 |
-
#
|
157 |
-
@app.route('/
|
158 |
-
def
|
159 |
-
global cached_image, cached_mimetype
|
160 |
-
# If the "url" parameter doesn't match our cached URL, you might consider triggering a prefetch update.
|
161 |
external_url = request.args.get('url')
|
162 |
-
if
|
163 |
-
return
|
|
|
|
|
|
|
|
|
164 |
else:
|
165 |
-
# If no pre-fetched image is available, fall back to a direct fetch.
|
166 |
try:
|
167 |
resp = requests.get(external_url, timeout=10)
|
168 |
-
|
|
|
|
|
|
|
|
|
|
|
169 |
except Exception as e:
|
170 |
return str(e), 500
|
171 |
|
172 |
-
# Background prefetching – we also store the URL that was prefetched.
|
173 |
-
def prefetch_image_task():
|
174 |
-
global cached_image, cached_mimetype
|
175 |
-
# For demonstration, we prefetch one specific image.
|
176 |
-
# In a more dynamic scenario, you could maintain a dict of URL -> image data.
|
177 |
-
while True:
|
178 |
-
# Here, update the URL as needed. For example, if you have default parameters:
|
179 |
-
url = "http://www.icar-crida.res.in:8080/naip/gisimages/7/2024-25/74_Maxt1.jpg"
|
180 |
-
try:
|
181 |
-
response = requests.get(url, timeout=10)
|
182 |
-
if response.status_code == 200:
|
183 |
-
cached_image = response.content
|
184 |
-
cached_mimetype = response.headers.get('Content-Type', 'image/jpeg')
|
185 |
-
prefetch_image_task.cached_url = url
|
186 |
-
print("Prefetched image from", url)
|
187 |
-
else:
|
188 |
-
print("Failed to prefetch, status code:", response.status_code)
|
189 |
-
except Exception as ex:
|
190 |
-
print("Prefetch error:", ex)
|
191 |
-
time.sleep(300) # Update every 5 minutes
|
192 |
-
|
193 |
-
# Initialize cached_url attribute for our task function.
|
194 |
-
prefetch_image_task.cached_url = ""
|
195 |
-
|
196 |
-
# Start the background prefetch thread
|
197 |
-
threading.Thread(target=prefetch_image_task, daemon=True).start()
|
198 |
-
|
199 |
if __name__ == '__main__':
|
200 |
app.run(debug=True)
|
|
|
1 |
+
import os
|
2 |
+
import hashlib
|
3 |
+
import time
|
4 |
+
import threading
|
5 |
import requests
|
6 |
+
from flask import Flask, render_template, request, jsonify, Response, send_file, url_for
|
7 |
from bs4 import BeautifulSoup
|
8 |
from flask_caching import Cache
|
9 |
|
10 |
app = Flask(__name__)
|
11 |
|
12 |
+
# Configure in-memory caching for non-image routes
|
|
|
13 |
app.config['CACHE_TYPE'] = 'SimpleCache'
|
14 |
app.config['CACHE_DEFAULT_TIMEOUT'] = 300 # Cache responses for 5 minutes
|
15 |
cache = Cache(app)
|
16 |
|
17 |
+
# Directory to store cached images
|
18 |
+
CACHE_DIR = "cache_images"
|
19 |
+
if not os.path.exists(CACHE_DIR):
|
20 |
+
os.makedirs(CACHE_DIR)
|
21 |
+
|
22 |
+
def get_cache_filename(url):
|
23 |
+
"""Generate a unique filename for a given URL."""
|
24 |
+
h = hashlib.md5(url.encode('utf-8')).hexdigest()
|
25 |
+
# Here we assume JPEG. You might want to derive extension from url or headers.
|
26 |
+
return os.path.join(CACHE_DIR, f"{h}.jpg")
|
27 |
|
28 |
# Internal mapping of crops to pests (for the form)
|
29 |
CROP_TO_PESTS = {
|
|
|
55 |
|
56 |
# Map our internal pest names to external page values per crop.
|
57 |
PEST_MAPPING = {
|
58 |
+
"Cotton": {"FallArmyWorm": "71"},
|
59 |
+
"Gram": {"H.armigera": "72", "Wilt": "73"},
|
60 |
+
"Maize": {"FallArmyWorm": "74"},
|
61 |
+
"Rice": {"Blast": "75", "GallMidge": "76", "YSB": "77", "PlantHopper": "78", "BlueBeetle": "79", "BacterialLeafBlight": "80"},
|
62 |
+
"Soybean": {"Girdlebeetle": "81", "H.armigera": "82", "Semilooper": "83", "Spodoptera": "84", "StemFLy": "85"},
|
63 |
+
"Tur": {"Wilt": "86", "Webbed_Leaves": "87", "Pod_damage": "88"},
|
64 |
+
"Sugarcane": {"FallArmyGrub": "89", "WhiteGrub": "90"},
|
65 |
+
"Sorgum": {"FallArmyWorm": "91"}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
66 |
}
|
67 |
|
68 |
# Parameter codes and labels for the final image URL
|
|
|
83 |
week = request.args.get('week', '')
|
84 |
param = request.args.get('param', '')
|
85 |
|
86 |
+
image_url_param = ""
|
87 |
if crop and pest and year and week and param:
|
88 |
# Build the external image URL (using HTTP)
|
89 |
base_url = f"http://www.icar-crida.res.in:8080/naip/gisimages/{crop}/{year}/{pest}_"
|
90 |
external_image_url = f"{base_url}{param}{week}.jpg"
|
91 |
+
# Instead of proxying on every request, pass the external URL to the template.
|
92 |
+
image_url_param = external_image_url
|
93 |
|
94 |
return render_template('index.html',
|
95 |
crops=list(CROP_TO_PESTS.keys()),
|
|
|
101 |
selected_year=year,
|
102 |
selected_week=week,
|
103 |
selected_param=param,
|
104 |
+
image_url_param=image_url_param)
|
105 |
|
106 |
+
# Cache this route based on its query string.
|
107 |
@app.route('/fetch_weeks')
|
108 |
@cache.cached(timeout=300, query_string=True)
|
109 |
def fetch_weeks():
|
|
|
134 |
weeks = [str(i) for i in range(1, 53)]
|
135 |
return jsonify({"weeks": weeks})
|
136 |
|
137 |
+
# New endpoint to serve a locally cached image file.
|
138 |
+
@app.route('/cached-image')
|
139 |
+
def cached_image_route():
|
|
|
|
|
140 |
external_url = request.args.get('url')
|
141 |
+
if not external_url:
|
142 |
+
return "Missing URL", 400
|
143 |
+
|
144 |
+
cache_filename = get_cache_filename(external_url)
|
145 |
+
if os.path.exists(cache_filename):
|
146 |
+
return send_file(cache_filename, mimetype="image/jpeg")
|
147 |
else:
|
|
|
148 |
try:
|
149 |
resp = requests.get(external_url, timeout=10)
|
150 |
+
if resp.status_code == 200:
|
151 |
+
with open(cache_filename, "wb") as f:
|
152 |
+
f.write(resp.content)
|
153 |
+
return send_file(cache_filename, mimetype=resp.headers.get('Content-Type', 'image/jpeg'))
|
154 |
+
else:
|
155 |
+
return "Error downloading image", resp.status_code
|
156 |
except Exception as e:
|
157 |
return str(e), 500
|
158 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
159 |
if __name__ == '__main__':
|
160 |
app.run(debug=True)
|