Skip to content
This repository was archived by the owner on Feb 22, 2025. It is now read-only.

Commit dd25ca3

Browse files
authored
Merge pull request #19 from fcabrera23/contoso-supermarket-source
Adding source code for Contoso Supermarket
2 parents 93517d5 + 1b04393 commit dd25ca3

35 files changed

+10839
-0
lines changed
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
{
2+
// Use IntelliSense to learn about possible attributes.
3+
// Hover to view descriptions of existing attributes.
4+
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5+
6+
"version": "0.2.0",
7+
"configurations": [
8+
{
9+
"name": "Python: Flask (0.11.x or later)",
10+
"type": "python",
11+
"request": "launch",
12+
"module": "flask",
13+
"env": {
14+
"FLASK_APP": "app.py",
15+
"SQL_HOST": "",
16+
"SQL_USERNAME": "",
17+
"SQL_PASSWORD": "",
18+
"SQL_DATABASE": "",
19+
"HEAD_TITLE" : "Hello World",
20+
"CAMERAS_ENABLED" : "False",
21+
"CAMERAS_BASEURL" : "",
22+
"NEW_CATEGORY" : "True"
23+
},
24+
"args": [
25+
"run",
26+
"--no-debugger",
27+
"--no-reload"
28+
]
29+
},
30+
{
31+
"name": "Python: Current File",
32+
"type": "python",
33+
"request": "launch",
34+
"program": "${file}",
35+
"env": {
36+
"FLASK_ENV": "development"
37+
}
38+
},
39+
{
40+
"name": "Python: Attach",
41+
"type": "python",
42+
"request": "attach",
43+
"localRoot": "${workspaceFolder}",
44+
"remoteRoot": "${workspaceFolder}",
45+
"port": 3000,
46+
"secret": "my_secret",
47+
"host": "localhost"
48+
}
49+
]
50+
}

contoso-supermarket/src/Dockerfile

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# syntax=docker/dockerfile:1
2+
FROM python:3.8-slim-buster
3+
4+
RUN apt-get update
5+
RUN apt-get install ffmpeg libsm6 libxext6 -y
6+
7+
WORKDIR /python-docker
8+
9+
COPY requirements.txt requirements.txt
10+
RUN pip3 install -r requirements.txt
11+
12+
COPY . .
13+
14+
CMD [ "python3", "-m" , "flask", "run", "--host=0.0.0.0"]

