diff --git a/framework/python/src/api/api.py b/framework/python/src/api/api.py index 217638049..a75b67854 100644 --- a/framework/python/src/api/api.py +++ b/framework/python/src/api/api.py @@ -42,6 +42,7 @@ DEVICE_FOLDER_PATH = "devices" DEVICE_TYPES_FILE_NAME = "types.json" DEVICE_TECHS_FILE_NAME = "technologies.json" +DEVICE_QUESTIONS_FILE_NAME = "device_profile.json" LATEST_RELEASE_CHECK = ("https://api.github.com/repos/google/" + "testrun/releases/latest") @@ -68,6 +69,9 @@ def __init__(self, testrun): # Load device technologies list self._device_techs = self._load_json(device_resources, DEVICE_TECHS_FILE_NAME) + # Load device profile questions + self._device_profile = self._load_json(device_resources, + DEVICE_QUESTIONS_FILE_NAME) # Fetch Testrun session self._session = self._testrun.get_session() @@ -111,10 +115,7 @@ def __init__(self, testrun): self._router.add_api_route("/device/edit", self.edit_device, methods=["POST"]) - self._router.add_api_route("/devices/types", - self.get_device_types) - self._router.add_api_route("/devices/technology", - self.get_device_technologies) + self._router.add_api_route("/devices/format", self.get_devices_profile) # Certificate endpoints self._router.add_api_route("/system/config/certs", self.get_certs) @@ -686,6 +687,25 @@ async def get_device_types(self): async def get_device_technologies(self): return self._device_techs + async def get_devices_profile(self, + request: Request, + response: Response, + step: int = 1): + """Device profile questions""" + + all_steps = len(self._device_profile) + + try: + questions = self._device_profile[step-1] + if step < all_steps: + questions["next_step"] = f"{request.url.path}?step={step + 1}" + return questions + + except IndexError: + response.status_code = status.HTTP_404_NOT_FOUND + return self._generate_msg( + False, f"Step {step} does not exist.") + def _validate_device_json(self, json_obj): # Check all required properties are present diff --git a/resources/devices/device_profile.json b/resources/devices/device_profile.json new file mode 100644 index 000000000..0e8354dd8 --- /dev/null +++ b/resources/devices/device_profile.json @@ -0,0 +1,355 @@ +[ + { + "step": 1, + "title": "Select device type & technology", + "description": "Before your device can go through testing, tell us more about your device and its functionality. It is important that we fully understand your device before a thorough assessment can be made.", + "questions": [ + { + "id": 1, + "question": "What type of device is this?", + "validation": { + "required": true + }, + "type": "select", + "options": [ + { + "text": "Building Automation Gateway", + "risk": "High", + "id": 1 + }, + { + "text": "IoT Gateway", + "risk": "High", + "id": 2 + }, + { + "text": "Controller - AHU", + "risk": "High", + "id": 3 + }, + { + "text": "Controller - Boiler", + "risk": "High", + "id": 4 + }, + { + "text": "Controller - Chiller", + "risk": "High", + "id": 5 + }, + { + "text": "Controller - FCU", + "risk": "Limited", + "id": 6 + }, + { + "text": "Controller - Pump", + "risk": "Limited", + "id": 7 + }, + { + "text": "Controller - CRAC", + "risk": "High", + "id": 8 + }, + { + "text": "Controller - VAV", + "risk": "Limited", + "id": 9 + }, + { + "text": "Controller - VRF", + "risk": "Limited", + "id": 10 + }, + { + "text": "Controller - Multiple", + "risk": "High", + "id": 11 + }, + { + "text": "Controller - Other", + "risk": "High", + "id": 12 + }, + { + "text": "Controller - Lighting", + "risk": "Limited", + "id": 13 + }, + { + "text": "Controller - Blinds/Facades", + "risk": "High", + "id": 14 + }, + { + "text": "Controller - Lifts/Elevators", + "risk": "High", + "id": 15 + }, + { + "text": "Controller - UPS", + "risk": "High", + "id": 16 + }, + { + "text": "Sensor - Air Quality", + "risk": "Limited", + "id": 17 + }, + { + "text": "Sensor - Vibration", + "risk": "Limited", + "id": 18 + }, + { + "text": "Sensor - Humidity", + "risk": "Limited", + "id": 19 + }, + { + "text": "Sensor - Water", + "risk": "Limited", + "id": 20 + }, + { + "text": "Sensor - Occupancy", + "risk": "High", + "id": 21 + }, + { + "text": "Sensor - Volume", + "risk": "Limited", + "id": 22 + }, + { + "text": "Sensor - Weight", + "risk": "Limited", + "id": 23 + }, + { + "text": "Sensor - Weather", + "risk": "Limited", + "id": 24 + }, + { + "text": "Sensor - Steam", + "risk": "High", + "id": 25 + }, + { + "text": "Sensor - Air Flow", + "risk": "Limited", + "id": 26 + }, + { + "text": "Sensor - Lighting", + "risk": "Limited", + "id": 27 + }, + { + "text": "Sensor - Other", + "risk": "High", + "id": 28 + }, + { + "text": "Sensor - Air Quality", + "risk": "Limited", + "id": 29 + }, + { + "text": "Monitoring - Fire System", + "risk": "Limited", + "id": 30 + }, + { + "text": "Monitoring - Emergency Lighting", + "risk": "Limited", + "id": 31 + }, + { + "text": "Monitoring - Other", + "risk": "High", + "id": 32 + }, + { + "text": "Monitoring - UPS", + "risk": "Limited", + "id": 33 + }, + { + "text": "Meter - Water", + "risk": "Limited", + "id": 34 + }, + { + "text": "Meter - Gas", + "risk": "Limited", + "id": 35 + }, + { + "text": "Meter - Electricity", + "risk": "Limited", + "id": 36 + }, + { + "text": "Meter - Other", + "risk": "High", + "id": 37 + }, + { + "text": "Other", + "risk": "High", + "id": 38 + }, + { + "text": "Data - Storage", + "risk": "High", + "id": 39 + }, + { + "text": "Data - Processing", + "risk": "High", + "id": 40 + }, + { + "text": "Tablet", + "risk": "High", + "id": 41 + } + ] + }, + { + "id": 2, + "question": "Does your device process any sensitive information? ", + "validation": { + "required": true + }, + "type": "select", + "options": [ + { + "id": 1, + "text": "Yes", + "risk": "Limited" + }, + { + "id": 2, + "text": "No", + "risk": "High" + }, + { + "id": 3, + "text": "I don't know", + "risk": "High" + } + ] + }, + { + "id": 3, + "question": "Please select the technology this device falls into", + "validation": { + "required": true + }, + "type": "select", + "options": [ + { + "id": 1, + "text": "Hardware - Access Control" + }, + { + "id": 2, + "text": "Hardware - Air quality" + }, + { + "id": 3, + "text": "Hardware - Asset location tracking" + }, + { + "id": 4, + "text": "Hardware - Audio Visual" + }, + { + "id": 5, + "text": "Hardware - Blinds/Facade" + }, + { + "id": 6, + "text": "Hardware - Cameras" + }, + { + "id": 7, + "text": "Hardware - Catering" + }, + { + "id": 8, + "text": "Hardware - Data Ingestion/Managment" + }, + { + "id": 9, + "text": "Hardware - EV Charging" + }, + { + "id": 10, + "text": "Hardware - Fitness" + }, + { + "id": 11, + "text": "Hardware - HVAC" + }, + { + "id": 12, + "text": "Hardware - Irrigation" + }, + { + "id": 13, + "text": "Hardware - Leak Detection" + }, + { + "id": 14, + "text": "Hardware - Lifts/Elevators" + }, + { + "id": 15, + "text": "Hardware - Lighting" + }, + { + "id": 16, + "text": "Hardware - Metering" + }, + { + "id": 17, + "text": "Hardware - Monitoring" + }, + { + "id": 18, + "text": "Hardware - Occupancy" + }, + { + "id": 19, + "text": "Hardware - System Integration" + }, + { + "id": 20, + "text": "Hardware - Time Management" + }, + { + "id": 21, + "text": "Hardware - UPS" + }, + { + "id": 22, + "text": "Hardware - Waste Management" + }, + { + "id": 23, + "text": "Building Automation" + }, + { + "id": 24, + "text": "Other" + } + ] + } + ] + } +] \ No newline at end of file diff --git a/testing/api/test_api.py b/testing/api/test_api.py index 33163cecc..131a3e86f 100644 --- a/testing/api/test_api.py +++ b/testing/api/test_api.py @@ -42,6 +42,8 @@ BASELINE_MAC_ADDR = "02:42:aa:00:01:01" ALL_MAC_ADDR = "02:42:aa:00:00:01" +DEVICE_PROFILE_QUESTIONS = "resources/devices/device_profile.json" + def pretty_print(dictionary: dict): """ Pretty print dictionary """ print(json.dumps(dictionary, indent=4)) @@ -1444,3 +1446,26 @@ def test_delete_profile(testrun, reset_profiles, add_profile): # pylint: disable ) # Check if profile was deleted assert deleted_profile is None + + +def test_get_device_profile(): + """ Test get device profile question""" + with open(DEVICE_PROFILE_QUESTIONS, "r", encoding="utf-8") as file: + questions = json.load(file) + + # Checking the 404 error when a step does not exist. + r = requests.get(f"{API}/devices/format?step={len(questions) + 1}", + timeout=5 + ) + assert r.status_code == 404 + + r = requests.get(f"{API}/devices/format", timeout=5) + assert r.status_code == 200 + r = requests.get(f"{API}/devices/format?step=1", timeout=5) + assert r.status_code == 200 + + # Check next_step is presented + if len(questions) == 1: + assert "next_step" not in r.json() + else: + assert "next_step" in r.json()