chandra7799 commited on
Commit
0605829
·
verified ·
1 Parent(s): f849d19

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +81 -121
app.py CHANGED
@@ -8,12 +8,6 @@ from datetime import datetime
8
  import shutil
9
  import base64
10
  import pytz
11
- import logging
12
- import tempfile
13
-
14
- # Set up logging
15
- logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
16
- logger = logging.getLogger(__name__)
17
 
18
  # Load environment variables
19
  load_dotenv()
@@ -22,8 +16,7 @@ SF_PASSWORD = os.getenv("SF_PASSWORD")
22
  SF_SECURITY_TOKEN = os.getenv("SF_SECURITY_TOKEN")
23
 
24
  if not all([SF_USERNAME, SF_PASSWORD, SF_SECURITY_TOKEN]):
25
- logger.error("Missing Salesforce credentials.")
26
- raise ValueError("Missing Salesforce credentials in .env file.")
27
 
28
  # Connect to Salesforce
29
  try:
@@ -33,165 +26,132 @@ try:
33
  security_token=SF_SECURITY_TOKEN,
34
  domain='login'
35
  )
36
- logger.info("Successfully connected to Salesforce.")
37
  except Exception as e:
38
- logger.error(f"Salesforce connection failed: {str(e)}")
39
  raise
40
 
41
  VALID_MILESTONES = ["Planning", "Foundation", "Walls Erected", "Completed"]
42
- MILESTONE_COMPLETION_MAP = {
43
- "Planning": 25,
44
- "Foundation": 50,
45
- "Walls Erected": 75,
46
- "Completed": 100
47
- }
48
- LOCAL_TIMEZONE = pytz.timezone("Asia/Kolkata")
49
- ALLOWED_EXTENSIONS = {'.jpg', '.jpeg', '.png'}
50
- MAX_FILE_SIZE_MB = 20
51
 
52
  # Milestone detection based on image brightness
53
  def detect_milestone_from_image(image_path):
54
- try:
55
- img = Image.open(image_path).convert("L")
56
- img_array = np.array(img)
57
- brightness = np.mean(img_array)
58
- logger.debug(f"Image {image_path} brightness: {brightness}")
59
-
60
- if brightness < 80:
61
- return "Planning"
62
- elif 80 <= brightness < 130:
63
- return "Foundation"
64
- elif 130 <= brightness < 180:
65
- return "Walls Erected"
66
- else:
67
- return "Completed"
68
- except Exception as e:
69
- logger.error(f"Failed to detect milestone for {image_path}: {str(e)}")
70
- return "Planning" # Default milestone on error
71
 
72
  def process_image(images, project_name):
73
  try:
74
- if not project_name or not project_name.strip():
75
- return "Error: Project name is required.", "Failure", "", "", "0%"
76
-
77
  if not images or len(images) == 0:
78
- return "Error: Please upload at least one image.", "Failure", "", "", "0%"
79
 
 
80
  milestones = []
81
- file_urls = []
82
- with tempfile.TemporaryDirectory() as temp_dir:
83
- for image in images:
84
- # Validate file extension
85
- ext = os.path.splitext(image.name)[1].lower()
86
- if ext not in ALLOWED_EXTENSIONS:
87
- return f"Error: {os.path.basename(image.name)} is not a supported format (JPG/PNG only).", "Failure", "", "", "0%"
88
-
89
- # Validate file size
90
- image_size_mb = os.path.getsize(image.name) / (1024 * 1024)
91
- if image_size_mb > MAX_FILE_SIZE_MB:
92
- return f"Error: {os.path.basename(image.name)} exceeds {MAX_FILE_SIZE_MB}MB.", "Failure", "", "", "0%"
93
-
94
- # Save image to temporary directory
95
- unique_id = datetime.now().strftime("%Y%m%d%H%M%S")
96
- image_filename = f"{unique_id}_{os.path.basename(image.name)}"
97
- temp_image_path = os.path.join(temp_dir, image_filename)
98
- shutil.copy(image.name, temp_image_path)
99
-
100
- # Upload to Salesforce
101
- with open(temp_image_path, 'rb') as image_file:
102
- image_data = base64.b64encode(image_file.read()).decode('utf-8')
103
-
104
  content_version = {
105
  'Title': image_filename,
106
- 'PathOnClient': image_filename,
107
  'VersionData': image_data
108
  }
109
- try:
110
- content_version_result = sf.ContentVersion.create(content_version)
111
- content_version_id = content_version_result['id']
112
- file_url = f"https://sathkruthatechsolutionspri8-dev-ed.develop.lightning.force.com/{content_version_id}"
113
- file_urls.append(file_url)
114
- logger.info(f"Uploaded {image_filename} to Salesforce: {file_url}")
115
- except Exception as e:
116
- logger.error(f"Failed to upload {image_filename} to Salesforce: {str(e)}")
117
- return f"Error: Failed to upload {image_filename} to Salesforce.", "Failure", "", "", "0%"
118
-
119
- # Detect milestone
120
- milestone = detect_milestone_from_image(temp_image_path)
121
- milestones.append(milestone)
122
-
123
- # Determine final milestone
124
  final_milestone = max(set(milestones), key=milestones.count) if milestones else "Planning"