contoso-supermarket/src/app.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
#!/usr/bin/env python
2+
from importlib import import_module
3+
import os
4+
import cv2
5+
from flask import Flask, render_template, Response, request
6+
from sqlConnector import SqlConnector
7+
8+
app = Flask(__name__)
9+
10+
@app.route('/')
11+
def index():
12+
"""Contoso Supermarket home page."""
13+
cameras_enabled = True
14+
if os.environ.get('CAMERAS_ENABLED'):
15+
cameras_enabled = os.environ.get('CAMERAS_ENABLED') == 'True'
16+
17+
head_title = "Contoso Supermarket"
18+
if os.environ.get('HEAD_TITLE'):
19+
head_title = os.environ.get('HEAD_TITLE')
20+
21+
new_category = False
22+
if os.environ.get('NEW_CATEGORY'):
23+
new_category = os.environ.get('NEW_CATEGORY') == 'True'
24+
25+
return render_template('index2.html' if new_category else 'index.html', head_title = head_title, cameras_enabled = cameras_enabled)
26+
27+
@app.route('/addPurchase',methods = ['POST'])
28+
def addPurchase():
29+
content_type = request.headers.get('Content-Type')
30+
if (content_type == 'application/json; charset=UTF-8'):
31+
json = request.get_json()
32+
sqlDb = SqlConnector()
33+
successful = sqlDb.addPurchase(json['ProductId'])
34+
if(successful):
35+
return "Ok"
36+
else:
37+
return "Error processing request"
38+
else:
39+
return 'Content-Type not supported!'
40+
41+
@app.route('/video_feed/<feed>')
42+
def video_feed(feed):
43+
return Response(gen_frames(feed),
44+
mimetype='multipart/x-mixed-replace; boundary=frame')
45+
46+
47+
def gen_frames(source):
48+
"""Video streaming frame capture function."""
49+
baseUrl = "rtsp://localhost:554/media/"
50+
if os.environ.get('CAMERAS_BASEURL'):
51+
baseUrl = str(os.environ['CAMERAS_BASEURL'])
52+
53+
cap = cv2.VideoCapture(baseUrl + source) # capture the video from the live feed
54+
55+
while True:
56+
# # Capture frame-by-frame. Return boolean(True=frame read correctly. )
57+
success, frame = cap.read() # read the camera frame
58+
if not success:
59+
break
60+
else:
61+
ret, buffer = cv2.imencode('.jpg', frame)
62+
frame = buffer.tobytes()
63+
yield (b'--frame\r\n'
64+
b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n') # concat frame one by one and show result
65+
66+
if __name__ == '__main__':
67+
app.run(host='0.0.0.0', threaded=True, debug=True)
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
USE contososupermarket;
2+
3+
CREATE TABLE `Stocks` (
4+
`ProductID` INT NOT NULL AUTO_INCREMENT,
5+
`Name` TEXT,
6+
`Sold` INT DEFAULT '10000',
7+
`Stock` INT zerofill,
8+
PRIMARY KEY (`ProductID`)
9+
);
10+
11+
INSERT INTO `Stocks`
12+
VALUES
13+
(1, "Red apple", 10000, 0),
14+
(2, "Banana", 10000, 0),
15+
(3, "Avocado", 10000, 0),
16+
(4, "Bread", 10000, 0),
17+
(5, "Milk", 10000, 0),
18+
(6, "Orange juice", 10000, 0),
19+
(7, "Chips", 10000, 0),
20+
(8, "Red bell pepper", 10000, 0),
21+
(9, "Lettuce", 10000, 0);
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
click==8.1.3
2+
Flask==2.2.2
3+
itsdangerous==2.1.2
4+
Jinja2==3.1.2
5+
MarkupSafe==2.1.1
6+
Werkzeug==2.2.2
7+
numpy==1.22.0
8+
opencv-python==4.6.0.66
9+
mysql-connector-python==8.0.30
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import os
2+
import mysql.connector
3+
4+
class SqlConnector:
5+
sqlHost = ""
6+
sqlUsername = ""
7+
sqlPassword = ""
8+
sqlDatabase = ""
9+
10+
def __init__(self):
11+
if os.environ.get('SQL_HOST'):
12+
self.sqlHost = str(os.environ['SQL_HOST'])
13+
14+
if os.environ.get('SQL_USERNAME'):
15+
self.sqlUsername = str(os.environ['SQL_USERNAME'])
16+
17+
if os.environ.get('SQL_PASSWORD'):
18+
self.sqlPassword = str(os.environ['SQL_PASSWORD'])
19+
20+
if os.environ.get('SQL_DATABASE'):
21+
self.sqlDatabase = str(os.environ['SQL_DATABASE'])
22+
23+
self.connection = self.createServerConnection()
24+
if(self.connection != None):
25+
self.cursor = self.connection.cursor()
26+
else:
27+
print("Fail to establish MySQL database connection")
28+
29+
def createServerConnection(self):
30+
connection = None
31+
try:
32+
connection = mysql.connector.connect(
33+
user= self.sqlUsername,
34+
password= self.sqlPassword,
35+
host= self.sqlHost,
36+
port=3306,
37+
database= self.sqlDatabase,
38+
ssl_disabled=True
39+
)
40+
41+
print("MySQL Database connection successful")
42+
except Exception as ex:
43+
print(f"Error: '{ex}'")
44+
45+
return connection
46+
47+
def addPurchase(self, productId):
48+
try:
49+
query = "UPDATE `Stocks` SET `Sold` = `Sold` + 1, `Stock` = `Stock` - 1 WHERE `ProductID` = {}".format(productId)
50+
self.cursor.execute(query)
51+
self.connection.commit()
52+
if(self.cursor.rowcount == 1):
53+
return True
54+
else:
55+
return False
56+
except Exception as ex:
57+
print(f"Error: '{ex}'")
58+
return False
59+

0 commit comments

Comments
 (0)