Skip to main content
Skip table of contents

Narrowcasting

Dit document beschrijft de integratie voor derde partijen specifiek voor narrowcasting.

 Het bestaat uit de volgende onderdelen:

  • Oproepen
    Het kunnen ontvangen van een oproep vanuit Universe.

  • Spreekuurverloop
    Het kunnen ontvangen van spreekuurverloop van agenda’s.

  • Wachttijden
    Het kunnen ontvangen van wachttijden op basis van inloop.

Deze integratie is beschikbaar vanaf 2023.* of hoger

Dit document beschrijft de koppeling tussen Logis.P en systemen van derden (hierna genoemd ‘leveranciers’) zoals leveranciers van Narrowcasting  of Digital Signage systemen. Met behulp van deze koppeling kan de ontvangende partij de oproepopdrachten op het scherm tonen.

Oproepen

Koppeling

Alle oproepen gegenereerd in het Logis.P systeem worden op de interne messagebus RabbitMQ gezet als een zogeheten CFMCall JSON bericht.

Dit CFMCall bericht ziet er als volgt uit: 

JSON
{
	"QueueID": 1,
	"TicketID": "23",
	"BalieDisplayText": "Ga naar de balie",
	"DisplayPrint": "A015",
	"TerminalID": "TEST"
}

Toegang tot de RabbitMQ messagebus verloopt via onze LogisP.Endpoints.Integration.Hub, waarmee u verbinding kunt maken met behulp van @microsoft/signalr NPM package.

Ter authenticatie worden door Logis.P de volgende gegevens verstrekt:

  • Apikey          = unieke sleutel voor de leverancier

  • TerminalID    = unieke sleutel per narrowcasting device van de leverancier

 Velden

Veld

Omschrijving

QueueID

ID van de wachtrij

TicketID

Technische sleutel (uniek) van de uitgegeven ticket. Indien er aanvullend wordt gecommuniceerd dient dit nummer meegezonden te worden bij het opvragen van gegevens. Normaliter zal dit veld niet worden gebruikt.

 

BalieDisplayText

Textuele beschrijving (wordt normaliter getoond) waar de patient zich moet melden. Bijvoorbeeld de onderzoekskamer of de balie.

DisplayPrint

Het nummer dat op het ticket is afgedrukt. Dit zal normaliter getoond worden.

TerminalID

De ID van het device waarop de oproep getoond moet worden.

Voorbeeld Javascript SignalR connectie

 

Hieronder treft u een HTML pagina met javascript aan, welke het leggen van de verbinding met onze Logisp.Endpoints.Integration.Hub illustreert.

HTML
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>DEMO SIGNALR Logis.P</title>
</head>
<body>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/6.0.1/signalr.js"></script>
    <script>
  // Setup the connection.
        const connection = new signalR.HubConnectionBuilder()            .withUrl("http://localhost:5000/integrationHub?terminalID=TEST&apikey=0a2c1fd4-98a1-4bb4-91a2-4bb54eba063d")
            .configureLogging(signalR.LogLevel.Information)
            .build();

        async function start() {
            try {
                await connection.start();
                console.log("SignalR Connected.");
            } catch (err) {
                console.log(err);
                setTimeout(start, 5000);
            }
        };

        connection.onclose(async () => {
            await start();
        });

        // Start the connection.
        start();

        // Receive the message.
        connection.on('CFMCall', (messageText) => {
//{"QueueID":1,"TicketID":"23","BalieDisplayText":"Ga naar de balie","DisplayPrint":"A015","TerminalID":"TEST"}

            console.log(`${JSON.stringify(messageText)}`);
            const newMessage = document.createElement('li');
            newMessage.appendChild(document.createTextNode(`${JSON.stringify(messageText)}`));
            document.getElementById('messages').appendChild(newMessage);
        });
    </script>
    <div class="signalr-demo">
        <ul id="messages"></ul>
    </div>
</body>
</html>

De terminalID en de apikey worden in dit voorbeeld doorgegeven in de geel gearceerde querystring.

 Voorbeeld C# SignalR connectie

C#
using System;
using System.Threading.Tasks;
using System.Windows;
using LogisP.Contracts.Bus.Kiosk;
using Microsoft.AspNetCore.SignalR.Client;
using Microsoft.AspNetCore.WebUtilities;

