Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…ototype into TELUS-UI
  • Loading branch information
YaokunLin committed Sep 21, 2023
2 parents c8cd3f8 + 2b6b208 commit 2cbfa6c
Show file tree
Hide file tree
Showing 25 changed files with 27 additions and 536 deletions.
8 changes: 0 additions & 8 deletions .github/workflows/build-and-push.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,6 @@ jobs:
name: api
build-args: |
"BB_TOKEN=${{ secrets.BB_TOKEN }}"
- image: ghcr.io/button-inc/iot-system-prototype/real_fake_sensors
context: .
dockerfile: real_fake_sensors/Dockerfile
name: realFakeSensors
- image: ghcr.io/button-inc/iot-system-prototype/sensational_sensors
context: .
dockerfile: sensational_sensors/Dockerfile
name: sensationalSensors
name: Build ${{ matrix.name }} docker image
steps:
- uses: actions/checkout@v3
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ To stop, `ctrl`/`cmd` + `c`, or `docker-compose stop` if using the daemon.
When working on the frontend code it can be useful to run `docker-compose stop app` , then `cd ./app`, `yarn dev` for the live changes.

## For backend reload on change

Need to have three terminals open:

- `cd api` then `uvicorn main:app --host 0.0.0.0 --port 8080 --reload`
- `cd real_fake_sensors` then `uvicorn main:app --host 0.0.0.0 --port 8081 --reload`
- `cd sensational_sensors` then `uvicorn main:app --host 0.0.0.0 --port 8082 --reload`
131 changes: 2 additions & 129 deletions api/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,25 +36,13 @@
# 📚 Authenticate with Google Sheets service account
sa = gspread.service_account(filename="google_sheets_sa_key.json")

# 🌎 Set base URLs based on the environment
if env == "prod":
REAL_FAKE_SENSORS_BASE_URL = "http://real-fake-sensors:8081"
SENSATIONAL_SENSORS_BASE_URL = "http://sensational-sensors:8082"
else:
REAL_FAKE_SENSORS_BASE_URL = "http://localhost:8081"
SENSATIONAL_SENSORS_BASE_URL = "http://localhost:8082"

# 🚀 Initialize FastAPI application
app = FastAPI()

