Skip to content

Commit

Permalink
Merge pull request #76 from xmartlabs/Refactor-EndpointsEndWithoutSlash
Browse files Browse the repository at this point in the history
Refactor Endpoints to not end with /
  • Loading branch information
renzodgc authored Nov 16, 2020
2 parents 09559b1 + 773bab2 commit faa9775
Show file tree
Hide file tree
Showing 8 changed files with 127 additions and 127 deletions.
64 changes: 32 additions & 32 deletions api/areas.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class AreasListDTO(BaseModel):


def get_areas():
config = extract_config(config_type='areas')
config = extract_config(config_type="areas")
return [map_area(x, config) for x in config.keys()]


Expand All @@ -34,28 +34,28 @@ def map_area(area_name, config):
"emails": area.get("Emails"),
"occupancyThreshold": area.get("OccupancyThreshold"),
"violationThreshold": area.get("ViolationThreshold"),
"dailyReport": area.get('DailyReport'),
'dailyReportTime': area.get('DailyReportTime')
"dailyReport": area.get("DailyReport"),
"dailyReportTime": area.get("DailyReportTime")
}


def map_to_area_file_format(area: AreaConfigDTO):
return dict(
{
'Id': area.id,
'Name': area.name,
'Cameras': area.cameras,
'NotifyEveryMinutes': str(area.notifyEveryMinutes),
'Emails': area.emails,
'OccupancyThreshold': str(area.occupancyThreshold),
'ViolationThreshold': str(area.violationThreshold),
"Id": area.id,
"Name": area.name,
"Cameras": area.cameras,
"NotifyEveryMinutes": str(area.notifyEveryMinutes),
"Emails": area.emails,
"OccupancyThreshold": str(area.occupancyThreshold),
"ViolationThreshold": str(area.violationThreshold),
"DailyReport": str(area.dailyReport),
'DailyReportTime': area.dailyReportTime
"DailyReportTime": area.dailyReportTime
}
)


@areas_router.get("/", response_model=AreasListDTO)
@areas_router.get("", response_model=AreasListDTO)
async def list_areas():
"""
Returns the list of areas managed by the processor.
Expand All @@ -70,37 +70,37 @@ async def get_area(area_id: str):
"""
Returns the configuration related to the area <area_id>
"""
area = next((area for area in get_areas() if area['id'] == area_id), None)
area = next((area for area in get_areas() if area["id"] == area_id), None)
if not area:
raise HTTPException(status_code=404, detail=f'The area: {area_id} does not exist')
raise HTTPException(status_code=404, detail=f"The area: {area_id} does not exist")
return area


@areas_router.post('/', response_model=AreaConfigDTO, status_code=status.HTTP_201_CREATED)
@areas_router.post("", response_model=AreaConfigDTO, status_code=status.HTTP_201_CREATED)
async def create_area(new_area: AreaConfigDTO):
"""
Adds a new area to the processor.
"""
config_dict = extract_config()
areas_name = [x for x in config_dict.keys() if x.startswith("Area")]
areas = [map_area(x, config_dict) for x in areas_name]
if new_area.id in [area['id'] for area in areas]:
if new_area.id in [area["id"] for area in areas]:
raise HTTPException(status_code=400, detail="Area already exists")

cameras = [x for x in config_dict.keys() if x.startswith("Source")]
cameras = [map_camera(x, config_dict, []) for x in cameras]
camera_ids = [camera['id'] for camera in cameras]
if not all(x in camera_ids for x in new_area.cameras.split(',')):
non_existent_cameras = set(new_area.cameras.split(',')) - set(camera_ids)
raise HTTPException(status_code=404, detail=f'The cameras: {non_existent_cameras} do not exist')
camera_ids = [camera["id"] for camera in cameras]
if not all(x in camera_ids for x in new_area.cameras.split(",")):
non_existent_cameras = set(new_area.cameras.split(",")) - set(camera_ids)
raise HTTPException(status_code=404, detail=f"The cameras: {non_existent_cameras} do not exist")
area_dict = map_to_area_file_format(new_area)
config_dict[f'Area_{len(areas)}'] = area_dict
config_dict[f"Area_{len(areas)}"] = area_dict

success = update_and_restart_config(config_dict)
return handle_response(area_dict, success, status.HTTP_201_CREATED)


@areas_router.put('/{area_id}', response_model=AreaConfigDTO)
@areas_router.put("/{area_id}", response_model=AreaConfigDTO)
async def edit_area(area_id: str, edited_area: AreaConfigDTO):
"""
Edits the configuration related to the area <area_id>
Expand All @@ -109,18 +109,18 @@ async def edit_area(area_id: str, edited_area: AreaConfigDTO):
config_dict = extract_config()
area_names = [x for x in config_dict.keys() if x.startswith("Area")]
areas = [map_area(x, config_dict) for x in area_names]
areas_ids = [area['id'] for area in areas]
areas_ids = [area["id"] for area in areas]
try:
index = areas_ids.index(area_id)
except ValueError:
raise HTTPException(status_code=404, detail=f'The area: {area_id} does not exist')
raise HTTPException(status_code=404, detail=f"The area: {area_id} does not exist")

