Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update HL7Monitor asset integration #877

Merged
merged 4 commits into from
Jun 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions care/facility/api/viewsets/asset.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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):
Expand All @@ -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,
Expand Down
29 changes: 23 additions & 6 deletions care/utils/assetintegration/base.py
Original file line number Diff line number Diff line change
@@ -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"}

23 changes: 13 additions & 10 deletions care/utils/assetintegration/hl7monitor.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
import json
import enum

from rest_framework.exceptions import ValidationError

from care.utils.assetintegration.base import BaseAssetIntegration


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"})

45 changes: 11 additions & 34 deletions care/utils/assetintegration/onvif.py
Original file line number Diff line number Diff line change
@@ -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

Expand All @@ -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"],
Expand All @@ -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"})