namespace LogisP.Endpoints.Integration.ConnectionExample
{
    internal class Program
        {        
        static  void Main(string[] args)            {
                    
            var uri = "http://localhost:5000/integrationHub";

            var queryString = new Dictionary<string, string>
            {
                {"terminalID", "TEST"},
            };

            var uriWithQueryString = QueryHelpers.AddQueryString(uri, 			queryString);
		//setup connection
            HubConnection connection = new HubConnectionBuilder()                
                .WithUrl(uriWithQueryString,   options =>
                {
                    options.Headers.Add("apikey", "0a2c1fd4-98a1-4bb4-91a2-							  4bb54eba063d");                     
                })
                .WithAutomaticReconnect()
                .Build();

             connection.Closed += async (error) =>
            {
                Console.WriteLine($"Connection closed by remote client with 			   error {error?.Message}");
            };
		
            connection.On<CfmCall>("CFMCall", (message) =>
            {
		//Receive message
             //{"QueueID":1,"TicketID":"23","BalieDisplayText":"Ga 			naar:","DisplayPrint":"A015","TerminalID":"TEST"}
            Console.WriteLine($"Received cfmcall with data {message.BalieDisplayText} for terminalID {message.TerminalID}");
                   
            });            

            try
            {
                connection.StartAsync();
                Console.WriteLine($"Connecting to {uri} with connection state 		   {connection.State.ToString()}");

            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error: {ex}");
            }

            Console.ReadKey();  // wait for userinput
 }}}

De terminalID en de apikey worden in dit voorbeeld doorgegeven in de geel gearceerde codeblokken.

Een volledig C# project met bovenstaande voorbeeldcode kan op verzoek verstrekt worden door Logis.P

 Voorbeeld Angular SignalR connectie

 

TYPESCRIPT
import { BehaviorSubject, Observable } from 'rxjs';
import { Injectable } from '@angular/core';
import * as signalR from "@microsoft/signalr"
import { cfmcall } from '../models/cfmcall.model';

@Injectable({
  providedIn: 'root'
})
export class SignalrhubService {
  
  private hubConnection: signalR.HubConnection | undefined
  public cfmCall$:BehaviorSubject<cfmcall|undefined> = new BehaviorSubject<cfmcall|undefined>(undefined);  
  public connectionStatus$:BehaviorSubject<number> = new BehaviorSubject<number>(0);
  public connectionState: number = 0;

  constructor() {
   }

  public startConnection = (terminalID: string, apikey: string) => {
     const self = this;

     // connecting
     this.connectionState = -1;
     this.connectionStatus$.next(-1) 
 
    this.hubConnection = new signalR.HubConnectionBuilder()
                            .withUrl(`http://localhost:5000/integrationHub?terminalID=${terminalID}&apikey=${apikey}` 
                             ,
                             {
                              withCredentials: false,
                              skipNegotiation: true,
                              transport: signalR.HttpTransportType.WebSockets
                            })
                            .withAutomaticReconnect()
                            .build();
    this.hubConnection
      .start( )                  
      .then(() => {
        console.log('Connection started');
        this.connectionState = 1;
        this.connectionStatus$.next(1);
          this.addListeners();
    })    
      .catch(err => {
        console.log('Error while starting connection: ' + err);
        self.connectionStatus$.next(0);
        console.log('Connection stopped');
        self.connectionState = 0;     
      });
      
      this.hubConnection.onclose(function (e) {
        self.connectionStatus$.next(0);
        console.log('Connection stopped');
        self.connectionState = 0;        
      });

      this.hubConnection.onreconnecting(function(e) {
        self.connectionStatus$.next(2);
        console.log('Connection reconnecting');
        self.connectionState = 2;        
      });

      this.hubConnection.onreconnected(function(e) {
        self.connectionStatus$.next(1);
        console.log('Connection onreconnected');
        self.connectionState = 3;        
      });

  }
  
  private addListeners = () => {
    this.hubConnection?.on('CFMCall', (data) => {
     this.cfmCall$.next(data);
      console.log(data);
    });  
  }

  public StopConnection = () => {
      if (this.hubConnection) {
        this.hubConnection.stop().then();
      }
  }
}

 De terminalID en de apikey worden in dit voorbeeld doorgegeven in de grijs gearceerde querystring.

 

