Developing a C# .NET Hello World (telemedical) application

Prequisites

  • We assume that you have downloaded and installed Net4Care.
  • To build the code you need Microsoft Visual Studio 2010 or 2012 (with Visual C# 2010 / Microsoft .NET Framework 4.0). The free Express version is sufficient
  • You need the NuGet Visual Studio extension installed. NuGet can handle installing and updating third-party libraries and tools in Visual Studio. You can download and install NuGet from: http://nuget.org/.

    (The C# .NET examples have been tested with Microsoft Visual Studio 2010 Professional on Windows 7)

Overview

In this example, we will review two simple C# .NET "Hello World" clients that communicate with the Net4Care server side (n4c_receiver). You will find Visual Studio solution file and example programs in the n4c_contrib/csharp-client folder of the distribution.

One client "HelloUpload" demonstrates how to write C# code using the Net4Care framework classes that define a tele observation (that is, a set of clinical measurements for a patient) and uploads it to the Net4Care server.

The other client "HelloQuery" demonstrates how to program a query for all tele observations made during the last 10 minutes.

Buildling and Starting the server

To be able to run the C# examples you first need to build and start the Net4Care server. For instructions on this see Building and Starting the server (ignore from "Building and Executing the HelloWorld clients" onwards on that page, as this pertains to building and creating a Java client).

Building and Executing the HelloWorld clients

Building the code

  • Open the solution file "net4care.sln" (from the folder n4c_contrib/csharp-client) in Visual Studio.
  • Select "Build Solution" to build the projects contained in the solution.

    (The included '.nuget' project should ensure that external packages depended on are automatically downloaded and installed when building the solution.)

Running the examples

The HelloUpload and HelloQuery examples contact a net4care server. Currently the examples assume a local server running at "http://localhost:8082/observation" (see above).

The HelloUpload and HelloQuery examples can either be run from inside Visual Studio (by setting the project you wish to run as 'Startup project') or from a command line. In the following we will use a command line.

Now, start a command prompt and execute the "HelloUpload" program:

  cd (root)\n4c_contrib\csharp-client\n4c_examples\HelloUpload\bin\Debug
  HelloUpload.exe

Output should be something like:

Hello Net4Care World: Uploading an observation
   to server at address: http://localhost:8082/observation
   (Make sure the Net4Care server is running!)
Upload result: True
Upload connection result: OKOK

Next, let us try to query for observations for the last 10 minutes:

  cd (root)\n4c_contrib\csharp-client\n4c_examples\HelloQuery\bin\Debug
  HelloQuery.exe

This should result in something like:

Hello Net4Care World: Query all observations for last 10 minutes
   to server at address: http://localhost:8082/observation
   (Make sure the Net4Care server is running!)
The query is: Forwarder.QueryPersonTimeInterval for 251248-4916 in time (1387364182930-1387364782930)

=== Observations from the last 10 minutes ===
 --- RAW FORMAT - using ToString() ---
STO: 251248-4916/MyOrgID/Device: Manufac1/MODEL1/1/obs=(Spiro: FEV1:2,8 L/FVC:3,5 L(False))
 --- OWN FORMAT - using API ---
-*-*-*-*-*-
  At date/time: 18-12-2013 11:03

Measured: FVC:3,5 L / FEV1:2,8 L(False)
End.

Code walkthrough

HelloUpload

The HelloUpload client does three things

  • Configure the DataUploader which is responsible for uploading observations to the server
  • Define a tele observation with proper information on the patient, devices used, and of course measured values
  • Perform the actual upload, testing that it went well

Configure the DataUploader

As both the upload and query application needs to configure the uploader, this is encapsulated in a global function.

// Configure the architecture 
IDataUploader dataUploader = Shared.setupN4CConfiguration(serverAddress);

This function looks like this:

public static IDataUploader setupN4CConfiguration(String serverAddress, params Type[] knownObservationTypes) {
    IDataUploader dataUploader = null;
    ISerializer serializer = new JSONSerializer(knownObservationTypes);
    dataUploader = new StandardDataUploader(serializer, new HttpConnector(serverAddress));
    return dataUploader;
}

Basically, we use a default implementation and configure it with a serializer role and a connector role. Presently the Net4Care framework only contains a single serializer implementation that uses JSON as on-the-wire format. There is currently only one implementation for the connector with HTTP as the transport protocol.

Define a tele observation

// Define the actual measured values for the patient, here 3.5L for 
// full lung capacity and 2.8L for 1 second lung capacity 
Spirometry sp = new Spirometry(3.5, 2.8, false);

// Define the information regarding the used device 
var devdesc = new DeviceDescription("Spirometry", "MODEL1", "Manufac1", 
    "1", "1", "1.0", "1.0", "Classification", DateTime.Now.Ticks);
// And finally define the observation itself. The patient ID is that 
// of the 'standard' patient Nancy. 
var sto = new StandardTeleObservation("251248-4916", "MyOrgID", "myTreatmentId", 
    Codes.LOINC_OID, devdesc, sp, "I have difficulties in breathing.");

You use two standard classes from the framework StandardTeleObservation and DeviceDescription which define patient identity, organizational identity, etc., and device characteristics. Finally, to adapt the framework to a specific set of measurements, you define your own class (here Spirometry) that must implement the ObservationSpecifics interface. Much more detail can be found in How to define and upload observations (although the code examples there are in Java, it should not be hard to generalize for use with C#).

Perform the actual upload

// Upload the observation to the server... 
IFutureResult result = dataUploader.Upload(sto);
result.Wait();
if (result == null)
    Console.WriteLine("Upload returned a null result (was the server running?).");
else
{
    Console.WriteLine("Upload result: " + result.IsSuccess);
    Console.WriteLine("Upload connection result: " + result.Result);
}

The basic upload is done using the upload(sto) method of the dataUploader. It will return a IFutureResult which can be queried for the result of the operation.

HelloQuery

The HelloQuery program does

  • Configure the DataUploader
  • Define a query for the last ten minutes of observations on the given person
  • Send the query to the server and
  • Process the returned observations

Configure the DataUploader

This step is identical to the one defined in the HelloUpload program.

Define a query

The interface IQuery has a set of implementing classes that define the queries that are possible. Here we demonstrate a query for a given patient ID and given time interval (from ten minutes ago up until now), which is defined by the query class QueryPersonTimeInterval.

long now = timestampStrategy.getCurrentTimeInMillis();
long minutes = 10;
long minutesago = now - 1000*60*minutes;
// Select the requrired query by picking the proper class implementing
// the query interface
QueryPersonTimeInterval query = new QueryPersonTimeInterval(personId, minutesago, now);
Console.WriteLine("The query is: " + query + "\n");

Send the query

Next we send the query to the server using our dataUploader instance, and validate the returned response, defined by an instance of the QueryResult interface.

// Send the query to the server.
IQueryResult res = dataUploader.Query(query);
res.Wait();

Process the returned observations

Finally, we retrive the list of StandardTeleObservation that match the query from the response. We next iterate this list in two ways, one using the internal ToString() method, and one using the API's of the tele observation class. Note how we cast the tele observation's observation specifics object to our own Spirometry class. For how deserialization back to our own class happens see the Deserialize(String messagePayload) member function of the JSONSerializer class defined in the n4c_serializer project.

// Retrieve the list of observations... 
Console.WriteLine("=== Observations from the last " + minutes + " minutes ===");
List<StandardTeleObservation> obslist = res.ObservationList;

// First output observations using just the ToString() method
Console.WriteLine(" --- RAW FORMAT - using ToString() ---");
foreach (StandardTeleObservation sto in obslist)
{
    Console.WriteLine(sto == null ? "Ignoring observation" : sto.ToString());
}

// Next output observations using the API of StandardTeleObservation
// as well as the special Spirometry class we ourselves have defined.
Console.WriteLine(" --- OWN FORMAT - using API ---");

DateTime dateTime = new System.DateTime(1970, 1, 1, 0, 0, 0, 0);

foreach (StandardTeleObservation sto in obslist)
{
    if (sto == null) continue;

    Console.WriteLine("-*-*-*-*-*-");
    long timestamp = sto.Time;
    DateTime d = dateTime.AddSeconds(timestamp / 1000);
    string nicedate = d.ToShortDateString() + " " + d.ToShortTimeString();

    Console.WriteLine("  At date/time: " + nicedate + "\n");
    Console.WriteLine(sto.ObservationSpecifics.ObservationAsHumanReadableText);
}
Console.WriteLine("End.");

HelloPHMRQuery

This program is nearly identical to HelloQuery except that the query is for the Personal Health Monitoring Record (PHMR) version of the tele observations instead of the C# objects. PHMR is a Continua Alliance defined extension of the Clinical Document Architecture that is part of HL7.

Experiments

You may experiment with the code as you like but beware of the following implementation constraints in the present release

  • Only a few person IDs are known by the server as it does not have a real lookup of person identities in national registers. You can find the list of known persons in Java class FakeObjectExternalDataSource in the n4c_storage bundle.
  • If you want to erase the database, you will find it in the folder "(root)\n4c_osgi\n4c_receiver\runner". It is called "xds.db".
  • If your experiments really mix up things, a clean and reinstall often helps. Issue "mvn clean install" in the n4c_osgi folder, and rerun the server.

Other language binding

It is possible to interface a Net4Care server using other languages. You must then negotiate the HTTP protocol and JSON format directly. Please consult the documentation Server Protocol.