cameras = [x for x in config_dict.keys() if x.startswith("Source")]
cameras = [map_camera(x, config_dict, []) for x in cameras]
camera_ids = [camera['id'] for camera in cameras]
if not all(x in camera_ids for x in edited_area.cameras.split(',')):
non_existent_cameras = set(edited_area.cameras.split(',')) - set(camera_ids)
raise HTTPException(status_code=404, detail=f'The cameras: {non_existent_cameras} do not exist')
camera_ids = [camera["id"] for camera in cameras]
if not all(x in camera_ids for x in edited_area.cameras.split(",")):
non_existent_cameras = set(edited_area.cameras.split(",")) - set(camera_ids)
raise HTTPException(status_code=404, detail=f"The cameras: {non_existent_cameras} do not exist")

area_dict = map_to_area_file_format(edited_area)
config_dict[f"Area_{index}"] = area_dict
Expand All @@ -129,21 +129,21 @@ async def edit_area(area_id: str, edited_area: AreaConfigDTO):
return handle_response(area_dict, success)


@areas_router.delete('/{area_id}', status_code=status.HTTP_204_NO_CONTENT)
@areas_router.delete("/{area_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_area(area_id: str):
"""
Deletes the configuration related to the area <area_id>
"""
config_dict = extract_config()
areas_name = [x for x in config_dict.keys() if x.startswith("Area")]
areas = [map_area(x, config_dict) for x in areas_name]
areas_ids = [area['id'] for area in areas]
areas_ids = [area["id"] for area in areas]
try:
index = areas_ids.index(area_id)
except ValueError:
raise HTTPException(status_code=404, detail=f'The area: {area_id} does not exist')
raise HTTPException(status_code=404, detail=f"The area: {area_id} does not exist")

config_dict.pop(f'Area_{index}')
config_dict.pop(f"Area_{index}")
config_dict = reestructure_areas((config_dict))

success = update_and_restart_config(config_dict)
Expand Down
82 changes: 41 additions & 41 deletions api/cameras.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ class ImageModel(BaseModel):

class Config:
schema_extra = {
'example': {
'image': 'data:image/jpg;base64,iVBORw0KG...'
"example": {
"image": "data:image/jpg;base64,iVBORw0KG..."
}
}

Expand All @@ -47,7 +47,7 @@ def map_camera(camera_name, config, options=[]):
image = None
if "withImage" in options:
dir_path = os.path.join(get_config().get_section_dict("App")["ScreenshotsDirectory"], camera_id)
image = base64.b64encode(cv.imread(f'{dir_path}/default.jpg'))
image = base64.b64encode(cv.imread(f"{dir_path}/default.jpg"))

return {
"id": camera_id,
Expand All @@ -57,46 +57,46 @@ def map_camera(camera_name, config, options=[]):
"violationThreshold": camera.get("ViolationThreshold"),
"notifyEveryMinutes": camera.get("NotifyEveryMinutes"),
"dailyReport": camera.get("DailyReport"),
'dailyReportTime': camera.get('DailyReportTime'),
"dailyReportTime": camera.get("DailyReportTime"),
"image": image,
"distMethod": camera.get("DistMethod"),
"distMethod": camera.get("DistMethod")
}


def get_cameras(options):
config = extract_config(config_type='cameras')
config = extract_config(config_type="cameras")
return [map_camera(x, config, options) for x in config.keys()]


def map_to_camera_file_format(camera: SourceConfigDTO):
return dict(
{
'Name': camera.name,
'VideoPath': camera.videoPath,
'Id': camera.id,
'Emails': camera.emails,
'Tags': camera.tags,
'NotifyEveryMinutes': str(camera.notifyEveryMinutes),
'ViolationThreshold': str(camera.violationThreshold),
'DistMethod': camera.distMethod,
'DailyReport': str(camera.dailyReport),
'DailyReportTime': camera.dailyReportTime
"Name": camera.name,
"VideoPath": camera.videoPath,
"Id": camera.id,
"Emails": camera.emails,
"Tags": camera.tags,
"NotifyEveryMinutes": str(camera.notifyEveryMinutes),
"ViolationThreshold": str(camera.violationThreshold),
"DistMethod": camera.distMethod,
"DailyReport": str(camera.dailyReport),
"DailyReportTime": camera.dailyReportTime
}
)


def delete_camera_from_areas(camera_id, config_dict):
areas = {key: config_dict[key] for key in config_dict.keys() if key.startswith("Area")}
for key, area in areas.items():
cameras = area['Cameras'].split(',')
cameras = area["Cameras"].split(",")
if camera_id in cameras:
cameras.remove(camera_id)
if len(cameras) == 0:
logger.warning(f'After removing the camera "{camera_id}", the area "{area["Id"]} - {area["Name"]}" \
"was left with no cameras and deleted')
config_dict.pop(key)
else:
config_dict[key]['Cameras'] = ",".join(cameras)
config_dict[key]["Cameras"] = ",".join(cameras)

config_dict = reestructure_areas(config_dict)
return config_dict
Expand All @@ -107,20 +107,20 @@ def reestructure_cameras(config_dict):
source_names = [x for x in config_dict.keys() if x.startswith("Source")]
source_names.sort()
for index, source_name in enumerate(source_names):
if f'Source_{index}' != source_name:
config_dict[f'Source_{index}'] = config_dict[source_name]
if f"Source_{index}" != source_name:
config_dict[f"Source_{index}"] = config_dict[source_name]
config_dict.pop(source_name)
return config_dict


def verify_path(base, camera_id):
dir_path = os.path.join(base, camera_id)
if not os.path.exists(dir_path):
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f'The camera: {camera_id} does not exist')
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"The camera: {camera_id} does not exist")
return dir_path


