diff --git a/care/facility/api/viewsets/asset.py b/care/facility/api/viewsets/asset.py index d5fd3b5a59..3fe55d297a 100644 --- a/care/facility/api/viewsets/asset.py +++ b/care/facility/api/viewsets/asset.py @@ -3,9 +3,8 @@ from django.shortcuts import get_object_or_404 from django_filters import rest_framework as filters from drf_yasg.utils import swagger_auto_schema -from rest_framework import filters as drf_filters from dry_rest_permissions.generics import DRYPermissions -from rest_framework.permissions import IsAuthenticated +from rest_framework import filters as drf_filters from rest_framework import status from rest_framework.decorators import action from rest_framework.exceptions import ValidationError @@ -15,6 +14,7 @@ RetrieveModelMixin, UpdateModelMixin, ) +from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response from rest_framework.serializers import CharField, JSONField, Serializer, UUIDField from rest_framework.viewsets import GenericViewSet @@ -33,6 +33,7 @@ ) from care.users.models import User from care.utils.assetintegration.asset_classes import AssetClasses +from care.utils.assetintegration.base import BaseAssetIntegration from care.utils.cache.cache_allowed_facilities import get_accessible_facilities from care.utils.filters.choicefilter import CareChoiceFilter, inverse_choices from care.utils.queryset.asset_location import get_asset_location_queryset @@ -166,7 +167,6 @@ def set_default_user_location(self, request, *args, **kwargs): # Dummy Serializer for Operate Asset class DummyAssetOperateSerializer(Serializer): - asset_id = UUIDField(required=True) action = JSONField(required=True) class DummyAssetOperateResponseSerializer(Serializer): @@ -184,18 +184,19 @@ def operate_assets(self, request, *args, **kwargs): This API is used to operate assets. API accepts the asset_id and action as parameters. """ try: - if "asset_id" not in request.data: - raise ValidationError({"asset_id": "is required"}) if "action" not in request.data: raise ValidationError({"action": "is required"}) - asset_id = request.data["asset_id"] action = request.data["action"] + if "type" not in action: + raise ValidationError({"type": "missing action type"}) asset: Asset = self.get_object() - result = AssetClasses(asset.asset_class).handle_action(action) + asset_class: BaseAssetIntegration = AssetClasses[asset.asset_class].value(asset.meta) + result = asset_class.handle_action(action) return Response({"result": result}, status=status.HTTP_200_OK) except ValidationError as e: return Response({"message": e.detail}, status=status.HTTP_400_BAD_REQUEST) except Exception as e: + print(f"error: {e}") return Response( {"message": "Internal Server Error"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR, diff --git a/care/utils/assetintegration/base.py b/care/utils/assetintegration/base.py index 150552e45d..5295c707b4 100644 --- a/care/utils/assetintegration/base.py +++ b/care/utils/assetintegration/base.py @@ -1,13 +1,30 @@ -import enum +import json +import requests class BaseAssetIntegration: - def __init__(self, type, meta): - self.type = type + def __init__(self, meta): self.meta = meta - - def get_type(self): - return self.type + self.host = self.meta["local_ip_address"] + self.middleware_hostname = self.meta["middleware_hostname"] def handle_action(self, action): pass + + def get_url(self, endpoint): + return "http://{}/{}".format(self.middleware_hostname, endpoint) + + def api_post(self, url, data=None): + req = requests.post(url, json=data) + try: + return req.json() + except json.decoder.JSONDecodeError: + return {"error": "Invalid Response"} + + def api_get(self, url, data=None): + req = requests.get(url, params=data) + try: + return req.json() + except Exception as e: + return {"error": "Invalid Response"} + diff --git a/care/utils/assetintegration/hl7monitor.py b/care/utils/assetintegration/hl7monitor.py index 6e1a20127e..13b129ec4e 100644 --- a/care/utils/assetintegration/hl7monitor.py +++ b/care/utils/assetintegration/hl7monitor.py @@ -1,4 +1,6 @@ -import json +import enum + +from rest_framework.exceptions import ValidationError from care.utils.assetintegration.base import BaseAssetIntegration @@ -6,15 +8,16 @@ class HL7MonitorAsset(BaseAssetIntegration): _name = "hl7monitor" + class HL7MonitorActions(enum.Enum): + GET_VITALS = "get_vitals" + def __init__(self, meta): - try: - self.meta = json.loads(meta) - self.meta = meta - self.host = meta["local_ip_address"] - self.username = meta["camera_access_key"].split(":")[0] - self.password = meta["access_credentials"].split(":")[1] - except KeyError: - print("Error: Invalid HL7Monitor Asset; Missing required fields") + super().__init__(meta) def handle_action(self, action): - pass + if action["type"] == self.HL7MonitorActions.GET_VITALS.value: + request_params = { "device_id": self.host } + return self.api_get(self.get_url("vitals"), data=request_params) + else: + raise ValidationError({"action": "invalid action type"}) + diff --git a/care/utils/assetintegration/onvif.py b/care/utils/assetintegration/onvif.py index d2e1137313..d6028b2f47 100644 --- a/care/utils/assetintegration/onvif.py +++ b/care/utils/assetintegration/onvif.py @@ -1,6 +1,6 @@ import enum -import json -from urllib import request + +from rest_framework.exceptions import ValidationError from care.utils.assetintegration.base import BaseAssetIntegration @@ -13,37 +13,14 @@ class OnvifActions(enum.Enum): GOTO_PRESET = "goto_preset" def __init__(self, meta): - try: - self.meta = json.loads(meta) - self.meta = meta - self.name = meta["camera_type"] - self.host = meta["local_ip_address"] - self.port = meta["camera_port"] or 80 - self.username = meta["camera_access_key"].split(":")[0] - self.password = meta["access_credentials"].split(":")[1] - self.middleware_hostname = meta["middleware_hostname"] - except KeyError: - print("Error: Invalid Onvif Asset; Missing required fields") - - def get_url(self, endpoint): - return "http://{}{}".format(self.middleware_hostname, endpoint) - - def api_post(self, url, data=None): - req = request.post(url, json=data) - try: - return req.json() - except json.decoder.JSONDecodeError: - return {"error": "Invalid Response"} - - def api_get(self, url, data=None): - req = request.get(url, data=data) - try: - return req.json() - except json.decoder.JSONDecodeError: - return {"error": "Invalid Response"} + super().__init__(meta) + self.name = self.meta["camera_type"] + self.port = self.meta["camera_port"] or 80 + self.username = self.meta["camera_access_key"].split(":")[0] + self.password = self.meta["access_credentials"].split(":")[1] def handle_action(self, action): - if action.type == self.OnvifActions.MOVE_ABSOLUTE.value: + if action["type"] == self.OnvifActions.MOVE_ABSOLUTE.value: # Make API Call for action request_data = { "x": action.data["x"], @@ -54,15 +31,15 @@ def handle_action(self, action): } return self.api_post(self.get_url("absoluteMove"), data=request_data) - elif action.type == self.OnvifActions.GOTO_PRESET.value: + elif action["type"] == self.OnvifActions.GOTO_PRESET.value: # Make API Call for action request_data = { "preset": action.preset, "meta": self.meta, } return self.api_post(self.get_url("gotoPreset"), data=request_data) - elif action.type == self.OnvifActions.GOTO_PRESET.value: + elif action["type"] == self.OnvifActions.GOTO_PRESET.value: # Make API Call for action return self.api_get(self.get_url("status"), data={}) else: - raise Exception("Invalid action") + raise ValidationError({"action": "invalid action type"})