Spaces:
Sleeping
Sleeping
Upload 30 files
Browse files- .gitattributes +1 -0
- .idea/.gitignore +3 -0
- .idea/inspectionProfiles/profiles_settings.xml +6 -0
- .idea/misc.xml +10 -0
- .idea/modules.xml +8 -0
- .idea/pythonProject.iml +10 -0
- .idea/workspace.xml +77 -0
- app.py +171 -0
- audio/disease.mp3 +0 -0
- audio/pest.mp3 +0 -0
- code_flow +15 -0
- prasunethon.html +143 -0
- static/backgrnd.jpg +3 -0
- static/img2.jpg +0 -0
- static/img4.jpg +0 -0
- static/img5.jpg +0 -0
- static/img6.jpg +0 -0
- static/styles.css +294 -0
- static/tea-estate.jpg +0 -0
- static/ultrasonic02.png +0 -0
- static/uv.jpg +0 -0
- templates/activity-log.html +147 -0
- templates/index.html +387 -0
- templates/notification.html +0 -0
- templates/sensors.html +159 -0
- templates/zones.html +282 -0
- uploads/brown_blight.jpg +0 -0
- uploads/img2.jpg +0 -0
- uploads/tea_mosquito.jpg +0 -0
- uploads/ultrasonic02.png +0 -0
- uploads/uv.jpg +0 -0
.gitattributes
CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
36 |
+
static/backgrnd.jpg filter=lfs diff=lfs merge=lfs -text
|
.idea/.gitignore
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
# Default ignored files
|
2 |
+
/shelf/
|
3 |
+
/workspace.xml
|
.idea/inspectionProfiles/profiles_settings.xml
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<component name="InspectionProjectProfileManager">
|
2 |
+
<settings>
|
3 |
+
<option name="USE_PROJECT_PROFILE" value="false" />
|
4 |
+
<version value="1.0" />
|
5 |
+
</settings>
|
6 |
+
</component>
|
.idea/misc.xml
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0" encoding="UTF-8"?>
|
2 |
+
<project version="4">
|
3 |
+
<component name="Black">
|
4 |
+
<option name="sdkName" value="Python 3.11 (pythonProject)" />
|
5 |
+
</component>
|
6 |
+
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.11 (pythonProject)" project-jdk-type="Python SDK" />
|
7 |
+
<component name="PyCharmProfessionalAdvertiser">
|
8 |
+
<option name="shown" value="true" />
|
9 |
+
</component>
|
10 |
+
</project>
|
.idea/modules.xml
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0" encoding="UTF-8"?>
|
2 |
+
<project version="4">
|
3 |
+
<component name="ProjectModuleManager">
|
4 |
+
<modules>
|
5 |
+
<module fileurl="file://$PROJECT_DIR$/.idea/pythonProject.iml" filepath="$PROJECT_DIR$/.idea/pythonProject.iml" />
|
6 |
+
</modules>
|
7 |
+
</component>
|
8 |
+
</project>
|
.idea/pythonProject.iml
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0" encoding="UTF-8"?>
|
2 |
+
<module type="PYTHON_MODULE" version="4">
|
3 |
+
<component name="NewModuleRootManager">
|
4 |
+
<content url="file://$MODULE_DIR$">
|
5 |
+
<excludeFolder url="file://$MODULE_DIR$/venv" />
|
6 |
+
</content>
|
7 |
+
<orderEntry type="inheritedJdk" />
|
8 |
+
<orderEntry type="sourceFolder" forTests="false" />
|
9 |
+
</component>
|
10 |
+
</module>
|
.idea/workspace.xml
ADDED
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0" encoding="UTF-8"?>
|
2 |
+
<project version="4">
|
3 |
+
<component name="AutoImportSettings">
|
4 |
+
<option name="autoReloadType" value="SELECTIVE" />
|
5 |
+
</component>
|
6 |
+
<component name="ChangeListManager">
|
7 |
+
<list default="true" id="493841b9-08f3-4b64-b579-c7b98f001729" name="Changes" comment="" />
|
8 |
+
<option name="SHOW_DIALOG" value="false" />
|
9 |
+
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
10 |
+
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
11 |
+
<option name="LAST_RESOLUTION" value="IGNORE" />
|
12 |
+
</component>
|
13 |
+
<component name="FileTemplateManagerImpl">
|
14 |
+
<option name="RECENT_TEMPLATES">
|
15 |
+
<list>
|
16 |
+
<option value="HTML File" />
|
17 |
+
</list>
|
18 |
+
</option>
|
19 |
+
</component>
|
20 |
+
<component name="ProjectColorInfo">{
|
21 |
+
"associatedIndex": 3
|
22 |
+
}</component>
|
23 |
+
<component name="ProjectId" id="2dIWWOAevy1AZn7m9dCU83K4U4H" />
|
24 |
+
<component name="ProjectViewState">
|
25 |
+
<option name="hideEmptyMiddlePackages" value="true" />
|
26 |
+
<option name="showLibraryContents" value="true" />
|
27 |
+
</component>
|
28 |
+
<component name="PropertiesComponent">{
|
29 |
+
"keyToString": {
|
30 |
+
"DefaultHtmlFileTemplate": "HTML File",
|
31 |
+
"RunOnceActivity.OpenProjectViewOnStart": "true",
|
32 |
+
"RunOnceActivity.ShowReadmeOnStart": "true",
|
33 |
+
"last_opened_file_path": "C:/Users/roshn/PycharmProjects/pythonProject/templates"
|
34 |
+
}
|
35 |
+
}</component>
|
36 |
+
<component name="RecentsManager">
|
37 |
+
<key name="CopyFile.RECENT_KEYS">
|
38 |
+
<recent name="C:\Users\roshn\PycharmProjects\pythonProject\templates" />
|
39 |
+
<recent name="C:\Users\roshn\PycharmProjects\pythonProject\static" />
|
40 |
+
<recent name="C:\Users\roshn\PycharmProjects\pythonProject" />
|
41 |
+
</key>
|
42 |
+
</component>
|
43 |
+
<component name="RunManager">
|
44 |
+
<configuration name="app" type="PythonConfigurationType" factoryName="Python" nameIsGenerated="true">
|
45 |
+
<module name="pythonProject" />
|
46 |
+
<option name="INTERPRETER_OPTIONS" value="" />
|
47 |
+
<option name="PARENT_ENVS" value="true" />
|
48 |
+
<envs>
|
49 |
+
<env name="PYTHONUNBUFFERED" value="1" />
|
50 |
+
</envs>
|
51 |
+
<option name="SDK_HOME" value="" />
|
52 |
+
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
53 |
+
<option name="IS_MODULE_SDK" value="true" />
|
54 |
+
<option name="ADD_CONTENT_ROOTS" value="true" />
|
55 |
+
<option name="ADD_SOURCE_ROOTS" value="true" />
|
56 |
+
<option name="SCRIPT_NAME" value="C:\Users\roshn\PycharmProjects\pythonProject\app.py" />
|
57 |
+
<option name="PARAMETERS" value="" />
|
58 |
+
<option name="SHOW_COMMAND_LINE" value="false" />
|
59 |
+
<option name="EMULATE_TERMINAL" value="false" />
|
60 |
+
<option name="MODULE_MODE" value="false" />
|
61 |
+
<option name="REDIRECT_INPUT" value="false" />
|
62 |
+
<option name="INPUT_FILE" value="" />
|
63 |
+
<method v="2" />
|
64 |
+
</configuration>
|
65 |
+
</component>
|
66 |
+
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
|
67 |
+
<component name="TaskManager">
|
68 |
+
<task active="true" id="Default" summary="Default task">
|
69 |
+
<changelist id="493841b9-08f3-4b64-b579-c7b98f001729" name="Changes" comment="" />
|
70 |
+
<created>1709696103263</created>
|
71 |
+
<option name="number" value="Default" />
|
72 |
+
<option name="presentableId" value="Default" />
|
73 |
+
<updated>1709696103263</updated>
|
74 |
+
</task>
|
75 |
+
<servers />
|
76 |
+
</component>
|
77 |
+
</project>
|
app.py
ADDED
@@ -0,0 +1,171 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from flask import Flask, render_template, request, jsonify, send_from_directory
|
2 |
+
import pymysql
|
3 |
+
import matplotlib.pyplot as plt
|
4 |
+
import io
|
5 |
+
import base64
|
6 |
+
from gtts import gTTS
|
7 |
+
import os
|
8 |
+
import random
|
9 |
+
from ai71 import AI71
|
10 |
+
|
11 |
+
app = Flask(__name__)
|
12 |
+
db = pymysql.connect(host="localhost", user="root", password="1234", database="tea_farm")
|
13 |
+
cursor = db.cursor()
|
14 |
+
|
15 |
+
UPLOAD_FOLDER = 'uploads'
|
16 |
+
OUTPUT_DIRECTORY = 'audio'
|
17 |
+
if not os.path.exists(UPLOAD_FOLDER):
|
18 |
+
os.makedirs(UPLOAD_FOLDER)
|
19 |
+
if not os.path.exists(OUTPUT_DIRECTORY):
|
20 |
+
os.makedirs(OUTPUT_DIRECTORY)
|
21 |
+
|
22 |
+
# Text for pest and disease
|
23 |
+
pest_text = '''tea mosquito bugs,to get rid,spray with neem oil and garlic,use sticky traps, and trap crops like castor . Expect results in 2 to 4 weeks.চা মশার বাগ, পরিত্রাণ পেতে, নিম তেল এবং রসুন দিয়ে স্প্রে করুন, আঠালো ফাঁদ ব্যবহার করুন এবং ক্যাস্টরের মতো ফসল ফাঁদ করুন। 2-4 সপ্তাহের মধ্যে ফলাফল আশা করুন।'''
|
24 |
+
disease_text = '''Detected Disease: Brown Blight is a fungal disease To treat it spray a mix of baking soda, water and apply organic mulch to keep soil healthy.ব্রাউন ব্লাইট একটি ছত্রাকজনিত রোগের চিকিৎসার জন্য বেকিং সোডা, পানির মিশ্রণ স্প্রে করুন এবং মাটি সুস্থ রাখতে জৈব মালচ প্রয়োগ করুন'''
|
25 |
+
|
26 |
+
@app.route('/home')
|
27 |
+
def home():
|
28 |
+
return render_template('index.html')
|
29 |
+
|
30 |
+
@app.route('/notification')
|
31 |
+
def notification():
|
32 |
+
return render_template('notification.html')
|
33 |
+
|
34 |
+
@app.route('/', methods=['GET', 'POST'])
|
35 |
+
def upload_file():
|
36 |
+
pest_filename = None
|
37 |
+
disease_filename = None
|
38 |
+
pest_audio_file = "pest.mp3"
|
39 |
+
disease_audio_file = "disease.mp3"
|
40 |
+
|
41 |
+
if request.method == 'POST':
|
42 |
+
if 'pest_file' in request.files:
|
43 |
+
pest_file = request.files['pest_file']
|
44 |
+
if pest_file.filename != '':
|
45 |
+
pest_filename = pest_file.filename
|
46 |
+
pest_file.save(os.path.join(UPLOAD_FOLDER, pest_filename))
|
47 |
+
tts_pest = gTTS(text=pest_text, lang='en', slow=False)
|
48 |
+
tts_pest.save(os.path.join(OUTPUT_DIRECTORY, pest_audio_file))
|
49 |
+
|
50 |
+
if 'disease_file' in request.files:
|
51 |
+
disease_file = request.files['disease_file']
|
52 |
+
if disease_file.filename != '':
|
53 |
+
disease_filename = disease_file.filename
|
54 |
+
disease_file.save(os.path.join(UPLOAD_FOLDER, disease_filename))
|
55 |
+
tts_disease = gTTS(text=disease_text, lang='en', slow=False)
|
56 |
+
tts_disease.save(os.path.join(OUTPUT_DIRECTORY, disease_audio_file))
|
57 |
+
|
58 |
+
return render_template('index.html', pest_filename=pest_filename, disease_filename=disease_filename,
|
59 |
+
pest_audio_file=pest_audio_file, disease_audio_file=disease_audio_file)
|
60 |
+
|
61 |
+
AI71_API_KEY = "api71-api-20725a9d-46d6-4baf-9e26-abfca35ab242"
|
62 |
+
@app.route('/chat', methods=['POST'])
|
63 |
+
def chat():
|
64 |
+
message = request.json['message']
|
65 |
+
ai71 = AI71(AI71_API_KEY)
|
66 |
+
response = ""
|
67 |
+
for chunk in ai71.chat.completions.create(
|
68 |
+
model="tiiuae/falcon-180b-chat",
|
69 |
+
messages=[
|
70 |
+
{"role": "system", "content": "You are a helpful assistant for a farming system.Guide the user properly to increase the yield."},
|
71 |
+
{"role": "user", "content": message},
|
72 |
+
],
|
73 |
+
stream=True,
|
74 |
+
):
|
75 |
+
if chunk.choices[0].delta.content:
|
76 |
+
response += chunk.choices[0].delta.content
|
77 |
+
return jsonify({'response': response.replace('\n','<br>')})
|
78 |
+
@app.route('/uploads/<filename>')
|
79 |
+
def uploaded_file(filename):
|
80 |
+
return send_from_directory(UPLOAD_FOLDER, filename)
|
81 |
+
|
82 |
+
@app.route('/audio/<filename>')
|
83 |
+
def audio_file(filename):
|
84 |
+
return send_from_directory(OUTPUT_DIRECTORY, filename)
|
85 |
+
|
86 |
+
@app.route('/sensors')
|
87 |
+
def sensors():
|
88 |
+
# Fetch a random row from the database
|
89 |
+
cursor.execute("SELECT * FROM sensor_data ORDER BY RAND() LIMIT 1")
|
90 |
+
sensor_data = cursor.fetchone()
|
91 |
+
|
92 |
+
if sensor_data:
|
93 |
+
sensor_dict = {
|
94 |
+
'id': sensor_data[0],
|
95 |
+
'temperature': sensor_data[1],
|
96 |
+
'humidity': sensor_data[2],
|
97 |
+
'irValue': sensor_data[3],
|
98 |
+
'distance': sensor_data[4],
|
99 |
+
'timestamp': sensor_data[5]
|
100 |
+
}
|
101 |
+
else:
|
102 |
+
sensor_dict = {
|
103 |
+
'temperature': None,
|
104 |
+
'humidity': None,
|
105 |
+
'irValue': None,
|
106 |
+
'distance': None,
|
107 |
+
'timestamp': None
|
108 |
+
}
|
109 |
+
|
110 |
+
return render_template('sensors.html', sensor_data=sensor_dict)
|
111 |
+
|
112 |
+
@app.route('/zones')
|
113 |
+
def zones():
|
114 |
+
return render_template('zones.html')
|
115 |
+
|
116 |
+
@app.route('/activity-log')
|
117 |
+
def activity_log():
|
118 |
+
|
119 |
+
# Fetch data for IR value distribution plot
|
120 |
+
cursor.execute("SELECT ir_value FROM sensor_data")
|
121 |
+
ir_values = cursor.fetchall()
|
122 |
+
count_0 = ir_values.count((0,))
|
123 |
+
count_1 = ir_values.count((1,))
|
124 |
+
labels = ['Pest Swarm Detected', 'No Pest Swarm Detected']
|
125 |
+
sizes = [count_0, count_1]
|
126 |
+
plt.figure(figsize=(6, 6))
|
127 |
+
plt.pie(sizes, labels=labels, autopct='%1.1f%%')
|
128 |
+
plt.title('IR Value Distribution')
|
129 |
+
plt.axis('equal')
|
130 |
+
ir_buffer = io.BytesIO()
|
131 |
+
plt.savefig(ir_buffer, format='png')
|
132 |
+
ir_buffer.seek(0)
|
133 |
+
ir_plot_data = base64.b64encode(ir_buffer.getvalue()).decode('utf-8')
|
134 |
+
plt.close()
|
135 |
+
|
136 |
+
# Fetch data for average closeness of pests plot
|
137 |
+
cursor.execute("SELECT timestamp, distance FROM sensor_data WHERE distance < 500")
|
138 |
+
data = cursor.fetchall()
|
139 |
+
timestamps = [row[0] for row in data]
|
140 |
+
distances = [row[1] for row in data]
|
141 |
+
average_distance = sum(distances) / len(distances)
|
142 |
+
plt.figure(figsize=(10, 6))
|
143 |
+
plt.plot(timestamps, distances, marker='o', linestyle='-')
|
144 |
+
plt.xlabel('Timestamp')
|
145 |
+
plt.ylabel('Distance (cm)')
|
146 |
+
plt.title('Average Closeness of Pests over Time')
|
147 |
+
plt.xticks(rotation=45)
|
148 |
+
plt.grid(True)
|
149 |
+
distance_buffer = io.BytesIO()
|
150 |
+
plt.savefig(distance_buffer, format='png')
|
151 |
+
distance_buffer.seek(0)
|
152 |
+
distance_plot_data = base64.b64encode(distance_buffer.getvalue()).decode('utf-8')
|
153 |
+
plt.close()
|
154 |
+
|
155 |
+
return render_template('activity-log.html', ir_plot_data=ir_plot_data, distance_plot_data=distance_plot_data)
|
156 |
+
|
157 |
+
@app.route('/sensor-data', methods=['POST'])
|
158 |
+
def update_sensor_data():
|
159 |
+
data = request.get_json()
|
160 |
+
temperature = data.get('temperature')
|
161 |
+
humidity = data.get('humidity')
|
162 |
+
ir_value = data.get('irValue')
|
163 |
+
distance = data.get('distance')
|
164 |
+
sql = "INSERT INTO sensor_data (temperature, humidity, ir_value, distance) VALUES (%s, %s, %s, %s)"
|
165 |
+
val = (temperature, humidity, ir_value, distance)
|
166 |
+
cursor.execute(sql, val)
|
167 |
+
db.commit()
|
168 |
+
return jsonify(success=True)
|
169 |
+
|
170 |
+
if __name__ == '__main__':
|
171 |
+
app.run(debug=True, host='0.0.0.0', port=5000)
|
audio/disease.mp3
ADDED
Binary file (182 kB). View file
|
|
audio/pest.mp3
ADDED
Binary file (230 kB). View file
|
|
code_flow
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
digraph {
|
2 |
+
node [fillcolor=lightblue shape=box style=filled]
|
3 |
+
line0 [label="def example_function(x):"]
|
4 |
+
line1 [label="if x < 0:"]
|
5 |
+
line1 -> line2 [label=True]
|
6 |
+
line2 [label="return 'Negative'" shape=oval]
|
7 |
+
line2 -> line3
|
8 |
+
line3 [label="elif x == 0:"]
|
9 |
+
line3 -> line4 [label=True]
|
10 |
+
line4 [label="return 'Zero'" shape=oval]
|
11 |
+
line4 -> line5
|
12 |
+
line5 [label="else:"]
|
13 |
+
line5 -> line6 [label=True]
|
14 |
+
line6 [label="return 'Positive'" shape=oval]
|
15 |
+
}
|
prasunethon.html
ADDED
@@ -0,0 +1,143 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html lang="en">
|
3 |
+
<head>
|
4 |
+
<meta charset="UTF-8">
|
5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6 |
+
<title>Resource Consumption Monitor</title>
|
7 |
+
<style>
|
8 |
+
body {
|
9 |
+
font-family: 'Arial', sans-serif;
|
10 |
+
background-color: #f7f7f7;
|
11 |
+
margin: 0;
|
12 |
+
padding: 20px;
|
13 |
+
color: #333;
|
14 |
+
}
|
15 |
+
h1 {
|
16 |
+
text-align: center;
|
17 |
+
color: #4CAF50;
|
18 |
+
margin-bottom: 40px;
|
19 |
+
}
|
20 |
+
.resource-card {
|
21 |
+
background-color: #fff;
|
22 |
+
padding: 20px;
|
23 |
+
border-radius: 10px;
|
24 |
+
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
25 |
+
margin-bottom: 20px;
|
26 |
+
display: flex;
|
27 |
+
align-items: center;
|
28 |
+
transition: transform 0.2s ease;
|
29 |
+
}
|
30 |
+
.resource-card:hover {
|
31 |
+
transform: translateY(-5px);
|
32 |
+
}
|
33 |
+
.resource-card img {
|
34 |
+
width: 60px;
|
35 |
+
height: 60px;
|
36 |
+
margin-right: 20px;
|
37 |
+
}
|
38 |
+
.card-content {
|
39 |
+
flex: 1;
|
40 |
+
display: flex;
|
41 |
+
flex-direction: column;
|
42 |
+
justify-content: center;
|
43 |
+
}
|
44 |
+
.card-title {
|
45 |
+
font-weight: bold;
|
46 |
+
font-size: 1.2em;
|
47 |
+
color: #333;
|
48 |
+
margin-bottom: 5px;
|
49 |
+
}
|
50 |
+
.data-value {
|
51 |
+
font-size: 1em;
|
52 |
+
color: #777;
|
53 |
+
}
|
54 |
+
.chart-container {
|
55 |
+
width: 50%;
|
56 |
+
max-width: 300px;
|
57 |
+
}
|
58 |
+
</style>
|
59 |
+
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
60 |
+
</head>
|
61 |
+
<body>
|
62 |
+
<h1>Resource Consumption</h1>
|
63 |
+
<div id="resource-cards"></div>
|
64 |
+
|
65 |
+
<script>
|
66 |
+
function fetchData() {
|
67 |
+
const resources = [
|
68 |
+
{ name: "Electricity", icon: "path/to/electricity.png", yesterday: 20, predicted: 710, unit: "MU(Million Units)", data: [21,24,25,22.5,27,22, 33] },
|
69 |
+
{ name: "Water", icon: "path/to/water.png", yesterday: 192, predicted: 3698, unit: "Million Liters", data: [198,193,215,206,214,200,219]},
|
70 |
+
{ name: "Gas", icon: "path/to/gas.png", yesterday: 179, predicted: 4982, unit: "kilo m³", data: [175,176,174,177,175,147,190] },
|
71 |
+
{ name: "Internet", icon: "path/to/internet.png", yesterday: 1.38, predicted: 34.9, unit: "PB", data: [1.22,1.38,1.24,1.24,1.36,1.35,2.78] },
|
72 |
+
{ name: "Waste", icon: "path/to/waste.png", yesterday: 864, predicted: 21850, unit: "metric tons", data: [874,859,847,841,853,864,845] },
|
73 |
+
// Add more resources here with their details
|
74 |
+
];
|
75 |
+
|
76 |
+
const resourceCards = document.getElementById("resource-cards");
|
77 |
+
|
78 |
+
resources.forEach((resource, index) => {
|
79 |
+
const card = document.createElement("div");
|
80 |
+
card.classList.add("resource-card");
|
81 |
+
|
82 |
+
const img = document.createElement("img");
|
83 |
+
img.src = resource.icon;
|
84 |
+
card.appendChild(img);
|
85 |
+
|
86 |
+
const cardContent = document.createElement("div");
|
87 |
+
cardContent.classList.add("card-content");
|
88 |
+
|
89 |
+
const title = document.createElement("h3");
|
90 |
+
title.classList.add("card-title");
|
91 |
+
title.textContent = resource.name;
|
92 |
+
cardContent.appendChild(title);
|
93 |
+
|
94 |
+
const yesterdayData = document.createElement("p");
|
95 |
+
yesterdayData.textContent = Yesterday: ${resource.yesterday} ${resource.unit};
|
96 |
+
cardContent.appendChild(yesterdayData);
|
97 |
+
|
98 |
+
const predictedData = document.createElement("p");
|
99 |
+
predictedData.textContent = Predicted (Next Month(July)): ${resource.predicted} ${resource.unit};
|
100 |
+
predictedData.classList.add("data-value");
|
101 |
+
cardContent.appendChild(predictedData);
|
102 |
+
|
103 |
+
card.appendChild(cardContent);
|
104 |
+
|
105 |
+
const chartContainer = document.createElement("div");
|
106 |
+
chartContainer.classList.add("chart-container");
|
107 |
+
const canvas = document.createElement("canvas");
|
108 |
+
canvas.id = chart-${index};
|
109 |
+
chartContainer.appendChild(canvas);
|
110 |
+
card.appendChild(chartContainer);
|
111 |
+
|
112 |
+
resourceCards.appendChild(card);
|
113 |
+
|
114 |
+
// Initialize the chart
|
115 |
+
const ctx = canvas.getContext('2d');
|
116 |
+
new Chart(ctx, {
|
117 |
+
type: 'line',
|
118 |
+
data: {
|
119 |
+
labels: ['Monday', 'Tuesday', 'wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'],
|
120 |
+
datasets: [{
|
121 |
+
label: resource.name,
|
122 |
+
data: resource.data,
|
123 |
+
backgroundColor: 'rgba(75, 192, 192, 0.2)',
|
124 |
+
borderColor: 'rgba(75, 192, 192, 1)',
|
125 |
+
borderWidth: 1,
|
126 |
+
fill: true
|
127 |
+
}]
|
128 |
+
},
|
129 |
+
options: {
|
130 |
+
scales: {
|
131 |
+
y: {
|
132 |
+
beginAtZero: false
|
133 |
+
}
|
134 |
+
}
|
135 |
+
}
|
136 |
+
});
|
137 |
+
});
|
138 |
+
}
|
139 |
+
|
140 |
+
fetchData();
|
141 |
+
</script>
|
142 |
+
</body>
|
143 |
+
</html>
|
static/backgrnd.jpg
ADDED
![]() |
Git LFS Details
|
static/img2.jpg
ADDED
![]() |
static/img4.jpg
ADDED
![]() |
static/img5.jpg
ADDED
![]() |
static/img6.jpg
ADDED
![]() |
static/styles.css
ADDED
@@ -0,0 +1,294 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/* Farm Tech System */
|
2 |
+
|
3 |
+
*{
|
4 |
+
margin: 0;
|
5 |
+
padding: 0;
|
6 |
+
box-sizing: border-box;
|
7 |
+
|
8 |
+
}
|
9 |
+
|
10 |
+
.body{
|
11 |
+
width: 100%;
|
12 |
+
padding: 50px;
|
13 |
+
background-image: url('tea-estate.jpg');
|
14 |
+
}
|
15 |
+
|
16 |
+
|
17 |
+
body {
|
18 |
+
background-image: url('tea-estate.jpg');
|
19 |
+
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
20 |
+
font-weight: bolder;
|
21 |
+
font-size: x-large;
|
22 |
+
height: 100vh;
|
23 |
+
color: #123C69;
|
24 |
+
}
|
25 |
+
|
26 |
+
header {
|
27 |
+
color: white;
|
28 |
+
padding: 8px ;
|
29 |
+
text-align: center;
|
30 |
+
}
|
31 |
+
|
32 |
+
.logo {
|
33 |
+
font-family: 'Poppins';
|
34 |
+
font-size: 24px;
|
35 |
+
text-align: center;
|
36 |
+
}
|
37 |
+
|
38 |
+
.navbar {
|
39 |
+
margin-top: 20px;
|
40 |
+
}
|
41 |
+
|
42 |
+
.nav-links {
|
43 |
+
list-style: none;
|
44 |
+
padding: 0;
|
45 |
+
display: flex;
|
46 |
+
justify-content: center;
|
47 |
+
}
|
48 |
+
|
49 |
+
.nav-links li {
|
50 |
+
margin: 0 15px;
|
51 |
+
}
|
52 |
+
|
53 |
+
.nav-links a {
|
54 |
+
color:#AC3B61 ;
|
55 |
+
font-weight: bolder;
|
56 |
+
font-size: larger;
|
57 |
+
text-decoration: none;
|
58 |
+
}
|
59 |
+
|
60 |
+
|
61 |
+
h2 {
|
62 |
+
font-size: 24px;
|
63 |
+
margin-bottom: 10px;
|
64 |
+
}
|
65 |
+
|
66 |
+
p {
|
67 |
+
line-height: 1.6;
|
68 |
+
|
69 |
+
}
|
70 |
+
|
71 |
+
|
72 |
+
|
73 |
+
|
74 |
+
.nav-links li:hover a
|
75 |
+
{
|
76 |
+
background: rgb(255, 255, 255);
|
77 |
+
color: black;
|
78 |
+
padding: .25rem .5rem;
|
79 |
+
transition: all ease-in 300ms;
|
80 |
+
border-radius: 25px;
|
81 |
+
|
82 |
+
}
|
83 |
+
|
84 |
+
.animate-charcter
|
85 |
+
{
|
86 |
+
text-align: right;
|
87 |
+
display: flex;
|
88 |
+
align-items: center;
|
89 |
+
justify-content: center;
|
90 |
+
background-image: linear-gradient(
|
91 |
+
-225deg,
|
92 |
+
#231557 0%,
|
93 |
+
#44107a 29%,
|
94 |
+
#ff1361 67%,
|
95 |
+
#fff800 100%
|
96 |
+
);
|
97 |
+
|
98 |
+
background-size: auto auto;
|
99 |
+
background-clip: border-box;
|
100 |
+
background-size: 200% auto;
|
101 |
+
color: #AC3B61;
|
102 |
+
background-clip: text;
|
103 |
+
text-justify: transparent;
|
104 |
+
-webkit-background-clip: text;
|
105 |
+
-webkit-text-fill-color: transparent;
|
106 |
+
animation: textclip 2s linear infinite;
|
107 |
+
display: inline-block ;
|
108 |
+
font-size: 80px;
|
109 |
+
font-family: Georgia, 'Times New Roman', Times, serif;
|
110 |
+
font-weight: bold;
|
111 |
+
|
112 |
+
}
|
113 |
+
|
114 |
+
@keyframes textclip {
|
115 |
+
to {
|
116 |
+
background-position: center;
|
117 |
+
}
|
118 |
+
};
|
119 |
+
|
120 |
+
|
121 |
+
*{
|
122 |
+
background-color: #eee2dc;
|
123 |
+
margin-bottom: 20px;
|
124 |
+
padding: 0;
|
125 |
+
box-sizing: border-box;
|
126 |
+
}
|
127 |
+
|
128 |
+
body{
|
129 |
+
align-items: center;
|
130 |
+
justify-content: center;
|
131 |
+
}
|
132 |
+
|
133 |
+
@keyframes scroll{
|
134 |
+
0%{
|
135 |
+
transform: translateX(0);
|
136 |
+
}
|
137 |
+
100%{
|
138 |
+
transform: translateX(calc(-250px * 7));
|
139 |
+
}
|
140 |
+
}
|
141 |
+
|
142 |
+
.slider{
|
143 |
+
height: 200px;
|
144 |
+
margin: auto;
|
145 |
+
overflow: hidden;
|
146 |
+
position: relative;
|
147 |
+
width: auto;
|
148 |
+
padding: 0 30px;
|
149 |
+
}
|
150 |
+
|
151 |
+
/* .slider::before, .slider::after {
|
152 |
+
content: '';
|
153 |
+
width: calc(50vw - 125px); /* Adjust the width for the desired padding */
|
154 |
+
|
155 |
+
|
156 |
+
*{
|
157 |
+
margin: 0;
|
158 |
+
padding: 0;
|
159 |
+
box-sizing: border-box;
|
160 |
+
font-family: Verdana, Geneva, Tahoma, sans-serif;
|
161 |
+
}
|
162 |
+
|
163 |
+
.container{
|
164 |
+
display: flex;
|
165 |
+
/* flex-direction: column; */
|
166 |
+
justify-content: center;
|
167 |
+
align-items: center;
|
168 |
+
text-align: center;
|
169 |
+
font-weight: bolder;
|
170 |
+
margin: 20px 20px 0 20px;
|
171 |
+
padding-top: 10%;
|
172 |
+
}
|
173 |
+
|
174 |
+
.container .heading{
|
175 |
+
width: 50%;
|
176 |
+
padding-bottom: 50px;
|
177 |
+
}
|
178 |
+
|
179 |
+
.container .heading h3{
|
180 |
+
font-size: 3em;
|
181 |
+
font-weight: bolder;
|
182 |
+
padding-bottom: 10px;
|
183 |
+
border-bottom: 3px solid #222;
|
184 |
+
}
|
185 |
+
|
186 |
+
.container .heading h3 span{
|
187 |
+
font-weight: 50;
|
188 |
+
}
|
189 |
+
|
190 |
+
.container .box{
|
191 |
+
display: flex;
|
192 |
+
flex-direction: row;
|
193 |
+
justify-content: space-between;
|
194 |
+
}
|
195 |
+
|
196 |
+
.container .box .dream{
|
197 |
+
display: flex;
|
198 |
+
flex-direction: column;
|
199 |
+
width: 32.5%;
|
200 |
+
}
|
201 |
+
|
202 |
+
.container .box .dream img{
|
203 |
+
width: 100%;
|
204 |
+
padding-bottom: 15px;
|
205 |
+
|
206 |
+
}
|
207 |
+
|
208 |
+
/* @media only screen and (max-width: 769px){
|
209 |
+
.container .box{
|
210 |
+
flex-direction: column;
|
211 |
+
}
|
212 |
+
}
|
213 |
+
|
214 |
+
.container .box .dream{
|
215 |
+
width: 100%;
|
216 |
+
} */
|
217 |
+
|
218 |
+
|
219 |
+
/* Default styles for all devices */
|
220 |
+
.body {
|
221 |
+
font-size: 16px;
|
222 |
+
}
|
223 |
+
|
224 |
+
/* Tablet styles */
|
225 |
+
@media (max-width: 1024px) {
|
226 |
+
body {
|
227 |
+
font-size: 14px;
|
228 |
+
}
|
229 |
+
}
|
230 |
+
|
231 |
+
/* Mobile styles */
|
232 |
+
@media (max-width: 768px) {
|
233 |
+
body {
|
234 |
+
font-size: 12px;
|
235 |
+
}
|
236 |
+
}
|
237 |
+
|
238 |
+
/* Adjust the footer for mobile and tablet views */
|
239 |
+
@media only screen and (max-width: 768px) {
|
240 |
+
.footer {
|
241 |
+
width: 125%;
|
242 |
+
flex-direction: column;
|
243 |
+
align-items: center;
|
244 |
+
}
|
245 |
+
|
246 |
+
.contact {
|
247 |
+
text-align: left;
|
248 |
+
text-indent: 0;
|
249 |
+
margin: 10px 0;
|
250 |
+
font-size: x-small;
|
251 |
+
}
|
252 |
+
|
253 |
+
.contact h2{
|
254 |
+
text-align: left;
|
255 |
+
text-indent: 0;
|
256 |
+
margin: 10px 0;
|
257 |
+
font-size: x-small;
|
258 |
+
|
259 |
+
}
|
260 |
+
|
261 |
+
.iframe
|
262 |
+
{
|
263 |
+
width: 100%;
|
264 |
+
padding: 10px;
|
265 |
+
}
|
266 |
+
|
267 |
+
.contact p:first-child{
|
268 |
+
|
269 |
+
text-align: left;
|
270 |
+
text-indent: 0;
|
271 |
+
margin: 10px 0;
|
272 |
+
font-size: x-small;
|
273 |
+
|
274 |
+
}
|
275 |
+
|
276 |
+
.contact p:last-child{
|
277 |
+
|
278 |
+
text-align: left;
|
279 |
+
text-indent: 0;
|
280 |
+
margin: 10px 0;
|
281 |
+
font-size: x-small;
|
282 |
+
}
|
283 |
+
|
284 |
+
.developer {
|
285 |
+
text-align: right;
|
286 |
+
text-indent: 0;
|
287 |
+
margin: 10px 0;
|
288 |
+
font-size: x-small;
|
289 |
+
}
|
290 |
+
|
291 |
+
.footer {
|
292 |
+
width: 100vw !important;
|
293 |
+
}
|
294 |
+
}
|
static/tea-estate.jpg
ADDED
![]() |
static/ultrasonic02.png
ADDED
![]() |
static/uv.jpg
ADDED
![]() |
templates/activity-log.html
ADDED
@@ -0,0 +1,147 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html lang="en">
|
3 |
+
<head>
|
4 |
+
<meta charset="UTF-8">
|
5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6 |
+
<link href='https://fonts.googleapis.com/css?family=Poppins:400,700&display=swap' rel='stylesheet'>
|
7 |
+
<link rel="stylesheet" href="{{ url_for('static', filename='styles.css') }}">
|
8 |
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
|
9 |
+
<title>Farm Tech System - Activity Log</title>
|
10 |
+
<style>
|
11 |
+
:root {
|
12 |
+
--primary-color: #2C5F2D;
|
13 |
+
--secondary-color: #97BC62;
|
14 |
+
--text-color: #333;
|
15 |
+
--background-color: rgba(255, 255, 255, 0.9);
|
16 |
+
}
|
17 |
+
|
18 |
+
body {
|
19 |
+
font-family: 'Poppins', sans-serif;
|
20 |
+
background-image: url('https://media.istockphoto.com/id/136546538/photo/tea-plantation.jpg?s=612x612&w=0&k=20&c=CMMc6rLPJTvuhwYhj2Q7XjNT4acTi5iUiAGnHsgOPkw=');
|
21 |
+
background-size: cover;
|
22 |
+
background-repeat: no-repeat;
|
23 |
+
background-attachment: fixed;
|
24 |
+
color: var(--text-color);
|
25 |
+
margin: 0;
|
26 |
+
padding: 0;
|
27 |
+
}
|
28 |
+
|
29 |
+
.container {
|
30 |
+
max-width: 1200px;
|
31 |
+
margin: 0 auto;
|
32 |
+
padding: 20px;
|
33 |
+
background-color: var(--background-color);
|
34 |
+
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
35 |
+
border-radius: 10px;
|
36 |
+
}
|
37 |
+
|
38 |
+
.animate-charcter {
|
39 |
+
text-align: center;
|
40 |
+
background-image: linear-gradient(
|
41 |
+
-225deg,
|
42 |
+
#231557 0%,
|
43 |
+
#44107a 29%,
|
44 |
+
#ff1361 67%,
|
45 |
+
#fff800 100%
|
46 |
+
);
|
47 |
+
background-size: 200% auto;
|
48 |
+
color: #AC3B61;
|
49 |
+
background-clip: text;
|
50 |
+
text-fill-color: transparent;
|
51 |
+
-webkit-background-clip: text;
|
52 |
+
-webkit-text-fill-color: transparent;
|
53 |
+
animation: textclip 2s linear infinite;
|
54 |
+
font-size: 48px;
|
55 |
+
font-weight: bold;
|
56 |
+
margin-bottom: 20px;
|
57 |
+
}
|
58 |
+
|
59 |
+
@keyframes textclip {
|
60 |
+
to {
|
61 |
+
background-position: 200% center;
|
62 |
+
}
|
63 |
+
}
|
64 |
+
|
65 |
+
.navbar {
|
66 |
+
background-color: var(--primary-color);
|
67 |
+
padding: 10px 0;
|
68 |
+
margin-bottom: 20px;
|
69 |
+
}
|
70 |
+
|
71 |
+
.nav-links {
|
72 |
+
list-style: none;
|
73 |
+
padding: 0;
|
74 |
+
display: flex;
|
75 |
+
justify-content: center;
|
76 |
+
}
|
77 |
+
|
78 |
+
.nav-links li {
|
79 |
+
margin: 0 15px;
|
80 |
+
}
|
81 |
+
|
82 |
+
.nav-links a {
|
83 |
+
color: white;
|
84 |
+
font-weight: bold;
|
85 |
+
font-size: 18px;
|
86 |
+
text-decoration: none;
|
87 |
+
transition: all 0.3s ease;
|
88 |
+
}
|
89 |
+
|
90 |
+
.nav-links li:hover a {
|
91 |
+
background: white;
|
92 |
+
color: var(--primary-color);
|
93 |
+
padding: 5px 10px;
|
94 |
+
border-radius: 25px;
|
95 |
+
}
|
96 |
+
|
97 |
+
h2 {
|
98 |
+
color: var(--primary-color);
|
99 |
+
font-size: 28px;
|
100 |
+
margin-top: 30px;
|
101 |
+
margin-bottom: 20px;
|
102 |
+
}
|
103 |
+
|
104 |
+
#welcome-section img {
|
105 |
+
max-width: 100%;
|
106 |
+
height: auto;
|
107 |
+
margin-bottom: 30px;
|
108 |
+
border-radius: 10px;
|
109 |
+
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
110 |
+
}
|
111 |
+
|
112 |
+
footer {
|
113 |
+
background-color: var(--primary-color);
|
114 |
+
color: white;
|
115 |
+
text-align: center;
|
116 |
+
padding: 20px 0;
|
117 |
+
margin-top: 40px;
|
118 |
+
}
|
119 |
+
</style>
|
120 |
+
</head>
|
121 |
+
<body>
|
122 |
+
<div class="container">
|
123 |
+
<header>
|
124 |
+
<h1 class="animate-charcter">Farm Tech System - Activity Log</h1>
|
125 |
+
<nav class="navbar">
|
126 |
+
<ul class="nav-links">
|
127 |
+
<li><a href="{{ url_for('home') }}"><i class="fas fa-home"></i> Dashboard</a></li>
|
128 |
+
<li><a href="sensors"><i class="fas fa-cogs"></i> Sensors</a></li>
|
129 |
+
<li><a href="zones"><i class="fas fa-envelope"></i> Zones</a></li>
|
130 |
+
</ul>
|
131 |
+
</nav>
|
132 |
+
</header>
|
133 |
+
|
134 |
+
<section id="welcome-section">
|
135 |
+
<h2>IR Value Distribution</h2>
|
136 |
+
<img src="data:image/png;base64,{{ ir_plot_data }}" alt="IR Value Distribution">
|
137 |
+
|
138 |
+
<h2>Average Closeness of Pests over Time</h2>
|
139 |
+
<img src="data:image/png;base64,{{ distance_plot_data }}" alt="Average Closeness of Pests over Time">
|
140 |
+
</section>
|
141 |
+
</div>
|
142 |
+
|
143 |
+
<footer>
|
144 |
+
<p>© 2024 Farm Tech System. All rights reserved.</p>
|
145 |
+
</footer>
|
146 |
+
</body>
|
147 |
+
</html>
|
templates/index.html
ADDED
@@ -0,0 +1,387 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html lang="en">
|
3 |
+
<head>
|
4 |
+
<meta charset="UTF-8">
|
5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6 |
+
<link href='https://fonts.googleapis.com/css?family=Poppins' rel='stylesheet'>
|
7 |
+
<link rel="stylesheet" href="{{ url_for('static', filename='styles.css') }}">
|
8 |
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
|
9 |
+
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
10 |
+
<title>Farm Tech System</title>
|
11 |
+
<style>
|
12 |
+
body {
|
13 |
+
font-family: Arial, sans-serif;
|
14 |
+
}
|
15 |
+
.container {
|
16 |
+
display: flex;
|
17 |
+
justify-content: space-between;
|
18 |
+
margin-top: 20px;
|
19 |
+
text-align: center;
|
20 |
+
}
|
21 |
+
.column {
|
22 |
+
flex: 0 0 48%;
|
23 |
+
padding: 30px;
|
24 |
+
border: 1px solid #ccc;
|
25 |
+
box-shadow: 2px 2px 12px #aaa;
|
26 |
+
background-color: rgba(240, 240, 240, 0.7);
|
27 |
+
}
|
28 |
+
.attention {
|
29 |
+
background-color: #ffcccc;
|
30 |
+
padding: 10px;
|
31 |
+
border: 1px solid #ff6666;
|
32 |
+
margin-bottom: -200px;
|
33 |
+
text-align: center;
|
34 |
+
width: 48%;
|
35 |
+
box-sizing: border-box;
|
36 |
+
animation: blink 1s infinite;
|
37 |
+
}
|
38 |
+
@keyframes blink {
|
39 |
+
0% { background-color: #ffcccc; }
|
40 |
+
50% { background-color: #ff9999; }
|
41 |
+
100% { background-color: #ffcccc; }
|
42 |
+
}
|
43 |
+
@keyframes pulsate {
|
44 |
+
0% { opacity: 1; }
|
45 |
+
50% { opacity: 0.5; }
|
46 |
+
100% { opacity: 1; }
|
47 |
+
}
|
48 |
+
.attention p {
|
49 |
+
font-weight: bold;
|
50 |
+
color: #cc0000;
|
51 |
+
margin: 0;
|
52 |
+
}
|
53 |
+
.attention span {
|
54 |
+
color: blue;
|
55 |
+
}
|
56 |
+
.attention-left {
|
57 |
+
margin-right: 10px;
|
58 |
+
}
|
59 |
+
.attention-right {
|
60 |
+
margin-left: auto;
|
61 |
+
}
|
62 |
+
.live {
|
63 |
+
animation: pulsate 1s infinite;
|
64 |
+
color: red;
|
65 |
+
font-weight: bold;
|
66 |
+
}
|
67 |
+
.chatbot-icon, .voice-icon {
|
68 |
+
position: fixed;
|
69 |
+
bottom: 30px;
|
70 |
+
background-color: #AC3B61;
|
71 |
+
color: #fff;
|
72 |
+
border-radius: 50%;
|
73 |
+
width: 70px;
|
74 |
+
height: 70px;
|
75 |
+
display: flex;
|
76 |
+
align-items: center;
|
77 |
+
justify-content: center;
|
78 |
+
cursor: pointer;
|
79 |
+
transition: transform 0.3s;
|
80 |
+
font-size: 24px;
|
81 |
+
box-shadow: 0 4px 8px rgba(0,0,0,0.2);
|
82 |
+
}
|
83 |
+
.chatbot-icon {
|
84 |
+
right: 30px;
|
85 |
+
}
|
86 |
+
.voice-icon {
|
87 |
+
right: 110px;
|
88 |
+
}
|
89 |
+
.voice-active {
|
90 |
+
animation: pulse 1s infinite;
|
91 |
+
}
|
92 |
+
@keyframes pulse {
|
93 |
+
0% { transform: scale(1); }
|
94 |
+
50% { transform: scale(1.1); }
|
95 |
+
100% { transform: scale(1); }
|
96 |
+
}
|
97 |
+
.chatbox {
|
98 |
+
position: fixed;
|
99 |
+
bottom: 120px;
|
100 |
+
right: 30px;
|
101 |
+
width: 400px;
|
102 |
+
max-width: 90%;
|
103 |
+
height: 600px;
|
104 |
+
max-height: 80vh;
|
105 |
+
background: #fff;
|
106 |
+
box-shadow: 0 5px 15px rgba(0,0,0,0.2);
|
107 |
+
border-radius: 20px;
|
108 |
+
display: none;
|
109 |
+
flex-direction: column;
|
110 |
+
overflow: hidden;
|
111 |
+
}
|
112 |
+
.chatbox-header {
|
113 |
+
padding: 15px;
|
114 |
+
font-size: 20px;
|
115 |
+
background: linear-gradient(45deg, #AC3B61, #8E2D4E);
|
116 |
+
color: white;
|
117 |
+
border-top-left-radius: 20px;
|
118 |
+
border-top-right-radius: 20px;
|
119 |
+
}
|
120 |
+
.chatbox-body {
|
121 |
+
height: calc(100% - 130px);
|
122 |
+
padding: 20px;
|
123 |
+
overflow-y: auto;
|
124 |
+
background-color: #f7f7f7;
|
125 |
+
}
|
126 |
+
.chatbox-footer {
|
127 |
+
padding: 15px;
|
128 |
+
background-color: white;
|
129 |
+
border-bottom-left-radius: 20px;
|
130 |
+
border-bottom-right-radius: 20px;
|
131 |
+
display: flex;
|
132 |
+
align-items: center;
|
133 |
+
}
|
134 |
+
.chatbox-footer input {
|
135 |
+
flex: 1;
|
136 |
+
padding: 12px;
|
137 |
+
border: 1px solid #ddd;
|
138 |
+
border-radius: 25px;
|
139 |
+
font-size: 16px;
|
140 |
+
margin-right: 10px;
|
141 |
+
}
|
142 |
+
.chatbox-footer button {
|
143 |
+
padding: 12px 20px;
|
144 |
+
background: linear-gradient(45deg, #AC3B61, #8E2D4E);
|
145 |
+
color: white;
|
146 |
+
border: none;
|
147 |
+
border-radius: 25px;
|
148 |
+
font-size: 16px;
|
149 |
+
cursor: pointer;
|
150 |
+
transition: background 0.3s ease;
|
151 |
+
}
|
152 |
+
.chatbox-footer button:hover {
|
153 |
+
background: linear-gradient(45deg, #8E2D4E, #AC3B61);
|
154 |
+
}
|
155 |
+
.message {
|
156 |
+
margin-bottom: 12px;
|
157 |
+
padding: 8px 12px;
|
158 |
+
border-radius: 16px;
|
159 |
+
max-width: 80%;
|
160 |
+
word-wrap: break-word;
|
161 |
+
animation: fadeIn 0.3s ease;
|
162 |
+
font-size: 14px; /* Reduced font size for chat messages */
|
163 |
+
}
|
164 |
+
|
165 |
+
.user-message {
|
166 |
+
background-color: #E1F5FE;
|
167 |
+
color: #0277BD;
|
168 |
+
margin-left: auto;
|
169 |
+
}
|
170 |
+
.bot-message {
|
171 |
+
background-color: #FFF3E0;
|
172 |
+
color: #E65100;
|
173 |
+
}
|
174 |
+
@keyframes fadeIn {
|
175 |
+
from { opacity: 0; transform: translateY(10px); }
|
176 |
+
to { opacity: 1; transform: translateY(0); }
|
177 |
+
}
|
178 |
+
.typing-indicator {
|
179 |
+
display: inline-block;
|
180 |
+
}
|
181 |
+
.typing-indicator span {
|
182 |
+
display: inline-block;
|
183 |
+
animation: blink 1.4s infinite both;
|
184 |
+
}
|
185 |
+
.typing-indicator span:nth-child(2) {
|
186 |
+
animation-delay: .2s;
|
187 |
+
}
|
188 |
+
.typing-indicator span:nth-child(3) {
|
189 |
+
animation-delay: .4s;
|
190 |
+
}
|
191 |
+
</style>
|
192 |
+
</head>
|
193 |
+
<body>
|
194 |
+
<div class="body">
|
195 |
+
<div class="container">
|
196 |
+
<div class="row">
|
197 |
+
<div class="col-md-12 text-center">
|
198 |
+
<h1 class="animate-charcter">Farm Tech System-Home</h1>
|
199 |
+
</div>
|
200 |
+
</div>
|
201 |
+
</div>
|
202 |
+
<header>
|
203 |
+
<nav class="navbar">
|
204 |
+
<ul class="nav-links">
|
205 |
+
<li><a href="sensors"><i class="fas fa-home"></i> Sensors</a></li>
|
206 |
+
<li><a href="zones"><i class="fas fa-cogs"></i> Zones</a></li>
|
207 |
+
<li><a href="activity-log"><i class="fas fa-envelope"></i> Activity Log</a></li>
|
208 |
+
<li><a href="notification"><i class="fas fa-bell"></i> Notifications</a></li>
|
209 |
+
</ul>
|
210 |
+
</nav>
|
211 |
+
</header>
|
212 |
+
<main>
|
213 |
+
<h1 style="text-align: center; color: white;">Test your crop health!!!</h1>
|
214 |
+
|
215 |
+
<p style="font-size: 20px; text-align: center; color: white;">
|
216 |
+
Temperature: 32°C, Humidity: 95%, Moisture: High (<span class="live">live</span>)
|
217 |
+
</p>
|
218 |
+
|
219 |
+
<div class="container">
|
220 |
+
<div class="attention attention-left">
|
221 |
+
<p>
|
222 |
+
Attention: This weather condition may lead to outbreak of <span>Tea mosquito bug</span> (Action Needed)
|
223 |
+
</p>
|
224 |
+
</div>
|
225 |
+
<div class="attention attention-right">
|
226 |
+
<p>
|
227 |
+
Attention: This weather condition may lead to outbreak of <span>Blister blight disease</span> (Action Needed)
|
228 |
+
</p>
|
229 |
+
</div>
|
230 |
+
</div>
|
231 |
+
|
232 |
+
<div class="container">
|
233 |
+
<div class="column">
|
234 |
+
<h2>Tea Crop Pest Detection</h2>
|
235 |
+
<form method="post" enctype="multipart/form-data">
|
236 |
+
<input type="file" name="pest_file" accept="image/*" required>
|
237 |
+
<br><br>
|
238 |
+
<input type="submit" value="Upload">
|
239 |
+
</form>
|
240 |
+
{% if pest_filename %}
|
241 |
+
<h3>Uploaded Photo:</h3>
|
242 |
+
<img src="{{ url_for('uploaded_file', filename=pest_filename) }}" alt="Uploaded Photo" style="max-width: 100%; height: auto;">
|
243 |
+
<h3>Detected Pest: <span>Tea mosquito bug</span></h3>
|
244 |
+
<p>Remedy:</p>
|
245 |
+
<ul>
|
246 |
+
<li>Spray neem oil on the affected areas.</li>
|
247 |
+
<li>Use yellow sticky traps to catch the bugs.</li>
|
248 |
+
<li>Plant trap crops like castor or sunflower to divert them away from tea plants.</li>
|
249 |
+
</ul>
|
250 |
+
<audio id="pest_audio" src="{{ url_for('audio_file', filename=pest_audio_file) }}" controls autoplay></audio>
|
251 |
+
{% endif %}
|
252 |
+
</div>
|
253 |
+
<div class="column">
|
254 |
+
<h2>Tea Crop Disease Detection</h2>
|
255 |
+
<form method="post" enctype="multipart/form-data">
|
256 |
+
<input type="file" name="disease_file" accept="image/*" required>
|
257 |
+
<br><br>
|
258 |
+
<input type="submit" value="Upload">
|
259 |
+
</form>
|
260 |
+
{% if disease_filename %}
|
261 |
+
<h3>Uploaded Photo:</h3>
|
262 |
+
<img src="{{ url_for('uploaded_file', filename=disease_filename) }}" alt="Uploaded Photo" style="max-width: 100%; height: auto;">
|
263 |
+
<h3>Detected Disease: <span>Brown Blight disease</span></h3>
|
264 |
+
<p>Remedy:</p>
|
265 |
+
<ul>
|
266 |
+
<li>Remove and destroy infected leaves.</li>
|
267 |
+
<li>Apply copper-based fungicides.</li>
|
268 |
+
<li>Ensure proper air circulation around the plants.</li>
|
269 |
+
</ul>
|
270 |
+
<audio id="disease_audio" src="{{ url_for('audio_file', filename=disease_audio_file) }}" controls autoplay></audio>
|
271 |
+
{% endif %}
|
272 |
+
</div>
|
273 |
+
</div>
|
274 |
+
</main>
|
275 |
+
</div>
|
276 |
+
|
277 |
+
<!-- Chatbot Icon -->
|
278 |
+
<div class="chatbot-icon" id="chatbotIcon">
|
279 |
+
<i class="fas fa-comments"></i>
|
280 |
+
</div>
|
281 |
+
|
282 |
+
<!-- Voice Icon -->
|
283 |
+
<div class="voice-icon" id="voiceIcon">
|
284 |
+
<i class="fas fa-microphone"></i>
|
285 |
+
</div>
|
286 |
+
|
287 |
+
<!-- Chatbox -->
|
288 |
+
<div class="chatbox" id="chatbox">
|
289 |
+
<div class="chatbox-header">Chat with AI</div>
|
290 |
+
<div class="chatbox-body" id="chatBody">
|
291 |
+
<!-- Chat content goes here -->
|
292 |
+
</div>
|
293 |
+
<div class="chatbox-footer">
|
294 |
+
<input type="text" placeholder="Type your message here..." id="chatInput">
|
295 |
+
<button id="sendButton">Send</button>
|
296 |
+
</div>
|
297 |
+
</div>
|
298 |
+
|
299 |
+
<script>
|
300 |
+
// JavaScript to handle the chatbot toggle
|
301 |
+
document.getElementById('chatbotIcon').addEventListener('click', function() {
|
302 |
+
var chatbox = document.getElementById('chatbox');
|
303 |
+
if (chatbox.style.display === 'none' || chatbox.style.display === '') {
|
304 |
+
chatbox.style.display = 'flex';
|
305 |
+
} else {
|
306 |
+
chatbox.style.display = 'none';
|
307 |
+
}
|
308 |
+
});
|
309 |
+
|
310 |
+
// JavaScript for voice recognition
|
311 |
+
var recognition;
|
312 |
+
if ('webkitSpeechRecognition' in window) {
|
313 |
+
recognition = new webkitSpeechRecognition();
|
314 |
+
} else if ('SpeechRecognition' in window) {
|
315 |
+
recognition = new SpeechRecognition();
|
316 |
+
} else {
|
317 |
+
alert('Your browser does not support speech recognition.');
|
318 |
+
}
|
319 |
+
|
320 |
+
if (recognition) {
|
321 |
+
recognition.continuous = false;
|
322 |
+
recognition.interimResults = false;
|
323 |
+
|
324 |
+
recognition.onstart = function() {
|
325 |
+
document.getElementById('voiceIcon').classList.add('voice-active');
|
326 |
+
};
|
327 |
+
|
328 |
+
recognition.onend = function() {
|
329 |
+
document.getElementById('voiceIcon').classList.remove('voice-active');
|
330 |
+
};
|
331 |
+
|
332 |
+
recognition.onresult = function(event) {
|
333 |
+
var transcript = event.results[0][0].transcript;
|
334 |
+
document.getElementById('chatInput').value = transcript;
|
335 |
+
};
|
336 |
+
|
337 |
+
document.getElementById('voiceIcon').addEventListener('click', function() {
|
338 |
+
recognition.start();
|
339 |
+
});
|
340 |
+
}
|
341 |
+
|
342 |
+
// Chat functionality
|
343 |
+
$(document).ready(function() {
|
344 |
+
$('#sendButton').click(sendMessage);
|
345 |
+
$('#chatInput').keypress(function(e) {
|
346 |
+
if (e.which == 13) {
|
347 |
+
sendMessage();
|
348 |
+
}
|
349 |
+
});
|
350 |
+
|
351 |
+
function sendMessage() {
|
352 |
+
var message = $('#chatInput').val();
|
353 |
+
if (message.trim() !== '') {
|
354 |
+
appendMessage('user', message);
|
355 |
+
$('#chatInput').val('');
|
356 |
+
|
357 |
+
// Show a typing indicator
|
358 |
+
appendMessage('bot', '<div class="typing-indicator">Typing<span>.</span><span>.</span><span>.</span></div>');
|
359 |
+
|
360 |
+
$.ajax({
|
361 |
+
url: '/chat',
|
362 |
+
method: 'POST',
|
363 |
+
contentType: 'application/json',
|
364 |
+
data: JSON.stringify({message: message}),
|
365 |
+
success: function(response) {
|
366 |
+
// Remove the typing indicator
|
367 |
+
$('.typing-indicator').parent().remove();
|
368 |
+
appendMessage('bot', response.response);
|
369 |
+
},
|
370 |
+
error: function() {
|
371 |
+
// Remove the typing indicator
|
372 |
+
$('.typing-indicator').parent().remove();
|
373 |
+
appendMessage('bot', 'Sorry, there was an error processing your request.');
|
374 |
+
}
|
375 |
+
});
|
376 |
+
}
|
377 |
+
}
|
378 |
+
|
379 |
+
function appendMessage(sender, message) {
|
380 |
+
var messageClass = sender === 'user' ? 'user-message' : 'bot-message';
|
381 |
+
$('#chatBody').append('<div class="message ' + messageClass + '">' + message + '</div>');
|
382 |
+
$('#chatBody').scrollTop($('#chatBody')[0].scrollHeight);
|
383 |
+
}
|
384 |
+
});
|
385 |
+
</script>
|
386 |
+
</body>
|
387 |
+
</html>
|
templates/notification.html
ADDED
The diff for this file is too large to render.
See raw diff
|
|
templates/sensors.html
ADDED
@@ -0,0 +1,159 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html lang="en">
|
3 |
+
<head>
|
4 |
+
<meta charset="UTF-8">
|
5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6 |
+
<title>Farm Tech System - Sensors</title>
|
7 |
+
<link href="https://fonts.googleapis.com/css2?family=Merriweather:wght@700&family=Open+Sans&display=swap" rel="stylesheet">
|
8 |
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
|
9 |
+
<style>
|
10 |
+
:root {
|
11 |
+
--dark-green: #2C5F2D;
|
12 |
+
--light-green: #97BC62;
|
13 |
+
--brown: #6A4028;
|
14 |
+
--cream: #F2E8CF;
|
15 |
+
}
|
16 |
+
|
17 |
+
body {
|
18 |
+
font-family: 'Open Sans', sans-serif;
|
19 |
+
background-color: var(--cream);
|
20 |
+
color: var(--brown);
|
21 |
+
margin: 0;
|
22 |
+
padding: 0;
|
23 |
+
}
|
24 |
+
|
25 |
+
.navbar {
|
26 |
+
background-color: var(--dark-green);
|
27 |
+
padding: 1rem;
|
28 |
+
position: fixed;
|
29 |
+
width: 100%;
|
30 |
+
top: 0;
|
31 |
+
z-index: 1000;
|
32 |
+
}
|
33 |
+
|
34 |
+
.nav-links {
|
35 |
+
list-style: none;
|
36 |
+
display: flex;
|
37 |
+
justify-content: center;
|
38 |
+
margin: 0;
|
39 |
+
padding: 0;
|
40 |
+
}
|
41 |
+
|
42 |
+
.nav-links li {
|
43 |
+
margin: 0 15px;
|
44 |
+
}
|
45 |
+
|
46 |
+
.nav-links a {
|
47 |
+
color: var(--cream);
|
48 |
+
text-decoration: none;
|
49 |
+
font-weight: bold;
|
50 |
+
transition: color 0.3s ease;
|
51 |
+
}
|
52 |
+
|
53 |
+
.nav-links a:hover {
|
54 |
+
color: var(--light-green);
|
55 |
+
}
|
56 |
+
|
57 |
+
.container {
|
58 |
+
max-width: 1200px;
|
59 |
+
margin: 80px auto 0;
|
60 |
+
padding: 2rem;
|
61 |
+
}
|
62 |
+
|
63 |
+
h1, h2, h3 {
|
64 |
+
font-family: 'Merriweather', serif;
|
65 |
+
color: var(--dark-green);
|
66 |
+
}
|
67 |
+
|
68 |
+
.sensor-grid {
|
69 |
+
display: grid;
|
70 |
+
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
71 |
+
gap: 2rem;
|
72 |
+
margin-top: 2rem;
|
73 |
+
}
|
74 |
+
|
75 |
+
.sensor-card {
|
76 |
+
background-color: white;
|
77 |
+
border-radius: 8px;
|
78 |
+
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
79 |
+
padding: 1.5rem;
|
80 |
+
text-align: center;
|
81 |
+
transition: transform 0.3s ease;
|
82 |
+
}
|
83 |
+
|
84 |
+
.sensor-card:hover {
|
85 |
+
transform: translateY(-5px);
|
86 |
+
}
|
87 |
+
|
88 |
+
.sensor-icon {
|
89 |
+
font-size: 3rem;
|
90 |
+
color: var(--dark-green);
|
91 |
+
margin-bottom: 1rem;
|
92 |
+
}
|
93 |
+
|
94 |
+
.sensor-name {
|
95 |
+
font-weight: bold;
|
96 |
+
margin-bottom: 0.5rem;
|
97 |
+
}
|
98 |
+
|
99 |
+
.sensor-data {
|
100 |
+
font-size: 1.2rem;
|
101 |
+
color: var(--brown);
|
102 |
+
}
|
103 |
+
|
104 |
+
.timestamp {
|
105 |
+
text-align: center;
|
106 |
+
margin-top: 2rem;
|
107 |
+
font-style: italic;
|
108 |
+
color: var(--brown);
|
109 |
+
}
|
110 |
+
</style>
|
111 |
+
</head>
|
112 |
+
<body>
|
113 |
+
<!-- Navigation menu -->
|
114 |
+
<nav class="navbar">
|
115 |
+
<ul class="nav-links">
|
116 |
+
<li><a href="{{ url_for('home') }}"><i class="fas fa-home"></i> Dashboard</a></li>
|
117 |
+
<li><a href="{{ url_for('zones') }}"><i class="fas fa-cogs"></i> Zones</a></li>
|
118 |
+
<li><a href="{{ url_for('activity_log') }}"><i class="fas fa-envelope"></i> Activity Log</a></li>
|
119 |
+
</ul>
|
120 |
+
</nav>
|
121 |
+
|
122 |
+
<div class="container">
|
123 |
+
<h1>Farm Tech System - Sensors</h1>
|
124 |
+
|
125 |
+
<div class="sensor-grid">
|
126 |
+
<div class="sensor-card">
|
127 |
+
<i class="fas fa-wave-square sensor-icon"></i>
|
128 |
+
<p class="sensor-name">Ultrasonic Transducer</p>
|
129 |
+
<p class="sensor-data">Distance: {{ sensor_data.distance }} cm</p>
|
130 |
+
</div>
|
131 |
+
<div class="sensor-card">
|
132 |
+
<i class="fas fa-bug sensor-icon"></i>
|
133 |
+
<p class="sensor-name">IR Sensor</p>
|
134 |
+
<p class="sensor-data">Pest Swarm: {{ 'Detected' if sensor_data.irValue == 0 else 'Not Detected' }}</p>
|
135 |
+
</div>
|
136 |
+
<div class="sensor-card">
|
137 |
+
<i class="fas fa-thermometer-half sensor-icon"></i>
|
138 |
+
<p class="sensor-name">Environmental Sensor</p>
|
139 |
+
<p class="sensor-data">Temperature: {{ sensor_data.temperature }} ℃</p>
|
140 |
+
<p class="sensor-data">Humidity: {{ sensor_data.humidity }}%</p>
|
141 |
+
</div>
|
142 |
+
<div class="sensor-card">
|
143 |
+
<i class="fas fa-running sensor-icon"></i>
|
144 |
+
<p class="sensor-name">PIR Sensor</p>
|
145 |
+
<p class="sensor-data">Motion: {{ 'Detected' if sensor_data.irValue == 0 else 'Not Detected' }}</p>
|
146 |
+
</div>
|
147 |
+
<div class="sensor-card">
|
148 |
+
<i class="fas fa-lightbulb sensor-icon"></i>
|
149 |
+
<p class="sensor-name">UV Light (Sticky Trap)</p>
|
150 |
+
<p class="sensor-data">Status: Normal</p>
|
151 |
+
</div>
|
152 |
+
</div>
|
153 |
+
|
154 |
+
<div class="timestamp">
|
155 |
+
<p>Last updated: {{ sensor_data.timestamp }}</p>
|
156 |
+
</div>
|
157 |
+
</div>
|
158 |
+
</body>
|
159 |
+
</html>
|
templates/zones.html
ADDED
@@ -0,0 +1,282 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html lang="en">
|
3 |
+
<head>
|
4 |
+
<meta charset="UTF-8">
|
5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6 |
+
<title>Farm Tech System - Zones</title>
|
7 |
+
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
|
8 |
+
<style>
|
9 |
+
/* Added CSS styles */
|
10 |
+
.animate-charcter {
|
11 |
+
text-align: center;
|
12 |
+
display: flex;
|
13 |
+
align-items: center;
|
14 |
+
justify-content: center;
|
15 |
+
background-image: linear-gradient(
|
16 |
+
-225deg,
|
17 |
+
#231557 0%,
|
18 |
+
#44107a 29%,
|
19 |
+
#ff1361 67%,
|
20 |
+
#fff800 100%
|
21 |
+
);
|
22 |
+
background-size: auto auto;
|
23 |
+
background-clip: border-box;
|
24 |
+
background-size: 200% auto;
|
25 |
+
color: #AC3B61;
|
26 |
+
background-clip: text;
|
27 |
+
text-justify: transparent;
|
28 |
+
-webkit-background-clip: text;
|
29 |
+
-webkit-text-fill-color: transparent;
|
30 |
+
animation: textclip 2s linear infinite;
|
31 |
+
display: inline-block;
|
32 |
+
font-size: 80px;
|
33 |
+
font-family: Georgia, 'Times New Roman', Times, serif;
|
34 |
+
font-weight: bold;
|
35 |
+
}
|
36 |
+
|
37 |
+
@keyframes textclip {
|
38 |
+
to {
|
39 |
+
background-position: center;
|
40 |
+
}
|
41 |
+
}
|
42 |
+
|
43 |
+
* {
|
44 |
+
margin-bottom: 20px;
|
45 |
+
padding: 0;
|
46 |
+
box-sizing: border-box;
|
47 |
+
}
|
48 |
+
|
49 |
+
body {
|
50 |
+
align-items: center;
|
51 |
+
justify-content: center;
|
52 |
+
background: url('{{ url_for('static', filename='backgrnd.jpg') }}') no-repeat center center fixed;
|
53 |
+
background-size: cover;
|
54 |
+
color: #fff; /* Ensuring the text is readable on a dark background */
|
55 |
+
}
|
56 |
+
|
57 |
+
@keyframes scroll {
|
58 |
+
0% {
|
59 |
+
transform: translateX(0);
|
60 |
+
}
|
61 |
+
100% {
|
62 |
+
transform: translateX(calc(-250px * 7));
|
63 |
+
}
|
64 |
+
}
|
65 |
+
|
66 |
+
.slider {
|
67 |
+
height: 200px;
|
68 |
+
margin: auto;
|
69 |
+
overflow: hidden;
|
70 |
+
position: relative;
|
71 |
+
width: auto;
|
72 |
+
padding: 0 30px;
|
73 |
+
}
|
74 |
+
|
75 |
+
.logo {
|
76 |
+
font-family: 'Poppins';
|
77 |
+
font-size: 24px;
|
78 |
+
text-align: center;
|
79 |
+
}
|
80 |
+
|
81 |
+
.navbar {
|
82 |
+
margin-top: 20px;
|
83 |
+
}
|
84 |
+
|
85 |
+
.nav-links {
|
86 |
+
list-style: none;
|
87 |
+
padding: 0;
|
88 |
+
display: flex;
|
89 |
+
justify-content: center;
|
90 |
+
}
|
91 |
+
|
92 |
+
.nav-links li {
|
93 |
+
margin: 0 15px;
|
94 |
+
}
|
95 |
+
|
96 |
+
.nav-links a {
|
97 |
+
color: #AC3B61;
|
98 |
+
font-weight: bolder;
|
99 |
+
font-size: larger;
|
100 |
+
text-decoration: none;
|
101 |
+
}
|
102 |
+
|
103 |
+
h2 {
|
104 |
+
font-size: 24px;
|
105 |
+
margin-bottom: 10px;
|
106 |
+
}
|
107 |
+
|
108 |
+
p {
|
109 |
+
line-height: 1.6;
|
110 |
+
}
|
111 |
+
|
112 |
+
.nav-links li:hover a {
|
113 |
+
background: rgb(255, 255, 255);
|
114 |
+
color: black;
|
115 |
+
padding: .25rem .5rem;
|
116 |
+
transition: all ease-in 300ms;
|
117 |
+
border-radius: 25px;
|
118 |
+
}
|
119 |
+
|
120 |
+
.container {
|
121 |
+
display: flex;
|
122 |
+
flex-direction: column;
|
123 |
+
align-items: center;
|
124 |
+
}
|
125 |
+
|
126 |
+
.box {
|
127 |
+
display: flex;
|
128 |
+
justify-content: center;
|
129 |
+
flex-wrap: wrap;
|
130 |
+
}
|
131 |
+
|
132 |
+
.dream {
|
133 |
+
text-align: center;
|
134 |
+
}
|
135 |
+
|
136 |
+
.dream .item {
|
137 |
+
margin: 10px;
|
138 |
+
}
|
139 |
+
|
140 |
+
.dream img {
|
141 |
+
display: block;
|
142 |
+
margin: 0 auto;
|
143 |
+
}
|
144 |
+
|
145 |
+
.dream .item p {
|
146 |
+
font-size: 20px; /* Increased font size */
|
147 |
+
color: red; /* Changed text color to red */
|
148 |
+
margin-top: 10px;
|
149 |
+
}
|
150 |
+
|
151 |
+
#map, #zoneMap {
|
152 |
+
height: 500px;
|
153 |
+
width: 80%;
|
154 |
+
margin: 20px auto;
|
155 |
+
}
|
156 |
+
|
157 |
+
</style>
|
158 |
+
</head>
|
159 |
+
<body>
|
160 |
+
<header>
|
161 |
+
<h1 class="animate-charcter">Farm Tech System - Zones</h1>
|
162 |
+
<!-- Navigation menu -->
|
163 |
+
<nav class="navbar">
|
164 |
+
<ul class="nav-links">
|
165 |
+
<li><a href="home"><i class="fas fa-home"></i> Home</a></li>
|
166 |
+
<li><a href="sensors"><i class="fas fa-sensors"></i> Sensors</a></li>
|
167 |
+
<li><a href="activity-log"><i class="fas fa-envelope"></i> Activity Log</a></li>
|
168 |
+
|
169 |
+
</ul>
|
170 |
+
</nav>
|
171 |
+
</header>
|
172 |
+
|
173 |
+
<!-- Zones content -->
|
174 |
+
<section>
|
175 |
+
<div id="map"></div>
|
176 |
+
<div id="zoneMap"></div>
|
177 |
+
</section>
|
178 |
+
|
179 |
+
<!-- Footer -->
|
180 |
+
<footer>
|
181 |
+
<!-- Footer content -->
|
182 |
+
</footer>
|
183 |
+
|
184 |
+
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
|
185 |
+
<script src="https://unpkg.com/leaflet.heat/dist/leaflet-heat.js"></script>
|
186 |
+
<script>
|
187 |
+
var map = L.map('map').setView([10.3269, 76.9512], 16); // Increased zoom level for closer view
|
188 |
+
|
189 |
+
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
190 |
+
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
191 |
+
}).addTo(map);
|
192 |
+
|
193 |
+
// Add a marker for the tea estate
|
194 |
+
L.marker([10.3269, 76.9512]).addTo(map)
|
195 |
+
.bindPopup('Tea Estate in Valparai Hills')
|
196 |
+
.openPopup();
|
197 |
+
|
198 |
+
// Define the coordinates of the boundary of the tea estate
|
199 |
+
var estateBoundary = [
|
200 |
+
[10.3275, 76.9500],
|
201 |
+
[10.3272, 76.9510],
|
202 |
+
[10.3270, 76.9520],
|
203 |
+
[10.3268, 76.9525],
|
204 |
+
[10.3265, 76.9527],
|
205 |
+
[10.3260, 76.9525],
|
206 |
+
[10.3255, 76.9520],
|
207 |
+
[10.3252, 76.9515],
|
208 |
+
[10.3250, 76.9510],
|
209 |
+
[10.3252, 76.9505],
|
210 |
+
[10.3255, 76.9500],
|
211 |
+
[10.3260, 76.9495],
|
212 |
+
[10.3265, 76.9492],
|
213 |
+
[10.3270, 76.9495]
|
214 |
+
];
|
215 |
+
|
216 |
+
// Add the boundary as a polygon
|
217 |
+
L.polygon(estateBoundary, {color: 'red'}).addTo(map)
|
218 |
+
.bindPopup('Tea Estate Boundary');
|
219 |
+
|
220 |
+
// Add a heatmap layer
|
221 |
+
var heat = L.heatLayer([
|
222 |
+
[10.3269, 76.9512, 0.5], // Example coordinates with intensity
|
223 |
+
[10.3270, 76.9520, 0.6],
|
224 |
+
[10.3280, 76.9530, 0.7]
|
225 |
+
], {radius: 25}).addTo(map);
|
226 |
+
|
227 |
+
// Additional map for zones
|
228 |
+
var zoneMap = L.map('zoneMap').setView([10.3269, 76.9512], 16);
|
229 |
+
|
230 |
+
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
231 |
+
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
232 |
+
}).addTo(zoneMap);
|
233 |
+
|
234 |
+
// Define coordinates for zone boundaries
|
235 |
+
var zone1 = [
|
236 |
+
[10.3280, 76.9500],
|
237 |
+
[10.3280, 76.9515],
|
238 |
+
[10.3270, 76.9515],
|
239 |
+
[10.3270, 76.9500]
|
240 |
+
];
|
241 |
+
|
242 |
+
var zone2 = [
|
243 |
+
[10.3280, 76.9515],
|
244 |
+
[10.3280, 76.9530],
|
245 |
+
[10.3270, 76.9530],
|
246 |
+
[10.3270, 76.9515]
|
247 |
+
];
|
248 |
+
|
249 |
+
var zone3 = [
|
250 |
+
[10.3270, 76.9500],
|
251 |
+
[10.3270, 76.9515],
|
252 |
+
[10.3260, 76.9515],
|
253 |
+
[10.3260, 76.9500]
|
254 |
+
];
|
255 |
+
|
256 |
+
var zone4 = [
|
257 |
+
[10.3270, 76.9515],
|
258 |
+
[10.3270, 76.9530],
|
259 |
+
[10.3260, 76.9530],
|
260 |
+
[10.3260, 76.9515]
|
261 |
+
];
|
262 |
+
|
263 |
+
// Add zones as polygons
|
264 |
+
L.polygon(zone1, {color: 'blue'}).addTo(zoneMap).bindPopup('Zone 1');
|
265 |
+
L.polygon(zone2, {color: 'green'}).addTo(zoneMap).bindPopup('Zone 2');
|
266 |
+
L.polygon(zone3, {color: 'yellow'}).addTo(zoneMap).bindPopup('Zone 3');
|
267 |
+
L.polygon(zone4, {color: 'orange'}).addTo(zoneMap).bindPopup('Zone 4');
|
268 |
+
|
269 |
+
// Add heatmap layers for zones
|
270 |
+
var zoneHeatData = [
|
271 |
+
// Example heat data for each zone
|
272 |
+
[10.3275, 76.9505, 0.5], // Zone 1
|
273 |
+
[10.3275, 76.9525, 0.6], // Zone 2
|
274 |
+
[10.3265, 76.9505, 0.7], // Zone 3
|
275 |
+
[10.3265, 76.9525, 0.8] // Zone 4
|
276 |
+
];
|
277 |
+
|
278 |
+
L.heatLayer(zoneHeatData, {radius: 25}).addTo(zoneMap);
|
279 |
+
|
280 |
+
</script>
|
281 |
+
</body>
|
282 |
+
</html>
|
uploads/brown_blight.jpg
ADDED
![]() |
uploads/img2.jpg
ADDED
![]() |
uploads/tea_mosquito.jpg
ADDED
![]() |
uploads/ultrasonic02.png
ADDED
![]() |
uploads/uv.jpg
ADDED
![]() |