@cameras_router.get("/", response_model=CamerasListDTO)
@cameras_router.get("", response_model=CamerasListDTO)
async def list_cameras(options: Optional[str] = ""):
"""
Returns the list of cameras managed by the processor.
Expand All @@ -135,24 +135,24 @@ async def get_camera(camera_id: str):
"""
Returns the configuration related to the camera <camera_id>
"""
camera = next((camera for camera in get_cameras(['withImage']) if camera['id'] == camera_id), None)
camera = next((camera for camera in get_cameras(["withImage"]) if camera["id"] == camera_id), None)
if not camera:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f'The camera: {camera_id} does not exist')
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"The camera: {camera_id} does not exist")
return camera


@cameras_router.post("/", response_model=SourceConfigDTO, status_code=status.HTTP_201_CREATED)
@cameras_router.post("", response_model=SourceConfigDTO, status_code=status.HTTP_201_CREATED)
async def create_camera(new_camera: SourceConfigDTO):
"""
Adds a new camera to the processor.
"""
config_dict = extract_config()
cameras_name = [x for x in config_dict.keys() if x.startswith("Source")]
cameras = [map_camera(x, config_dict, []) for x in cameras_name]
if new_camera.id in [camera['id'] for camera in cameras]:
if new_camera.id in [camera["id"] for camera in cameras]:
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Camera already exists")
camera_dict = map_to_camera_file_format(new_camera)
config_dict[f'Source_{len(cameras)}'] = camera_dict
config_dict[f"Source_{len(cameras)}"] = camera_dict
success = update_and_restart_config(config_dict)
return handle_response(camera_dict, success, status.HTTP_201_CREATED)

Expand All @@ -166,11 +166,11 @@ async def edit_camera(camera_id: str, edited_camera: SourceConfigDTO):
config_dict = extract_config()
camera_names = [x for x in config_dict.keys() if x.startswith("Source")]
cameras = [map_camera(x, config_dict, []) for x in camera_names]
cameras_ids = [camera['id'] for camera in cameras]
cameras_ids = [camera["id"] for camera in cameras]
try:
index = cameras_ids.index(camera_id)
except ValueError:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f'The camera: {camera_id} does not exist')
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"The camera: {camera_id} does not exist")

camera_dict = map_to_camera_file_format(edited_camera)
config_dict[f"Source_{index}"] = map_to_camera_file_format(edited_camera)
Expand All @@ -187,15 +187,15 @@ async def delete_camera(camera_id: str):
config_dict = extract_config()
camera_names = [x for x in config_dict.keys() if x.startswith("Source")]
cameras = [map_camera(x, config_dict) for x in camera_names]
cameras_ids = [camera['id'] for camera in cameras]
cameras_ids = [camera["id"] for camera in cameras]
try:
index = cameras_ids.index(camera_id)
except ValueError:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f'The camera: {camera_id} does not exist')
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"The camera: {camera_id} does not exist")

config_dict = delete_camera_from_areas(camera_id, config_dict)

config_dict.pop(f'Source_{index}')
config_dict.pop(f"Source_{index}")
config_dict = reestructure_cameras((config_dict))
success = update_and_restart_config(config_dict)
return handle_response(None, success, status.HTTP_204_NO_CONTENT)
Expand All @@ -207,7 +207,7 @@ async def get_camera_image(camera_id: str):
Gets the image related to the camera <camera_id>
"""
dir_path = verify_path(settings.config.get_section_dict("App")["ScreenshotsDirectory"], camera_id)
with open(f'{dir_path}/default.jpg', "rb") as image_file:
with open(f"{dir_path}/default.jpg", "rb") as image_file:
encoded_string = base64.b64encode(image_file.read())
return {
"image": encoded_string
Expand All @@ -221,7 +221,7 @@ async def replace_camera_image(camera_id: str, body: ImageModel):
"""
dir_path = verify_path(settings.config.get_section_dict("App")["ScreenshotsDirectory"], camera_id)
try:
decoded_image = base64.b64decode(body.image.split(',')[1])
decoded_image = base64.b64decode(body.image.split(",")[1])
nparr = np.fromstring(decoded_image, np.uint8)
cv_image = cv.imdecode(nparr, cv.IMREAD_COLOR)
cv.imwrite(f"{dir_path}/default.jpg", cv_image)
Expand All @@ -234,16 +234,16 @@ async def config_calibrated_distance(camera_id: str, body: ConfigHomographyMatri
"""
Calibrates the camera <camera_id> receiving as input the coordinates of a square of size 3ft 3" by 3ft 3" (1m by 1m).
"""
dir_source = next((source for source in settings.config.get_video_sources() if source['id'] == camera_id), None)
dir_source = next((source for source in settings.config.get_video_sources() if source["id"] == camera_id), None)
if not dir_source:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f'The camera: {camera_id} does not exist')
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"The camera: {camera_id} does not exist")
dir_path = get_camera_calibration_path(settings.config, camera_id)
compute_and_save_inv_homography_matrix(points=body, destination=dir_path)
sections = settings.config.get_sections()
config_dict = {}
for section in sections:
config_dict[section] = settings.config.get_section_dict(section)
config_dict[dir_source['section']]['DistMethod'] = 'CalibratedDistance'
config_dict[dir_source["section"]]["DistMethod"] = "CalibratedDistance"
success = update_and_restart_config(config_dict)
return handle_response(None, success, status.HTTP_204_NO_CONTENT)

Expand All @@ -253,14 +253,14 @@ async def get_camera_calibration_image(camera_id: str):
"""
Gets the image required to calibrate the camera <camera_id>
"""
camera = next((camera for camera in get_cameras(['withImage']) if camera['id'] == camera_id), None)
camera_cap = cv.VideoCapture(camera['videoPath'])
camera = next((camera for camera in get_cameras(["withImage"]) if camera["id"] == camera_id), None)
camera_cap = cv.VideoCapture(camera["videoPath"])
if not camera_cap.isOpened():
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f'The camera: {camera_id} is not available.')
detail=f"The camera: {camera_id} is not available.")
_, cv_image = camera_cap.read()
_, buffer = cv.imencode('.jpg', cv_image)
_, buffer = cv.imencode(".jpg", cv_image)
encoded_string = base64.b64encode(buffer)
camera_cap.release()
return {
Expand Down
4 changes: 2 additions & 2 deletions api/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def map_config(config, options):
}


@config_router.get("/", response_model=ConfigDTO)
@config_router.get("", response_model=ConfigDTO)
async def get_config(options: Optional[str] = ""):
"""
Returns the configuration used by the processor
Expand All @@ -42,7 +42,7 @@ async def get_config(options: Optional[str] = ""):
return map_config(extract_config(), options)


@config_router.put("/", response_model=ConfigDTO)
@config_router.put("", response_model=ConfigDTO)
async def update_config(config: ConfigDTO):
"""
Overwrites the configuration used by the processor.
Expand Down
Loading

0 comments on commit faa9775

Please sign in to comment.