{"id":19562,"date":"2023-04-22T15:50:05","date_gmt":"2023-04-22T15:50:05","guid":{"rendered":"http:\/\/13.234.18.93\/?p=19562"},"modified":"2023-05-15T10:50:54","modified_gmt":"2023-05-15T05:20:54","slug":"how-to-build-a-telemedicine-app","status":"publish","type":"post","link":"https:\/\/techvariable.com\/blogs\/how-to-build-a-telemedicine-app","title":{"rendered":"How to Build a Telemedicine App"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\"><strong>Introduction<\/strong><\/h2>\n\n\n\n<p><strong>Telemedicine <\/strong><em><strong>(noun)<\/strong><\/em>: The remote delivery of clinical services in real-time via two-way communication between the healthcare provider and the availer.<\/p>\n\n\n\n<p><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-purple-color\">A telemedicine app is software that typically covers modules such as video conferencing, instant messaging, secured file sharing, and real-time medical consulting to help patients receive quality care irrespective of the time and place. Features incorporated may include appointment scheduling, prescription management, and online medical records.<\/mark><\/p>\n\n\n\n<p>Consequently, a telemedicine app demands data encryption and other security measures to protect patient privacy and confidentiality.&nbsp;<\/p>\n\n\n\n<p>Considering the above features, we can prioritize them and build a POC (Proof Of Concept) to display the application\u2019s working.&nbsp;<\/p>\n\n\n\n<p>Here\u2019s a detailed step-by-step guide to building a telemedicine application. This guide is a walk-through of the telemedicine PoC TechVariable created<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Frontend System for the Telemedicine App<\/h2>\n\n\n\n<p>The frontend part of the telemedicine app has the following sub-systems involved:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>User Interface (UI) and User Experience (UX)<\/li>\n\n\n\n<li>Appointment Scheduling<\/li>\n\n\n\n<li>Video conferencing<\/li>\n\n\n\n<li>Diagnosis\/Prognosis and prescriptions<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">A. User Interface (UI) and User Experience (UX)<\/h3>\n\n\n\n<p><strong>Requirement<\/strong><\/p>\n\n\n\n<p>A well-designed user interface and user experience are critical for a telemedicine app&#8217;s success. Patients and healthcare practitioners should be able to easily use and navigate the user interface (UI) and user experience (UX).&nbsp;<\/p>\n\n\n\n<p><strong>Implementation<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Efficient Design and Easy Navigation<\/strong><\/li>\n<\/ul>\n\n\n\n<p>To achieve this,<mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-purple-color\"> the app&#8217;s design should be intuitive and straightforward, with a clear and concise layout.<\/mark> It should include an easy-to-use navigation mechanism allowing users to access various functionalities rapidly.<\/p>\n\n\n\n<p>For example, the app&#8217;s main menu should be easily accessible and provide users with quick access to essential services like booking appointments, seeing medical information, or initiating a video conference with a healthcare practitioner.<\/p>\n\n\n\n<p>You can utilize a UI library such as <a href=\"https:\/\/mui.com\/\"><u>MUI<\/u><\/a>, <a href=\"https:\/\/ant.design\/\"><u>Ant Design<\/u><\/a>, or others to have a standard to follow. These libraries assist us in maintaining uniform layouts and designs across the program.&nbsp;<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Soothing Visuals<\/strong><\/li>\n<\/ul>\n\n\n\n<p>Selecting a nice color palette is critical because medical practitioners and patients will use this app. Therefore, <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-purple-color\">the colors must be soothing and relaxing<\/mark><strong>.<\/strong> White and grey are <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-purple-color\">neutral hues that exude cleanliness, professionalism, and sophistication.<\/mark><strong> <\/strong>These can be used as backdrop colors or in conjunction with other colors to create a color scheme that is both balanced and harmonious.<\/p>\n\n\n\n<p>You can ensure patients and healthcare professionals communicate successfully and receive the treatment they require by prioritizing app usability and building a user-friendly interface.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">B. Appointment Scheduling<\/h3>\n\n\n\n<p><strong>Requirement<\/strong><\/p>\n\n\n\n<p><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-purple-color\">The appointment scheduling feature should be intuitive and easy for patients.<\/mark> It should provide users with a clear overview of available appointment slots, allowing them to select a time that suits them best. The feature should also confirm the appointment and provide an automated reminder of the upcoming consultation.<\/p>\n\n\n\n<p><strong>Implementation<\/strong><\/p>\n\n\n\n<p>To implement this feature, <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-purple-color\">you must design a backend system allowing healthcare providers to manage their schedules and appointment slots.<\/mark> The system should be updated in real-time to ensure patients can only book available slots.&nbsp;<\/p>\n\n\n\n<p>Things to consider when building the appointment scheduling system.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Ability to handle different time zones.<\/li>\n\n\n\n<li>Ability to cancel or reschedule their appointments.<\/li>\n\n\n\n<li>Integration of payment gateway (optional).<\/li>\n\n\n\n<li>Real-time confirmation of the scheduled appointments.<\/li>\n<\/ul>\n\n\n\n<p>A simple architectural overview of the appointment scheduling system.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">C. Video Conferencing<\/h3>\n\n\n\n<p><strong>Requirement<\/strong><\/p>\n\n\n\n<p>Video conferencing allows patients and healthcare providers to communicate in real-time regardless of location. The video conferencing option should be simple to use, dependable, and delivers high-quality audio and video for a smooth consultation experience.&nbsp;<\/p>\n\n\n\n<p><strong>Implementation<\/strong><\/p>\n\n\n\n<p>Communication is to be done through secure channels for video conferencing. This is when WebRTC comes into play.<\/p>\n\n\n\n<p>The WebRTC technology allows for peer-to-peer audio, video, and data communication between web browsers and mobile apps without additional plugins or downloads. All major web browsers, including Google Chrome, Mozilla Firefox, Apple Safari, Microsoft Edge, and mobile platforms such as iOS and Android, support WebRTC.<\/p>\n\n\n\n<p>The WebRTC configuration is simple. In this scenario, you need to merely link the two peers &#8211; the patient and the consultant &#8211; so that they may share data.&nbsp;<\/p>\n\n\n\n<p><strong>But how do you achieve that?&nbsp;<\/strong><\/p>\n\n\n\n<p>Below are the steps you can follow.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Choosing a signaling server<\/strong><\/li>\n<\/ul>\n\n\n\n<p>A signaling server is responsible for exchanging Offers and Answers generated by WebRTC, which both the peers have to set in their Local Description. It is also known as SDP (Session Description).<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const signalingServerUrl = \"ws:\/\/example.com:9000\"; \/\/ can be any socket server\nconst signaling = new WebSocket(signalingServerUrl);<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Setting up media streams from the clients<\/strong><\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>const mediaStream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });\nconst localVideoElement = document.querySelector(\"#localVideo\");\nlocalVideoElement.srcObject = mediaStream;<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Creating a WebRTC peer connection&nbsp;<\/strong><\/li>\n<\/ul>\n\n\n\n<p>This peer connection requires STUN and TURN servers. The \u2018RTCPeerConnection()\u2019 is provided by the browser APIs.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const configuration = { iceServers: &#91; { urls: \"stun:stun.example.com\" } ] }; \/\/ here goes the URLs of the stun servers\nconst peerConnection = new RTCPeerConnection(configuration);<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Generating an offer<\/strong><\/li>\n<\/ul>\n\n\n\n<p>Now you generate an offer from the side that had already initiated the video or audio call and we set that offer into our local description.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const offer = await peerConnection.createOffer();\nawait peerConnection.setLocalDescription(offer);\nsignaling.send(JSON.stringify({ type: \"offer\", sdp: offer })); \/\/ here we use the socket to send the offer to the other peer<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Post the offer received<\/strong><\/li>\n<\/ul>\n\n\n\n<p>You need to check if the message you are getting is of the type of offer. If it is, then you need to generate an answer and set the offer that you receive as the remote description.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>signaling.addEventListener(\"message\", async event =&gt; {\n  const message = JSON.parse(event.data);\n  if (message.type === \"offer\") {\nawait peerConnection.setRemoteDescription(message.sdp);\nconst answer = await peerConnection.createAnswer();\nawait peerConnection.setLocalDescription(answer);\nsignaling.send(JSON.stringify({ type: \"answer\", sdp: answer }));\n  } else if (message.type === \"answer\") {\nawait peerConnection.setRemoteDescription(message.sdp);\n  } else if (message.type === \"candidate\") {\nconst candidate = new RTCIceCandidate(message.candidate);\nawait peerConnection.addIceCandidate(candidate);\n  }\n});<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Adding listeners and setting video element<\/strong><\/li>\n<\/ul>\n\n\n\n<p>Finally, you can add listeners to the peerConnection object when the other peer adds their video and audio stream and when the ICE Candidates are generated. When you get the remote stream, you need to set that to the remote video element.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>peerConnection.addEventListener(\"icecandidate\", event =&gt; {\n  if (event.candidate) {\nsignaling.send(JSON.stringify({ type: \"candidate\", candidate: event.candidate }));\n  }\n});\npeerConnection.addEventListener(\"addstream\", event =&gt; {\n  const remoteVideoElement = document.querySelector(\"#remoteVideo\");\n  remoteVideoElement.srcObject = event.stream;\n});<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">D. Diagnosis\/Prognosis and prescriptions<\/h3>\n\n\n\n<p>While on a video conference, the doctor must be able to add the patient\u2019s diagnosis and suggest medications, lab tests, etc. The system for storing and retrieving this information should be fluent and easy to understand.&nbsp;<\/p>\n\n\n\n<p>Also, in cases where the doctor was unable to provide a diagnosis or prescriptions, the application must provide the ability to prompt the doctor or the consultant to add those later after the meeting.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Backend systems for Telemedicine app<\/h2>\n\n\n\n<p>Decoupling frontend and backend systems are necessary to develop them separately by individual developers. The backend is developed with the developers&#8217; individual expertise and the application of different scalability solutions whenever necessary.<\/p>\n\n\n\n<p>The backend part of the telemedicine app has many different sub-systems-<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Django REST server<\/li>\n\n\n\n<li>Django Signalling server.<\/li>\n\n\n\n<li>RDBMS.<\/li>\n\n\n\n<li>Kubernetes Cluster.<\/li>\n\n\n\n<li>EHR system.<\/li>\n<\/ul>\n\n\n\n<p>Below is a diagram of the overall flow of the system.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img decoding=\"async\" src=\"http:\/\/13.234.18.93\/wp-content\/uploads\/2023\/04\/image-41.png\" alt=\"\" class=\"wp-image-19565\"\/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">A. Django REST Server<\/h3>\n\n\n\n<p>Django is a beautiful framework for developing web server applications using Python. The libraries provided by Django and by the community are very helpful for developing web server applications faster and safer. We have used the Django Rest Framework library and Django to build our REST server.<\/p>\n\n\n\n<p>This server is the root point for accessing the backend by the frontend system. The purpose of this REST server is to serve as a user management system for hospital admins, patients, and doctors and to serve different operations such as meeting schedules, lab reports inventory, prescriptions, etc.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">B. Django Signalling Server<\/h3>\n\n\n\n<p>When two devices want to communicate directly, they must share their communication address with each other. This is what a Signalling server helps to do. <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-purple-color\">The signaling server is just a WebSocket server where two devices connect and share information through a channel layer.&nbsp;<\/mark><\/p>\n\n\n\n<p><strong>But why should the devices share their device communication addresses when connected through this signaling server?&nbsp;<\/strong><\/p>\n\n\n\n<p>The answer is for privacy reasons, you will not prefer sharing data through a server. You must communicate directly with each other. This is called P2P communication.&nbsp;<\/p>\n\n\n\n<p><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-purple-color\">P2P communication is the WebRTC technique where video calling is directly done without using a central server most of the time.\u00a0<\/mark><\/p>\n\n\n\n<p><strong>The question is why is WebRTC used most of the time?<\/strong><\/p>\n\n\n\n<p>Sometimes it\u2019s impossible to establish a direct connection between two devices over the Internet because some routers are not that friendly. However, using a relay server as a fallback communication channel can solve the problem.&nbsp;<\/p>\n\n\n\n<p>This guide will help you get deep into our workflow. You will be able to have a proper idea of the purpose of the relay server and the <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-purple-color\">Kubernetes Cluster system.<\/mark><\/p>\n\n\n\n<p>So, back to the point, the signaling server is the first step for two devices for WebRTC communication establishment. Once the direct communication gets established, both can be disconnected from our signaling server.<\/p>\n\n\n\n<p><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-purple-color\">Previously, there has been a mention of the term \u201cChannel Layer.\u201d Let\u2019s understand what it is.<\/mark><\/p>\n\n\n\n<p>When two devices are connected to a WebSocket server, their connections are isolated, i.e. they both can send or receive data only from the WebSocket server. But if device A wants to send a message to device B, then the WebSocket server must find a way to interchange their messages.&nbsp;<\/p>\n\n\n\n<p>This is where the Channel Layer helps. The channel layer is like a sharing tunnel for multiple WebSocket connections.&nbsp;<\/p>\n\n\n\n<p><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-purple-color\">In our case, we have used Redis for our channel layer. So, the WebSocket server communicated with the Redis channel layer.<\/mark><\/p>\n\n\n\n<p>We have also used the Django Channel library for building WebSocket applications in Django. This is a separate server from our REST server.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">C. Relational Database Management System (RDBMS)&nbsp;<\/h3>\n\n\n\n<p>This database server retrieves and stores user information: medicine, surgery, diseases, and allergies datasets. Any healthcare application working on the patient front needs the integration of EHR systems. However, despite that, there is also a need for a database.&nbsp;<\/p>\n\n\n\n<p><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-purple-color\">RDBMS has a strict schema to use, and our Django framework is very easy and helpful to integrate an RDBMS.\u00a0<\/mark><\/p>\n\n\n\n<p>Django ORM is the most popular ORM (object-relational mapper) available today. With the power of Django Framework and Django REST Framework library, you can build many features into your main service.<\/p>\n\n\n\n<p>We have integrated our RDBMS to search drugs, surgery names, diseases, and allergies data. The data was collected off the internet and fed into the database.&nbsp;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">D. Kubernetes Cluster<\/h3>\n\n\n\n<p>As mentioned earlier you need a relay server as a fallback communication for WebRTC whenever direct device-to-device communication is impossible.&nbsp;<\/p>\n\n\n\n<p><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-purple-color\">Remember what we talked about earlier, i.e. sharing communication addresses for two devices to establish the WebRTC connection?<\/mark><\/p>\n\n\n\n<p>The technical term for the address is called ICE Candidate. These ICE candidates are generated using the STUN and the TURN servers. In the Internet world, communications happen using IP addresses and ports. But not all IP addresses are accessible.&nbsp;<\/p>\n\n\n\n<p>Each device connected to the Internet gets two IP addresses, Private and Public IP. Each IP address has a coverage area. Thus, there\u2019s a certain area for Private IP, outside which the device can\u2019t be accessed using its Private IP by other devices. But the coverage area for the public is global.&nbsp;<\/p>\n\n\n\n<p><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-purple-color\">That means we need the public IP for a device so we can communicate with it from anywhere in the world. This is where the STUN server helps.<\/mark><strong>\u00a0<\/strong><\/p>\n\n\n\n<p><em>The job of the STUN server is to tell the public IP of the device and the Public Port for the application inside the device requesting to the STUN server.<\/em> In our case, the WebRTC application is the application asking STUN to know its public IP and public PORT.&nbsp;<\/p>\n\n\n\n<p>Again, as we discussed earlier, if a direct connection is not possible between two devices with their public IP and port, then the devices have to set up their relay connection, which is the TURN server\u2019s job.&nbsp;<\/p>\n\n\n\n<p>In our case, the TURN server is responsible for setting up the relay connection with the application, i.e. the WebRTC application.&nbsp;<\/p>\n\n\n\n<p><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-purple-color\">Here\u2019s the STUN and TURN server configuration for a WebRTC application for compiling its ICE Candidate.<\/mark><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>iceServers: &#91;\n    {\n        urls: &#91;\n            'stun:stun.l.google.com:19302',\n        ],\n    },\n    {\n        urls: 'turn:1xx.18.0.3:3xx01',\n        credential: 'password',\n        username: 'username',\n    }\n],<\/code><\/pre>\n\n\n\n<p>We can add multiple stun and turn servers in the configuration.<\/p>\n\n\n\n<p><strong>How do all these relate to a Kubernetes cluster?<\/strong><\/p>\n\n\n\n<p>The TURN server is for relay purposes. And each relay server has some capacity, exceeding which will lead to a bad video-calling experience. Imagine a single relay server that can handle 500 connections at a time. Now if you have less number of video-calling users, then there is no problem.&nbsp;<\/p>\n\n\n\n<p><strong>But what if 1000 WebRTC applications are asking for relay connections?&nbsp;<\/strong><\/p>\n\n\n\n<p>The relay server will then ignore the extra connections. You don\u2019t want this to happen. For that, you need a scalable TURN server.&nbsp;<\/p>\n\n\n\n<p>The idea is that you will spin multiple TURN server instances and use a load balancer for them.&nbsp; Additionally, enabling auto-scaling features is advisable for when there are more requests, and a new TURN server has to be added. This is to maintain minimum costs for the servers.&nbsp;<\/p>\n\n\n\n<p>To build and deploy such a system, there are many cloud services <strong>AWS, GCP, Azure<\/strong>, etc. <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-purple-color\">But, we want our plans not to be independent of a specific cloud platform and to get better autonomy over the TURN Server cluster, hence, we have chosen Kubernetes.<\/mark><\/p>\n\n\n\n<p><strong>Steps we followed to deploy TURN Server using Kubernetes Cluster in AWS:<\/strong><\/p>\n\n\n\n<p>1. We reached our AWS DevOps person to create an AWS user account with the IAM policies listed in <a href=\"https:\/\/eksctl.io\/usage\/minimum-iam-policies\/\">https:\/\/eksctl.io\/usage\/minimum-iam-policies\/<\/a><\/p>\n\n\n\n<p>2. We configured our AWS credentials in ~\/.aws\/credentials like below.&nbsp;<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;telehealth]\n\naws_access_key_id=AKIAXRVxxxxxxxxxxxxx\n\naws_secret_access_key=6VpV+x3p8xxxxxxxxxxxxxxxxxxxxxQ2atHzOh<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Set the default AWS profile and some config before creating the cluster.<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>export AWS_DEFAULT_PROFILE=telehealth\nexport KUBE_AWS_ZONE=ap-south-1b\nexport NUM_NODES=2\nexport MASTER_SIZE=t2.micro\nexport NODE_SIZE=t2.micro\nexport AWS_S3_REGION=ap-south-1\nexport INSTANCE_PREFIX=k8s<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Install the eksctl tool.<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>curl --silent --location \"https:\/\/github.com\/weaveworks\/eksctl\/releases\/latest\/download\/eksctl_$(uname -s)_amd64.tar.gz\" | tar xz -C \/tmp\nsudo mv \/tmp\/eksctl \/usr\/local\/bin<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Create a cluster.yml file.<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>apiVersion: eksctl.io\/v1alpha5\nkind: ClusterConfig\n\nmetadata:\n  name: basic-cluster\n  region: ap-south-1\n\nnodeGroups:\n  - name: ng-1\ninstanceType: t2.micro\ndesiredCapacity: 2<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Deploy the cluster in AWS EKS.<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>eksctl create cluster -f cluster.yaml<\/code><\/pre>\n\n\n\n<p>3. Check the Kubernetes cluster config in ~\/.kube\/config. This will display information like below.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>apiVersion: v1\nclusters:\n- cluster:\ncertificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMvakNDQWVhZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJek1ESXdOekExTkRRMU4xb1hEVE16TURJd05EQTFORFExTjFvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWR0lramN5NEE3TXo5U1RrRHpVb3JTNW0vMURZTjk4L1dVZFlxxxxxxxxxxxxxxxxxxxxxxxxxxdnRUJBSDhDd3h2bmxVU3RXWDViQ2d5VgpRWldXdmUyTmg2UzRZS1RIOUZ2eFQwOEJvc2hLWTlWQnZpLzlMdXpNWk5oWHNZVllSdVpXZXovZk82OFZNbEVsCkRGWmpnam8yMnI1RCtBdGdUV29FUFZaVzFjWm1CYS9KZWZsOXJOb1ExWnZ2Z1RQR0tIRHVqeXJYOFk2OFFpVzEKZXdFS3Mwc2k3MHlienB0Z29iM3FwWWphVitwV1Zna2owMnVTNW8vZisvNGhjOHgrZm5qV0srRVUvZnVrbTI2VQpmT2d3eE5zMlhiRURxenI4ZzBpRE9lUkNvUldNVEtLNzVpNHhCWFhka3dTNzQ2cXBUQnBLNlI2d3YvekxGb3lrCkFxczBEeDUxUUR0TGFNN29saUFVazZ3a0MyVGVXNlpmWjJ3NUMxakVoYWRqVTFYNi9tdEdSQ3R4OVgvNHBBS2kKdDdrPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==\nserver: https:\/\/8EAB6CF483xxxxxx1.gr7.ap-south-1.eks.amazonaws.com\n  name: basic-cluster.ap-south-1.eksctl.io\n- cluster:\ncertificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMvakNDQWVhZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJek1ERXpNVEV3TXpnek1sb1hEVE16TURFeU9ERXdNemd6TWxvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGURS0tLS0tCg==\nserver: https:\/\/127.0.0.1:35539\n  name: kind-kind\ncontexts:\n- context:\ncluster: basic-cluster.ap-south-1.eksctl.io\nuser: xxxxxx@basic-cluster.ap-south-1.eksctl.io\n  name: xxxxxx@basic-cluster.ap-south-1.eksctl.io\n- context:\ncluster: kind-kind\nuser: kind-kind\n  name: kind-kind\ncurrent-context: bxxxxxx@basic-cluster.ap-south-1.eksctl.io\nkind: Config\npreferences: {}\nusers:\n- name: xxxxxx@basic-cluster.ap-south-1.eksctl.io\n  user:\nexec:\n  apiVersion: client.authentication.k8s.io\/v1beta1\n  args:\n  - eks\n  - get-token\n  - --cluster-name\n  - basic-cluster\n  - --region\n  - ap-south-1\n  command: aws\n  env:\n  - name: AWS_STS_REGIONAL_ENDPOINTS\n    value: regional\n  provideClusterInfo: false\n- name: kind-kind\n  user:\nclient-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURJVENDQWdtZ0F3SUJBZ0lJQ2VOUmJSOWdrd3d3RFFZSktvWklodmNOQVFFTEJRQXdGVEVUTUJFR0ExVUUKQXhNS2EzVmlaWEp1WlhSbGN6QWVGdzB5TXpBeE16RXhNRE00TXpKYUZ3MHlOREF4TXpFeE1ETTRNelJhTURReApGekFWQmdOVkJBb1REbk41YzNSbGJUcHRZWE4wWlhKek1Sa32c5MDU3U0dMdE9Xc0EKaWoxN3BPV2dmTzduVXkxek01OUticTVsVU9xRk8wYVlTV0xWaUc2R040K3E2M1Nlc0lvbUlGMXJRRnNQbXFlUQpVU1ovVDVuMStrWXY4Vk1kbGxURmMwTVpaZ0VVa3piYzdxxxxxxxxxxxxxxxxxxxxxxxxxxdBYjAvV0VxLzZNNy9aRnZ3TDlVawpYVEFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBenk5czFkem5vVVNRbzJIWFJVdTFndC9VT0VUNnMrQUFYZUFzCkFZRVJ4cHZWcU5KNUtSQ0VOYkpsa2xPbGo0eFZ6RURXdVUzY2w2WHNPTlUrQ1QyaTJMOVQ3NExCcnhraE44b2IKeUlJN2hmalY5b29LdGVOUGhhNHBYbG1YcHJCQ2NRcVpHWWlONzFuVXRiR0NKODN6ckltY0VUWEZNTFpWQjQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==\nclient-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSU0E2T003R1ljeHZBb0dBTWt6TXFpMHJRYVdTaU5qbUo4eDAKWWIvSVlTSU1UNjZCRzJWcCt2bmo0VTlYR08wTnZOaDI3Tnd0TklwR0xOVDZKZVZpZUZScWYvamJicVVvc01VcwpuS1lqK2N5Q0pqRmJHVllaeEtyUlBaVzgxc3VMYUl4dlN1ZVBSNnRhbXRjbVQ2MHQzR0pHSXRIU0RoU0VHcWdqCnZBSFA4NkVaY1I4T0F0YXFMS1RrdS9FQ2dZRUFuaU5kZG1uWXBFeXd2WTZaQVBQdERlMGUycm1LMHZOQ3hOVnQKdC91aFp6M0NQblpyNVJIUmpUMDRWSk11L0I5bmZCbndDMmRpNEwrbkdTZjFNSzQ0TVZZNmM0bXRCQkZNVS9keAptNEMzQnYzVHpjT1UzQ2Y4Mkg3a2EvYVJPWGI5blJKRDQ3dVkwR0VXUTVscXE3Rk01cVE4aE5iZU4vbitXY3B3CmZQN3BxT01DZ1lCWVVzSlYydG1BVjVvSlJXbE9Nc0k5bFZzemJwZ1UrSW9DNk52LzNsTCtCQ2tvNUFaUDJBeWsKelEzMjQyYXNTUVFSc3RpSFp1Rm9Ka0xuSmJiY0hieVgwM1NFU1cvbkdmVHRzWDRaQmtQak0vTmo3djVEdHkxMApvSExHbDc5Z2VqcnFkRXprSDVqSmNsWHArRFZmTjhVR29pSko2T0UyTmtyNzNkRktDdWVZWEE9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo=<\/code><\/pre>\n\n\n\n<p>4. Create a TURN server deployment file turnserver_deployment.yml.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>apiVersion: apps\/v1\nkind: Deployment\nmetadata:\n  name: turnserver-deployment\n  labels:\napp: turnserver\nspec:\n  replicas: 3\n  selector:\nmatchLabels:\n  app: turnserver\n  template:\nmetadata:\n  name: turnserver\n  namespace: default\n  labels:\n    app: turnserver\nspec:\n  containers:\n  - name: turnserver\n    image: instrumentisto\/coturn\n    args: &#91;\"-a\",\"-v\",\"-n\",\"-u\",\"turn_username:turn_password\",\"-p\",\"3478\",\"-r\",\"someRealm\",\"--no-dtls\",\"--no-tls\"]<\/code><\/pre>\n\n\n\n<p>5. Deploy the turnserver_deployment.yml file.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl create -f turnserver_deployment.yaml<\/code><\/pre>\n\n\n\n<p>6. Create a turnserver_loadbalancer_service.yml file.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>apiVersion: v1\nkind: Service\nmetadata:\n  name: turnserver\n  annotations:\nservice.beta.kubernetes.io\/aws-load-balancer-type: nlb\nservice.beta.kubernetes.io\/aws-load-balancer-nlb-target-type: \"ip\"\nservice.beta.kubernetes.io\/aws-load-balancer-healthcheck-port: \"80\"\nservice.beta.kubernetes.io\/aws-load-balancer-healthcheck-protocol: TCP\nservice.beta.kubernetes.io\/aws-load-balancer-scheme: internet-facing\n  labels:\nname: turnserver\nspec:\n  type: LoadBalancer\n  ports:\n- name: udp\n  protocol: UDP\n  port: 3478 #loadbalancer port\n  targetPort: 3478 #Pod port\n  selector:\napp: turnserver<\/code><\/pre>\n\n\n\n<p>7. Deploy turnserver_loadbalancer_service.yml file.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl create -f turnserver_loadbalancer_service.yaml<\/code><\/pre>\n\n\n\n<p>8. You can now use the kubectl command to communicate with our turn server cluster.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl get services<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">E. Electronic Health Record (EHR) Integration<\/h3>\n\n\n\n<p>We could have used our RDBMS to store meeting details, doctors\u2019 details, patients\u2019 medications data, lab reports, etc. But then, our backend system would not be compatible with the Healthcare Interoperability framework.<\/p>\n\n\n\n<p>Hence, as mentioned earlier, we use EHR systems.<strong> <\/strong><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-purple-color\">Hospitals use EHR systems. Some popular EHR technologies are Epic, Oracle Cerner, Allscripts, etc. And they are made to be supported by different Interfaces like HL7 v2.x and hl7 v3.x, FHIR, X12 etc.&nbsp;<\/mark><\/p>\n\n\n\n<p>Similarly, you can use one of many interfaces provided by EHR. One of the most popular interfaces is FHIR. FHIR interface supports many resources, and they are served as REST endpoints.<\/p>\n\n\n\n<p><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-purple-color\">The Logica sandbox is the best way to start with an EHR FHIR endpoint. You have to make an app in the EHR system to use the REST endpoints provided by the EHR.\u00a0<\/mark><\/p>\n\n\n\n<p>There are three types of apps supported by the EHR system.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Patient-facing app<\/strong>: To use FHIR endpoints with this app, the client application goes through an OAuth flow which needs consent from a patient, and the patient must have an account in the EHR system.<\/li>\n\n\n\n<li><strong>Provider-facing app<\/strong>: Same as Patient facing app, the Provider goes through the OAuth sign-in flow.<\/li>\n\n\n\n<li><strong>Backend system app<\/strong>: Using this type of app, the client program does not need any OAuth flow and can use the FHIR endpoint without user interactions.<\/li>\n<\/ul>\n\n\n\n<p>The Backend system app is perfect based on our requirements.&nbsp;<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How can we utilize FHIR resources for our purpose?<\/h2>\n\n\n\n<p>If you visit <a href=\"http:\/\/hl7.org\/fhir\/R4\/resourcelist.html\">http:\/\/hl7.org\/fhir\/R4\/resourcelist.html<\/a>, you will find many FHIR resources along with their documentation. Some valuable resources include:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\/Patient <\/strong>&#8211; This resource contains patient information such as demographics, contact information, and identifiers. It displays the patient\u2019s report to the healthcare professional and updates the patient\u2019s data after a virtual visit.<\/li>\n\n\n\n<li><strong>\/Coverage<\/strong> &#8211; This resource details the patient\u2019s coverage, such as the insurer, plan, and policy. It verifies and submits virtual visit claims.<\/li>\n\n\n\n<li><strong>\/Condition<\/strong> &#8211; This resource details the patient\u2019s medical issues, such as diagnoses, symptoms, and onset dates. It provides the patient\u2019s history to the healthcare professional and documents new diagnoses or symptoms following a virtual visit.&nbsp;<\/li>\n\n\n\n<li><strong>\/FamilyMemberHistory<\/strong> &#8211; This resource acquires information about the patient\u2019s family health history, regarding genetically transferred health problems and illnesses, during a virtual visit and updates it as needed.<\/li>\n\n\n\n<li><strong>\/AllergyIntolerance<\/strong> &#8211; This resource offers information regarding the patient\u2019s allergies and intolerances. It displays the information to the healthcare professional and documents new allergies or intolerances following a virtual visit.<\/li>\n\n\n\n<li><strong>\/MedicationStatement <\/strong>&#8211; This resource details the patient\u2019s medication history, such as medication names, dosages, and administration schedules,&nbsp; and updates it after a virtual visit.<\/li>\n\n\n\n<li><strong>\/Procedure<\/strong> &#8211; This resource offers information regarding patient surgical, diagnostic, and therapeutic procedures during a virtual visit and updates the patient\u2019s history as needed.<\/li>\n\n\n\n<li><strong>\/CoverageEligibility<\/strong> &#8211; This resource details the patient\u2019s healthcare coverage, such as coverage type, plan, and service codes. It validates the patient\u2019s data for virtual visits and calculates their cost-sharing obligation.<\/li>\n\n\n\n<li><strong>\/CoverageEligibilityRequest <\/strong>&#8211; This resource requests information regarding the patient\u2019s eligibility for care coverage. It submits requests for coverage eligibility necessary for virtual visits.<\/li>\n\n\n\n<li>\/<strong>Appointment<\/strong> &#8211; This resource contains information about the patient\u2019s scheduled appointments, including the date, time, and location. It organizes and displays the patient\u2019s virtual visits.<\/li>\n\n\n\n<li>\/<strong>MedicationRequest<\/strong> &#8211; This resource is used to request medication orders for the patient during a virtual visit.<\/li>\n\n\n\n<li>\/<strong>DiagnosticReport<\/strong> &#8211; This resource documents information about diagnostic tests performed on the patient, including the test name, results, and interpretation.&nbsp;<\/li>\n\n\n\n<li>\/<strong>DocumentReference<\/strong> &#8211; This resource uploads and accesses patient healthcare-related documents related to virtual visits, including referral letters, medical reports, and clinical notes.<\/li>\n\n\n\n<li>\/<strong>Practitioner<\/strong> &#8211; This resource displays information on healthcare providers, including their names, contact information, and identifiers, to the patient and periodically updates the information.&nbsp;<\/li>\n\n\n\n<li>\/<strong>Encounter<\/strong> &#8211; This resource contains information about a virtual healthcare visit, including the date, time, location, and reason.&nbsp;<\/li>\n\n\n\n<li>\/<strong>Observation<\/strong> &#8211; This resource documents clinical observations performed on the patient, including vital signs, laboratory results, and other clinical measurements.<\/li>\n\n\n\n<li>\/<strong>Slot<\/strong> &#8211; This resource displays available appointment slots, including the appointment&#8217;s date, time, and location.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Compliance with HIPAA (Health Insurance Portability and Accountability Act)<\/h2>\n\n\n\n<p>To protect patient safety and privacy, telemedicine apps must adhere to various regulatory regulations and data privacy legislation. One of the most essential regulatory requirements for telemedicine apps in the United States is the Health Insurance Portability and Accountability Act (HIPAA).&nbsp;<\/p>\n\n\n\n<p><strong>HIPAA establishes standards for protecting sensitive patient health information. Failure to comply can lead to severe legal and financial ramifications.<\/strong><\/p>\n\n\n\n<p>To comply with HIPAA, you must take numerous steps to protect patient data, including:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Secure Storage:<\/strong> Ensure that all patient data is securely kept on the app\u2019s servers and encrypted.<\/li>\n\n\n\n<li><strong>Access Controls:<\/strong> Implement access controls to guarantee that only authorized personnel can access patient data.<\/li>\n\n\n\n<li><strong>Audit record:<\/strong> Maintain an audit record of all patient data activity, including who accessed it and when.<\/li>\n\n\n\n<li><strong>Data Backup:<\/strong> Back up patient data regularly to guarantee that it can be restored during data loss.<\/li>\n\n\n\n<li><strong>Patient Consent:<\/strong> Obtain patient consent before collecting or distributing data.<\/li>\n\n\n\n<li><strong>Data Retention Policy:<\/strong> Create a data retention policy outlining how long patient data will be kept and when it will be removed.<\/li>\n\n\n\n<li><strong>Regular Security Audits:<\/strong> Conduct regular security audits to discover and remedy app vulnerabilities.<\/li>\n<\/ul>\n\n\n\n<p>It\u2019s also critical to follow state-specific telemedicine regulations, which can differ between states. You should seek legal advice to ensure the app conforms to all applicable rules and regulations in the target states.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p>This detailed guide gives a view of the process of building a successful telemedicine application from scratch. However, just creating and working on the framework isn\u2019t enough. Any healthcare application to be viable for use in the U.S. healthcare field must be highly compliant with the prevalent governing laws.&nbsp;<\/p>\n\n\n\n<p>Compliance with regulatory requirements and data privacy laws is crucial for the success of a telemedicine app. By ensuring patient safety and privacy, you can build trust with patients and healthcare providers and establish your app as a reliable platform for telemedicine services.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction Telemedicine (noun): The remote delivery of clinical services in real-time via two-way communication between the healthcare provider and the availer. A telemedicine app is software that typically covers modules such as video conferencing, instant messaging, secured file sharing, and real-time medical consulting to help patients receive quality care irrespective of the time and place. [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"h5ap_radio_sources":[],"footnotes":""},"categories":[8,9,75],"tags":[],"class_list":["post-19562","post","type-post","status-publish","format-standard","hentry","category-blogs","category-healthcare","category-healthcare-software-feature"],"acf":[],"_links":{"self":[{"href":"https:\/\/techvariable.com\/index.php?rest_route=\/wp\/v2\/posts\/19562","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/techvariable.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/techvariable.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/techvariable.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/techvariable.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=19562"}],"version-history":[{"count":0,"href":"https:\/\/techvariable.com\/index.php?rest_route=\/wp\/v2\/posts\/19562\/revisions"}],"wp:attachment":[{"href":"https:\/\/techvariable.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=19562"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/techvariable.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=19562"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/techvariable.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=19562"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}