Een volledig Angular project met bovenstaande voorbeeldcode kan op verzoek verstrekt worden door Logis.P.

Testomgeving

Logis.P kan op verzoek een testomgeving in de cloud beschikbaar stellen, waarbij om de x minuten een CFMCall bericht op de RabbitMQ messagebus gezet wordt om de SignalR connectie vanuit het client narrowcasting programma te kunnen testen.

Hiertoe worden van tevoren uitgewisseld:

  • Apikey          = unieke sleutel voor de leverancier

  • TerminalID    = unieke sleutel per narrowcasting device van de leverancier

  • URL              = http(s) verbinding met Logisp.Endpoints.Integration.Hub

Spreekuurverloop – uitlooptijden

Logis.P houdt per agenda de uitloop bij indien ingeschakeld. De berekening wordt elke 60 seconden bijgewerkt.

 Belangrijk bij narrowcasting is de juiste agenda’s te tonen bij het juiste scherm. Hiervoor bestaan een aantal methodes:

  • Op basis van afdelingscode in de afdeling

  • Op basis van LocationID in CDR_Schedule object (de afspraak). Dit wordt gevuld vanuit de HL7 koppeling.

  • Op basis van de ExternalID van de wachtrijgroep waarbinnen de wachtrijen vallen die op basis van wachtrij ID in CDR_CustomerflowQueue gekoppeld zijn (Voorwaarde dat de afspraak gekoppeld is aan een ticket)

  • Alle uitloop

 Welke methode gebruikt zal worden moet afgestemd worden binnen het project met de betrokken implementatie consultant.

Koppeling

 De API is een standaard REST API met berichtgeving in JSON formaat. NC leverancier krijgt toestemming om verbinding te maken op basis van een uitgegeven apikey door Logis.P. De apikey moet meegegeven worden in elk bericht in de header "X-ApiKey".

 Alle naamgeving van de API is in het Engels.

 Wij gebruiken de volgende http status codes consistent:

 "200" - alles ok

"400" - bad request (indien documenten verlopen zijn, of sessie niet geldig)

"401" - geen toegang

"500" - systeem fout
Een systeem fout kan een body bevatten met extra informatie.

 De url om verbinding mee te maken ziet er zo uit:

 https://[klantomgeving.klant.nl]/integration/api/narrowcasting/[aanroep]

Uitloop

Hier staan de aanroepen hoogover beschreven. Er is een openapi JSON (Swagger) beschikbaar voor gedetailleerde technische specificatie van de API, welke op verzoek door Logis.P verstrekt kan worden.

Alle aanroepen hieronder zijn GET requests.

Op basis van afdelingscode

Url voor aanroep:

CODE
https://[klantomgeving.klant.nl]/integration/api/narrowcasting/departments

 

Parameter

Waarde

Omschrijving

Optioneel

[QUERY]departments

ExternalID van afdeling. U kunt meerdere ExternalID’s meegeven.

Haalt de agenda’s op gekoppeld aan deze afdeling

Nee

[QUERY]showzerodelay

True of false

Indien true dan worden ook agenda’s getoond die geen uitloop hebben

Ja, standaard true

[QUERY]onlyshowactiveresources

True of false

Indien true dan worden enkel agenda’s getoond die in de laatste 30 minuten een afspraak hadden en geen afspraken meer hebben op die dag

Ja, standaard true

Voorbeeld aanroep:

CODE
https://[klantomgeving.klant.nl]/integration/api/narrowcasting/departments?departments=Bloedafname&departments=Cardiologie&showzerodelay=true&onlyshowactiveresources=false

Op basis van LocationID

Url voor aanroep:

CODE
https://[klantomgeving.klant.nl]/integration/api/narrowcasting/location

  

Parameter

Waarde

Omschrijving

Optioneel

[QUERY]locationid

LocationID van afspraak. Dit kunnen er meerdere zijn.

Haalt de agenda’s op gekoppeld aan deze afspraak met betreffende LocationID. De LocationID matched met alles dat daarmee begint. Stel bij een afspraak staat LocationID “route6” dan matched het ook met “route606”

Nee

[QUERY]filter

“default” of “complete”