125
- percent_complete = MILESTONE_COMPLETION_MAP.get(final_milestone, 0)
 
 
 
 
 
 
126
 
127
- # Get current time in local timezone
128
- now = datetime.now(LOCAL_TIMEZONE)
129
- local_time = now.strftime("%Y-%m-%dT%H:%M:%S%z")[:-2] + ":" + now.strftime("%z")[-2:]
130
 
131
- # Create Salesforce record
132
  record = {
133
- "Name__c": project_name.strip(),
134
  "Current_Milestone__c": final_milestone,
135
  "Completion_Percentage__c": percent_complete,
136
  "Last_Updated_On__c": local_time,
137
  "Upload_Status__c": "Success",
138
- "Comments__c": f"Detected milestone: {final_milestone}",
139
- "Last_Updated_Image__c": file_urls[-1] if file_urls else ""
140
  }
141
 
142
  try:
143
  sf.Construction__c.create(record)
144
- logger.info(f"Created Salesforce record for project {project_name}: {final_milestone}")
145
  except Exception as e:
146
- logger.error(f"Failed to create Salesforce record: {str(e)}")
147
- return f"Error: Failed to update Salesforce record.", "Failure", "", "", "0%"
148
 
 
149
  return (
150
  f"<h3 style='color:green;'>Milestone: {final_milestone}</h3>",
151
  "Success",
152
  final_milestone,
153
- f"{percent_complete}%",
154
- file_urls[-1] if file_urls else ""
155
  )
156
 
157
  except Exception as e:
158
- logger.error(f"Unexpected error in process_image: {str(e)}")
159
- return f"Error: An unexpected error occurred - {str(e)}", "Failure", "", "", "0%"
160
 
161
  # Gradio UI
162
- with gr.Blocks(theme=gr.themes.Soft(), css=".title {text-align: center; font-size: 2em; margin-bottom: 20px;}") as demo:
163
  gr.Markdown("<h1 class='title'>Construction Progress Analyzer</h1>")
164
  with gr.Row():
165
- with gr.Column(scale=2):
166
- image_input = gr.Files(
167
- file_types=[".jpg", ".jpeg", ".png"],
168
- label=f"Upload Construction Site Photos (JPG/PNG, ≤ {MAX_FILE_SIZE_MB}MB)",
169
- file_count="multiple"
170
- )
171
- with gr.Column(scale=1):
172
- project_name_input = gr.Textbox(
173
- label="Project Name (Required)",
174
- placeholder="e.g., Highrise_001",
175
- lines=1
176
- )
177
-
178
- submit_button = gr.Button("Process Images", variant="primary")
179
  output_html = gr.HTML(label="Result")
180
- with gr.Row():
181
- upload_status = gr.Textbox(label="Upload Status", interactive=False)
182
- milestone = gr.Textbox(label="Detected Milestone", interactive=False)
183
- progress = gr.Textbox(label="Completion Percentage", interactive=False)
184
- file_url = gr.Textbox(label="Last Image URL", interactive=False, visible=False)
185
 
186
  submit_button.click(
187
  fn=process_image,
188
  inputs=[image_input, project_name_input],
189
- outputs=[output_html, upload_status, milestone, progress, file_url]
190
  )
191
 
192
- # Launch Gradio app
193
- try:
194
- demo.launch(share=False, server_name="0.0.0.0", server_port=7860)
195
- except Exception as e:
196
- logger.error(f"Failed to launch Gradio app: {str(e)}")
197
- raise
 
8
  import shutil
9
  import base64
10
  import pytz
 
 
 
 
 
 
11
 
12
  # Load environment variables
13
  load_dotenv()
 
16
  SF_SECURITY_TOKEN = os.getenv("SF_SECURITY_TOKEN")
17
 
18
  if not all([SF_USERNAME, SF_PASSWORD, SF_SECURITY_TOKEN]):
19
+ raise ValueError("Missing Salesforce credentials.")
 
20
 
21
  # Connect to Salesforce
22
  try:
 
26
  security_token=SF_SECURITY_TOKEN,
27
  domain='login'
28
  )
 
29
  except Exception as e:
30
+ print(f"Salesforce connection failed: {str(e)}")
31
  raise
32
 
33
  VALID_MILESTONES = ["Planning", "Foundation", "Walls Erected", "Completed"]
34
+ local_timezone = pytz.timezone("Asia/Kolkata")
 
 
 
 
 
 
 
 
35
 
36
  # Milestone detection based on image brightness
37
  def detect_milestone_from_image(image_path):
38
+ img = Image.open(image_path).convert("L")
39
+ img_array = np.array(img)
40
+ brightness = np.mean(img_array)
41
+
42
+ if brightness < 80:
43
+ return "Planning"
44
+ elif 80 <= brightness < 130:
45
+ return "Foundation"
46
+ elif 130 <= brightness < 180:
47
+ return "Walls Erected"
48
+ else:
49
+ return "Completed"
 
 
 
 
 