# 🌐 Define CORS origins that are allowed to access the API
origins = [
"http://localhost:5173",
"http://localhost:3000",
"http://localhost:8081",
"http://localhost:8082",
"http://0.0.0.0:8081",
"http://0.0.0.0:8082",
"http://wav.button.build",
"http://34.123.69.225/",
"http://34.123.69.225:80",
Expand Down Expand Up @@ -97,35 +85,6 @@ class BasicSensor(BaseModel):
bin_volume: str


# 📝 Model to represent a RealFakeSensor
class RealFakeSensor(BaseModel):
sensorsID: str
sensorCompany: str
sensorDeviceID: int
firmwareVersion: str
clientId: int
simCardNumber: str
connectivityProvider: str
latest_sensors_data: dict | None
latitude: float
longitude: float
asset_tag: str
bin_volume: str


# 📝 Model to represent a SensationalSensor
class SensationalSensor(BaseModel):
id: str
sensor_type: SensorType
fill_level: int
sim: str
lat: float
long: float
man: str
asset_tag: str
bin_volume: str


# 📝 Model to represent a BrighterBinsSensorReading
class BrighterBinsSensorReading(BaseModel):
epoch_ms: int
Expand Down Expand Up @@ -190,72 +149,6 @@ class TekelekSensor(BaseModel):
PercentFull: Optional[float] = None


# 🔧 Function to convert RealFakeSensor to BasicSensor
def rfs_to_bs(sensor: RealFakeSensor) -> BasicSensor:
return BasicSensor(
id=sensor["sensorsID"],
sensor_type=SensorType.LIQUID_BIN_LEVEL,
fill_level=sensor["latest_sensors_data"]["level"]
if sensor["latest_sensors_data"]
else None,
lat=sensor["latitude"],
long=sensor["longitude"],
manufacturer=sensor["sensorCompany"],
bin_name=sensor["bin_name"],
address_line1=sensor["address_line1"],
address_line2=sensor["address_line2"],
group=sensor["group"],
bin_type=sensor["bin_type"],
material_type=sensor["material_type"],
asset_tag=sensor["asset_tag"],
bin_volume=sensor["bin_volume"],
)


# 🔧 Function to convert RealFakeSensor dictionary to BasicSensor list
def rfs_dict_to_bs_list(
sensors: dict[str, RealFakeSensor | None]
) -> list[BasicSensor | None]:
bs_list = []
for index, sensor_id in enumerate(sensors):
if sensor_id in sensors:
bs_list.append(rfs_to_bs(sensors[sensor_id]))

return bs_list


# 🔧 Function to convert SensationalSensor to BasicSensor
def sensational_sensor_to_basic_sensor(sensor: SensationalSensor) -> BasicSensor:
return BasicSensor(
id=sensor["id"],
sensor_type=SensorType.SOLID_BIN_LEVEL,
fill_level=sensor["fill_level"] if sensor["fill_level"] else None,
lat=sensor["lat"],
long=sensor["long"],
manufacturer=sensor["man"],
bin_name=sensor["bin_name"],
address_line1=sensor["address_line1"],
address_line2=sensor["address_line2"],
group=sensor["group"],
bin_type=sensor["bin_type"],
material_type=sensor["material_type"],
asset_tag=sensor["asset_tag"],
bin_volume=sensor["bin_volume"],
)


# 🔧 Function to convert SensationalSensor dictionary to BasicSensor list
def ss_dict_to_bs_list(
sensors: dict[str, SensationalSensor | None]
) -> list[BasicSensor | None]:
bs_list = []
for index, sensor_id in enumerate(sensors):
if sensor_id in sensors:
bs_list.append(sensational_sensor_to_basic_sensor(sensors[sensor_id]))

return bs_list


# 🔧 Function to convert TekelekSensor to BasicSensor
def tkl_to_bs(sensor: TekelekSensor) -> BasicSensor:
lat, long = None, None # Default values in case of errors
Expand Down Expand Up @@ -442,27 +335,9 @@ def make_http_request(url, method="GET", headers=None, params=None, data=None):


# Caches for sensor data
rfs_cache = []
ss_cache = []
bb_cache = {}
last_run_timestamp = 0
tkl_cache = {}


# 🤖 Event handler: Populate rfs_cache and ss_cache with initial data on start up
@app.on_event("startup")
def set_rfs_and_ss_cache():
global rfs_cache
global ss_cache
# Convert the sensors to the common "BasicSensor" type and cache their values
# rfs and ss are mock so they have a simple case, we can fetch once and never again, they won't change.
rfs_response = requests.get(REAL_FAKE_SENSORS_BASE_URL + "/sensors").json()
rfs_as_bs = rfs_dict_to_bs_list(rfs_response)
rfs_cache = rfs_as_bs
# print(f"rfs_cache: {rfs_cache}")
ss_response = requests.get(SENSATIONAL_SENSORS_BASE_URL + "/sensors").json()
ss_cache = ss_dict_to_bs_list(ss_response)
return
last_run_timestamp = 0


# 🤖 Event handler: Populate Tekelek data in tkl_cache with initial data on start up
Expand Down Expand Up @@ -611,8 +486,6 @@ def update_bb_cache() -> None:
# 🚀 API endpoint: Get the latest readings from all types of sensors
@app.get("/latest_readings")
def get_latest_readings():
global rfs_cache
global ss_cache
global bb_cache
global tkl_cache

Expand All @@ -626,7 +499,7 @@ def get_latest_readings():
for index, sensor in enumerate(tkl_cache):
tkl_readings.append(tkl_cache[sensor])

latest_readings = bb_readings + tkl_readings + rfs_cache + ss_cache
latest_readings = bb_readings + tkl_readings
# latest_readings = filter_nulls(latest_readings)
return {"sensors": latest_readings}

Expand Down
6 changes: 0 additions & 6 deletions app/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,6 @@ const Home: NextPage = () => {
for (const sensorId in responseJson.brighterBins) {
sensorsArray.push(responseJson.brighterBins[sensorId]);
}
for (const sensorId in responseJson.realFakeSensors) {
sensorsArray.push(responseJson.realFakeSensors[sensorId]);
}
for (const sensorId in responseJson.sensationalSensors) {
sensorsArray.push(responseJson.sensationalSensors[sensorId]);
}
setSensors(sensorsArray);
}, []);

Expand Down
5 changes: 3 additions & 2 deletions app_vue/index.html
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<html class="html-class" lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<link rel="preload" as="font" href="./src/assets/fonts/Inter.woff2" type="font/woff2" crossorigin="anonymous">

<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vite App</title>
<title>TELUS Smart Waste</title>
</head>
<body>
<div id="app"></div>
Expand Down
Binary file modified app_vue/public/favicon.ico
Binary file not shown.
9 changes: 7 additions & 2 deletions app_vue/src/assets/base.scss
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
/* color palette from <https://github.com/vuejs/theme> */
// custom font used globally, used in _variables $font-face
@import './stylesheets/fonts';
@import './stylesheets/variables';
@import './stylesheets/mixins';
@import './stylesheets/fonts';