Indien men enkel wil matchen met specifieke LocationID dan kan men de filter “complete”. Dan moet het een exacte match zijn

Ja, standaard “default”

[QUERY]showzerodelay

True of false

Indien true dan worden ook agenda’s getoon die geen uitloop hebben

Ja, standaard true

[QUERY]onlyshowactiveresources

True of false

Indien true dan worden enkel agenda’s getoond die in de laatste 30 minuten een afspraak hadden en geen afspraken meer hebben op die dag

Ja, standaard true

Voorbeeld aanroep:

CODE
https://[klantomgeving.klant.nl]/api/narrowcasting/location?locationids=route1&locationids=route2&filter=default&showzerodelay=true&onlyshowactiveresources=false

Op basis van wachtrij

Url voor aanroep:

CODE
https://[klantomgeving.klant.nl]/integration/api/narrowcasting/queue

  

Parameter

Waarde

Omschrijving

Optioneel

[QUERY] groupExternalIDs

ExternalID van de groep waarin de wachtrij vermeld in de customerflowqueuezit zit.

U kunt meerdere ExternalIDs meegeven.

Haalt de agenda’s op gekoppeld aan de afspraak in de wachtrijen behorende bij de betreffende wachtrijgroepen

Nee

[QUERY]showzerodelay

True of false

Indien true dan worden ook agenda’s getoond die geen uitloop hebben

Ja, standaard true

[QUERY]onlyshowactiveresources

True of false

Indien true dan worden enkel agenda’s getoond die in de laatste 30 minuten een afspraak hadden en geen afspraken meer hebben op die dag

Ja, standaard true

Voorbeeld aanroep:

CODE
https://[klantomgeving.klant.nl]/ integration/api/narrowcasting/queue?groupExternalIDs=a&groupExternalIDs=b&groupExternalIDs=c&showzerodelay=true&onlyshowactiveresources=true

Alles

Url voor aanroep:

CODE
https://[klantomgeving.klant.nl]/integration/api/narrowcasting/all

  

Parameter

Waarde

Omschrijving

Optioneel

[QUERY]showzerodelay

True of false

Indien true dan worden ook agenda’s getoond die geen uitloop hebben

Ja, standaard true

[QUERY]onlyshowactiveresources

True of false

Indien true dan worden enkel agenda’s getoond die in de laatste 30 minuten een afspraak hadden en geen afspraken meer hebben op die dag

Ja, standaard true

Voorbeeld aanroep:

CODE
https://[klantomgeving.klant.nl]/integration/api/narrowcasting/all?showzerodelay=true&onlyshowactiveresources=false

Response

 De response is een JSON en ziet er als volgt uit:

JSON
[
  {
    "Department": "Bloedafname",
    "Resource": "001",
    "ResourceDescription": "Ronald heel lange naam hier",
    "Display": "10",
    "Delay": "10"
  },
  {
    "Department": "Bloedafname",
    "Resource": "004",
    "ResourceDescription": "Piet",
    "Display": "10", //de regels van afronden, tonen vanaf en correctie zijn hier toegepast
    "Delay": "10"    //de daadwerkelijke waarde
  },
  {
    "Department": "Cardiologie",
    "Resource": "002",
    "ResourceDescription": "Janssen",
    "Display": "0",
    "Delay": "0"
  }
]

Inloop

Op basis van wachtrijgroep id {groupid}

 Url voor aanroep:

CODE
https://[klantomgeving.klant.nl]/integration/api/narrowcasting/waitingtimes

  

Parameter

Waarde

Omschrijving

Optioneel

[QUERY]groupid

ID van wachtrijgroep

Haalt wachttijden op van de groep, en individueel van de wachtrijen

Nee

Voorbeeld aanroep:

CODE
https://[klantomgeving.klant.nl]/integration/api/narrowcasting/waitingtimes?groupid=1

Response

JSON
{
    “Name”: ”Group”,
    "ExpectedInMinutes": 5,
    "ActualInMinutes": 1,
    "WaitinginQueue": 5,
    "WaitingTimesPerCounter": [
        {
            “Name”: ”Bloedafname”,
            “ExpectedInMinutes": 5,
    	   "ActualInMinutes": 1,
    	   "WaitinginQueue": 5
        },
        {
            …
        }
    ]
}

 

JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.