50
 
51
  def process_image(images, project_name):
52
  try:
53
+ # Validates that at least one image is provided
 
 
54
  if not images or len(images) == 0:
55
+ return "Error: Please upload at least one image to proceed.", "Pending", "", "", 0
56
 
57
+ # List to store milestones for all images
58
  milestones = []
59
+ for image in images:
60
+ img = Image.open(image)
61
+
62
+ # Check file size and format
63
+ image_size_mb = os.path.getsize(image) / (1024 * 1024)
64
+ if image_size_mb > 20:
65
+ return "Error: One or more images exceed 20MB.", "Failure", "", "", 0
66
+ if not str(image).lower().endswith(('.jpg', '.jpeg', '.png')):
67
+ return "Error: Only JPG/PNG images are supported.", "Failure", "", "", 0
68
+
69
+ # Save image locally with unique filename
70
+ upload_dir = "public_Uploads"
71
+ os.makedirs(upload_dir, exist_ok=True)
72
+ unique_id = datetime.now().strftime("%Y%m%d%H%M%S")
73
+ image_filename = f"{unique_id}_{os.path.basename(image)}"
74
+ saved_image_path = os.path.join(upload_dir, image_filename)
75
+ shutil.copy(image, saved_image_path)
76
+
77
+ # Upload image to Salesforce
78
+ with open(saved_image_path, 'rb') as image_file:
79
+ image_data = base64.b64encode(image_file.read()).decode('utf-8')
80
+
81
+ try:
82
  content_version = {
83
  'Title': image_filename,
84
+ 'PathOnClient': saved_image_path,
85
  'VersionData': image_data
86
  }
87
+ content_version_result = sf.ContentVersion.create(content_version)
88
+ content_version_id = content_version_result['id']
89
+ file_url = f"https://sathkruthatechsolutionspri8-dev-ed.develop.lightning.force.com/{content_version_id}"
90
+ except Exception as e:
91
+ return f"Error: Failed to upload image to Salesforce - {str(e)}", "Failure", "", "", 0
92
+
93
+ # Detect milestone for each image and store
94
+ milestone = detect_milestone_from_image(saved_image_path)
95
+ milestones.append(milestone)
96
+
97
+ # Aggregate milestones by selecting the most frequent one
 
 
 
 
98
  final_milestone = max(set(milestones), key=milestones.count) if milestones else "Planning"
99
+ milestone_completion_map = {
100
+ "Planning": 10,
101
+ "Foundation": 30,
102
+ "Walls Erected": 50,
103
+ "Completed": 100,
104
+ }
105
+ percent_complete = milestone_completion_map.get(final_milestone, 0)
106
 
107
+ # Get current time in Asia/Kolkata timezone
108
+ now = datetime.now(local_timezone)
109
+ local_time = now.strftime("%Y-%m-%dT%H:%M:%S") + now.strftime("%z")[:-2] + ":" + now.strftime("%z")[-2:]
110
 
111
+ # Create Salesforce record with aggregated milestone and last image URL
112
  record = {
113
+ "Name__c": project_name,
114
  "Current_Milestone__c": final_milestone,
115
  "Completion_Percentage__c": percent_complete,
116
  "Last_Updated_On__c": local_time,
117
  "Upload_Status__c": "Success",
118
+ "Comments__c": f"{final_milestone}",
119
+ "Last_Updated_Image__c": file_url # Note: Uses the last image's URL
120
  }
121
 
122
  try:
123
  sf.Construction__c.create(record)
 
124
  except Exception as e:
125
+ return f"Error: Failed to update Salesforce - {str(e)}", "Failure", "", "", 0
 
126
 
127
+ # Return formatted output for Gradio UI
128
  return (
129
  f"<h3 style='color:green;'>Milestone: {final_milestone}</h3>",
130
  "Success",
131
  final_milestone,
132
+ f"{percent_complete}%"
 
133
  )
134
 
135
  except Exception as e:
136
+ return f"Error: {str(e)}", "Failure", "", "", "0%"
 
137
 
138
  # Gradio UI
139
+ with gr.Blocks(css="") as demo:
140
  gr.Markdown("<h1 class='title'>Construction Progress Analyzer</h1>")
141
  with gr.Row():
142
+ image_input = gr.Files(type="filepath", label="Upload Construction Site Photos (JPG/PNG, ≤ 20MB)")
143
+ project_name_input = gr.Textbox(label="Project Name (Required)", placeholder="e.g. Project_12345")
144
+
145
+ submit_button = gr.Button("Process Image")
 
 
 
 
 
 
 
 
 
 
146
  output_html = gr.HTML(label="Result")
147
+ upload_status = gr.Textbox(label="Upload Status")
148
+ milestone = gr.Textbox(label="Detected Milestone")
149
+ progress = gr.Textbox(label="Completion Percentage", interactive=False)
 
 
150
 
151
  submit_button.click(
152
  fn=process_image,
153
  inputs=[image_input, project_name_input],
154
+ outputs=[output_html, upload_status, milestone, progress]
155
  )
156
 
157
+ demo.launch(share=True)