Skip to content

Commit

Permalink
add new asset actions and clenup asset_monitor task (#2411)
Browse files Browse the repository at this point in the history
Co-authored-by: Vignesh Hari <[email protected]>
  • Loading branch information
sainak and vigneshhari authored Aug 30, 2024
1 parent 92f717e commit 66cdc38
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 20 deletions.
1 change: 1 addition & 0 deletions care/facility/api/viewsets/asset.py
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,7 @@ def operate_assets(self, request, *args, **kwargs):
asset_class: BaseAssetIntegration = AssetClasses[asset.asset_class].value(
{
**asset.meta,
"id": asset.external_id,
"middleware_hostname": middleware_hostname,
}
)
Expand Down
53 changes: 37 additions & 16 deletions care/facility/tasks/asset_monitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from celery import shared_task
from django.contrib.contenttypes.models import ContentType
from django.db.models import Q
from django.utils import timezone

from care.facility.models.asset import Asset, AvailabilityRecord, AvailabilityStatus
Expand All @@ -17,12 +18,25 @@
def check_asset_status():
logger.info(f"Checking Asset Status: {timezone.now()}")

assets = Asset.objects.all()
assets = (
Asset.objects.exclude(Q(asset_class=None) | Q(asset_class=""))
.select_related(
"current_location",
"current_location__facility",
)
.only(
"external_id",
"meta",
"asset_class",
"current_location__middleware_address",
"current_location__facility__middleware_address",
)
)
asset_content_type = ContentType.objects.get_for_model(Asset)

for asset in assets:
# Skipping if asset class or local IP address is not present
if not asset.asset_class or not asset.meta.get("local_ip_address", None):
# Skipping if local IP address is not present
if not asset.meta.get("local_ip_address", None):
continue
try:
# Fetching middleware hostname
Expand All @@ -49,24 +63,31 @@ def check_asset_status():
].value(
{
**asset.meta,
"id": asset.external_id,
"middleware_hostname": resolved_middleware,
}
)
# Fetching the status of the device
if asset.asset_class == "ONVIF":
asset_config = asset.meta["camera_access_key"].split(":")
assets_config = [
{
"hostname": asset.meta.get("local_ip_address"),
"port": 80,
"username": asset_config[0],
"password": asset_config[1],
}
]

result = asset_class.api_post(
asset_class.get_url("cameras/status"), data=assets_config
)
try:
# TODO: Remove this block after all assets are migrated to the new middleware
asset_config = asset.meta["camera_access_key"].split(":")
assets_config = [
{
"hostname": asset.meta.get("local_ip_address"),
"port": 80,
"username": asset_config[0],
"password": asset_config[1],
}
]

result = asset_class.api_post(
asset_class.get_url("cameras/status"), data=assets_config
)
except Exception:
result = asset_class.api_get(
asset_class.get_url("cameras/status")
)
else:
result = asset_class.api_get(asset_class.get_url("devices/status"))
except Exception as e:
Expand Down
15 changes: 11 additions & 4 deletions care/utils/assetintegration/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class BaseAssetIntegration:

def __init__(self, meta):
self.meta = meta
self.id = self.meta.get("id", "")
self.host = self.meta["local_ip_address"]
self.middleware_hostname = self.meta["middleware_hostname"]
self.insecure_connection = self.meta.get("insecure_connection", False)
Expand All @@ -25,30 +26,36 @@ def get_url(self, endpoint):
protocol += "s"
return f"{protocol}://{self.middleware_hostname}/{endpoint}"

def get_headers(self):
return {
"Authorization": (self.auth_header_type + generate_jwt()),
"Accept": "application/json",
}

def api_post(self, url, data=None):
req = requests.post(
url,
json=data,
headers={"Authorization": (self.auth_header_type + generate_jwt())},
headers=self.get_headers(),
)
try:
response = req.json()
if req.status_code >= 400:
raise APIException(response, req.status_code)
return response
except json.decoder.JSONDecodeError:
return {"error": "Invalid Response"}
raise APIException({"error": "Invalid Response"}, req.status_code)

def api_get(self, url, data=None):
req = requests.get(
url,
params=data,
headers={"Authorization": (self.auth_header_type + generate_jwt())},
headers=self.get_headers(),
)
try:
if req.status_code >= 400:
raise APIException(req.text, req.status_code)
response = req.json()
return response
except json.decoder.JSONDecodeError:
return {"error": "Invalid Response"}
raise APIException({"error": "Invalid Response"}, req.status_code)
10 changes: 10 additions & 0 deletions care/utils/assetintegration/hl7monitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class HL7MonitorAsset(BaseAssetIntegration):

class HL7MonitorActions(enum.Enum):
GET_VITALS = "get_vitals"
GET_STREAM_TOKEN = "get_stream_token"

def __init__(self, meta):
try:
Expand All @@ -26,4 +27,13 @@ def handle_action(self, action):
request_params = {"device_id": self.host}
return self.api_get(self.get_url("vitals"), request_params)

if action_type == self.HL7MonitorActions.GET_STREAM_TOKEN.value:
return self.api_post(
self.get_url("api/stream/getToken/vitals"),
{
"asset_id": self.id,
"ip": self.host,
},
)

raise ValidationError({"action": "invalid action type"})
9 changes: 9 additions & 0 deletions care/utils/assetintegration/onvif.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class OnvifActions(enum.Enum):
GOTO_PRESET = "goto_preset"
ABSOLUTE_MOVE = "absolute_move"
RELATIVE_MOVE = "relative_move"
GET_STREAM_TOKEN = "get_stream_token"

def __init__(self, meta):
try:
Expand Down Expand Up @@ -54,4 +55,12 @@ def handle_action(self, action):
if action_type == self.OnvifActions.RELATIVE_MOVE.value:
return self.api_post(self.get_url("relativeMove"), request_body)

if action_type == self.OnvifActions.GET_STREAM_TOKEN.value:
return self.api_post(
self.get_url("api/stream/getToken/videoFeed"),
{
"stream_id": self.access_key,
},
)

raise ValidationError({"action": "invalid action type"})
10 changes: 10 additions & 0 deletions care/utils/assetintegration/ventilator.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class VentilatorAsset(BaseAssetIntegration):

class VentilatorActions(enum.Enum):
GET_VITALS = "get_vitals"
GET_STREAM_TOKEN = "get_stream_token"

def __init__(self, meta):
try:
Expand All @@ -26,4 +27,13 @@ def handle_action(self, action):
request_params = {"device_id": self.host}
return self.api_get(self.get_url("vitals"), request_params)

if action_type == self.VentilatorActions.GET_STREAM_TOKEN.value:
return self.api_post(
self.get_url("api/stream/getToken/vitals"),
{
"asset_id": self.id,
"ip": self.host,
},
)

raise ValidationError({"action": "invalid action type"})

0 comments on commit 66cdc38

Please sign in to comment.