*,
*::before,
Expand All @@ -13,6 +14,10 @@
font-family: $font-face;
}

html.html-class {
overflow-y: auto;
}

a {
color: inherit;
text-decoration: none;
Expand All @@ -23,4 +28,4 @@ li {
align-items: center;
list-style: none;
margin: 16px 0;
}
}
Binary file removed app_vue/src/assets/fonts/Rubik_VariableFont.woff2
Binary file not shown.
7 changes: 3 additions & 4 deletions app_vue/src/assets/stylesheets/_fonts.scss
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// a single global font
@font-face {
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
src: url('../fonts/Inter.woff2') format('woff2');
font-family: 'Inter';
src: url('@/assets/fonts/Inter.woff2') format('woff2');
font-weight: 100 900;
font-display: block;
}
}
3 changes: 1 addition & 2 deletions app_vue/src/assets/stylesheets/_mixins.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// font mixins

@mixin fontHeading1() {
font-size: 6rem;
font-weight: 300;
Expand Down Expand Up @@ -131,4 +130,4 @@ $extraLargeScreenWidth: 1600px;
@media (min-width: $extraLargeScreenWidth) {
@content;
}
}
}
1 change: 1 addition & 0 deletions app_vue/src/assets/stylesheets/_variables.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// global font face variable
$font-face: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Helvetica', 'Arial', 'sans-serif';

//color variables
Expand Down
2 changes: 1 addition & 1 deletion app_vue/src/components/sensorMap.vue
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@
:deep .leaflet-popup-content-wrapper {
width: 300px;
height: 300px;
overflow-y: scroll;
overflow-y: auto;
overflow-x: hidden;
@include smallScreens {
Expand Down
7 changes: 4 additions & 3 deletions app_vue/src/utils/mapMarkerHelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ const getBinIconName = (sensor) => {

export const getMaterialTypeIconURL = (materialType) => {
const directory = 'src/assets/images/materialTypeIcons';
const genericMaterialIconPath = `${directory}/generic-material.svg`;
if (!materialType) {
return 'src/assets/images/generic-material.png';
return genericMaterialIconPath;
}
const materialMap = {
'Cardboard': `${directory}/cardboard.svg`, //confirmed
Expand All @@ -32,7 +33,7 @@ export const getMaterialTypeIconURL = (materialType) => {
'Gas Oil': `${directory}/oil-drum.svg`,
'Mixed waste': `${directory}/trash.svg`
};
return materialMap[materialType] || 'src/assets/images/generic-material.png';
return materialMap[materialType] || genericMaterialIconPath;
}

// linearProgressColor -> used by Vuetify to determine progress bar color
Expand Down Expand Up @@ -70,4 +71,4 @@ export const getIconAndProgressColor = (sensor) => {
return { iconUrl, linearProgressColor };
}

export default getIconAndProgressColor
export default getIconAndProgressColor
1 change: 1 addition & 0 deletions app_vue/vite.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export default defineConfig({
preprocessorOptions: {
scss: {
additionalData: `
@import "@/assets/stylesheets/fonts";
@import "@/assets/stylesheets/variables";
@import "@/assets/stylesheets/mixins";
@import "@/assets/stylesheets/functions";
Expand Down
4 changes: 2 additions & 2 deletions bin/vueLocalDeploy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ sleep .5
echo "looking up docker containers..."
docker container ls -a
sleep .5
if [ "$( docker inspect --format '{{json .State.Running}}' real-fake-sensors )" = "true" ] && [ "$( docker inspect --format '{{json .State.Running}}' sensational-sensors )" = "true" ];
if [ "$( docker inspect --format '{{json .State.Running}}' api )" = "true" ];
then
echo "docker is running, continuing execution..."
else
Expand All @@ -48,4 +48,4 @@ echo "installing node packages..."
npm install

echo "starting up vue app..."
npm run start
npm run start
17 changes: 0 additions & 17 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,30 +1,13 @@
version: "3.9"

services:
real_fake_sensors:
container_name: real-fake-sensors
build:
context: .
dockerfile: real_fake_sensors/Dockerfile
ports:
- "8081:8081"
sensational_sensors:
container_name: sensational-sensors
build:
context: .
dockerfile: sensational_sensors/Dockerfile
ports:
- "8082:8082"
api:
container_name: api
build:
context: .
dockerfile: api/Dockerfile
ports:
- "8080:8080"
depends_on:
- real_fake_sensors
- sensational_sensors
environment:
- ENVIRONMENT=prod
app:
Expand Down
Loading

0 comments on commit 2cbfa6c

Please sign in to comment.