mhd
v0.2.2
Published
IHE MHD profile service facade for node.js
Downloads
21
Readme
mhd.js
Overview
Node.js implementation of IHE MHD, providing a RESTful API to access health documents from mobile devices.
MHD is an IHE profile for Mobile access to Health Documents. The implementation follows trial implementation rev1.1 and provides a MHD Document Responder actor using an XDS Document Consumer as a proxy to XDS registry/repository.
This is a partial implementation:
- findDocumentDossiers supports only PatientId parameter
- document posting not implemented
Installation
npm install mhd
Testing
npm test mhd
Use
var mhd = require('mhd').mhd;
var http = require("http");
Implement an auditRecordWriter callback. The following implementation writes to the console:
var auditRecordWriter = {
write: function(auditRecord, callback) {
console.log(auditRecord.toXml());
callback(null);
}
}
Implement an adapter for your document repository. The following implementation returns static data:
var repositoryAdapter = {
patientIdPattern: '^[0-9]{9}[\^]{3}[&]2.16.840.1.113883.2.1.3.9.1.0.0&ISO$',
getDocumentDossier: function(entryUuid, patientId, format, callback) {
var dossier = {
documentEntry:{
patientID:patientId,
classCode:{
code:'34133 -9',
codingScheme:'2.16.840.1.113883.6.1',
codeName:'Summary of Episode Note'},
confidentialityCode:{
code:'N',
codingScheme:'2.16.840.1.113883.5.25',
codeName:'Normal sensitivity'},
formatCode:{
code:'urn:ihe:lab:xd-lab:2008',
codingScheme:'1.3.6.1.4.1.19376.1.2.3',
codeName:'XD-Lab'},
typeCode:{
code:'',
codingScheme:'',
codeName:''},
Author:{
todo:'need to expand this!!!'},
practiceSettingCodes:{
code:'394802001',
codingScheme:'2.16.840.1.113883.6.96',
codeName:'General Medicine'},
Title:'document title',
creationTime:'20061224',
hash:'e543712c0e10501972de13a5bfcbe826c49feb75',
Size:'350',
languageCode:'en-us',
serviceStartTime:'200612230800',
serviceStopTime:'200612230900',
sourcePatientId:'4567856789^^^&3.4.5&ISO',
mimeType:'text/xml',
uniqueId:'1.2009.0827.08.33.5074',
entryUUID:entryUuid}};
callback(null, JSON.stringify(dossier));
},
findDocumentDossiers: function(query, format, callback) {
var timestamp = new Date().toString();
var response = {
updated:timestamp,
self:'http://127.0.0.1:1337/...',
entries:[
{
id:'urn:uuid:50a0807a-10a0-7c10-6296-71ed0c235b31',
self:'http://127.0.0.1:1337/net.ihe/DocumentDossier/urn:uuid:50a0807a-10a0-7c10-6296-71ed0c235b31/?PatientID=' + query.PatientID,
related:'http://127.0.0.1:1337/net.ihe/Document/urn:uuid:50a0807a-10a0-7c10-6296-71ed0c235b31/?PatientID=' + query.PatientID,
updated:timestamp}
]};
callback(null, JSON.stringify(response));
},
getDocument: function(entryUuid, patientId, format, callback){
var tmp = [];
tmp.push("<?xml version='1.0' encoding='UTF-8'?>");
tmp.push("<ClinicalDocument xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns='urn:hl7-org:v3'>");
tmp.push("<typeId extension='POCD_HD000040' root='2.16.840.1.113883.1.3'/>");
tmp.push("<templateId root='2.16.840.1.113883.2.1.3.9.10.0.0'/>");
tmp.push("<id extension='742318311954' root='2.16.840.1.113883.2.1.3.9'/>");
tmp.push("<code code='57027-5' codeSystem='2.16.840.1.113883.6.1' codeSystemName='LOINC' displayName='Measure Observations'/>");
tmp.push("<title>Measure Observations</title>");
tmp.push("<effectiveTime value='20080506143021+0100'/>");
tmp.push("<confidentialityCode code='N' codeSystem='2.16.840.1.113883.5.25' codeSystemName='HL7' displayName='Normal'/>");
tmp.push("<languageCode code='en-UK'/>");
tmp.push("<recordTarget>");
tmp.push("<patientRole>");
tmp.push("<id extension='223568611' root='2.16.840.1.113883.2.1.3.9.1.0.0'/>");
tmp.push("<addr><streetName>60 Hounslow Rd</streetName><city>SMYTHE'S GREEN</city><postalCode>CO5 1VO</postalCode></addr>");
tmp.push("<patient>");
tmp.push("<name><family>OWEN</family><given>OLIVER</given></name>");
tmp.push("<administrativeGenderCode code='M' codeSystem='2.16.840.1.113883.5.1'/>");
tmp.push("<birthTime value='19331210'/>");
tmp.push("</patient>");
tmp.push("</patientRole>");
tmp.push("</recordTarget>");
tmp.push("<author>");
tmp.push("<time value='20080506143021+0100'/>");
tmp.push("<assignedAuthor>");
tmp.push("<id extension='593978059683' root='2.16.840.1.113883.2.1.3.9.1.0.0'/>");
tmp.push("<assignedPerson>");
tmp.push("<name><family>HOOK</family><given>JAMES</given></name>");
tmp.push("</assignedPerson>");
tmp.push("<representedOrganization>");
tmp.push("<id root='2.16.840.1.113883.2.1.3.9.19.5'/>");
tmp.push("<name>Good Health Clinic</name>");
tmp.push("</representedOrganization>");
tmp.push("</assignedAuthor>");
tmp.push("</author>");
tmp.push("<custodian>");
tmp.push("<assignedCustodian>");
tmp.push("<representedCustodianOrganization>");
tmp.push("<id root='2.16.840.1.113883.2.1.3.9.1.1.1.2.0'/>");
tmp.push("<name>Sintero XDS</name>");
tmp.push("</representedCustodianOrganization>");
tmp.push("</assignedCustodian>");
tmp.push("</custodian>");
tmp.push("<documentationOf>");
tmp.push("<serviceEvent classCode='MPROT'>");
tmp.push("<effectiveTime>");
tmp.push("<low value='20080506141821'/>");
tmp.push("<high value='20080506144221+0100'/>");
tmp.push("</effectiveTime>");
tmp.push("</serviceEvent>");
tmp.push("</documentationOf>");
tmp.push("<component>");
tmp.push("<structuredBody>");
tmp.push("<component>");
tmp.push("<section>");
tmp.push("<templateId root='2.16.840.1.113883.2.1.3.9.10.1.1'/>");
tmp.push("<code code='2276-4' codeSystem='2.16.840.1.113883.6.1' codeSystemName='LOINC' displayName='Ferritin'/>");
tmp.push("<text>06-May-2008 13:30:21 GMT+01:00 Ferritin: 622.0 ug/L</text>");
tmp.push("<entry>");
tmp.push("<observation classCode='OBS' moodCode='EVN'>");
tmp.push("<code code='2276-4' codeSystem='2.16.840.1.113883.6.1' codeSystemName='LOINC' displayName='Ferritin'/>");
tmp.push("<effectiveTime value='20080506141821'/>");
tmp.push("<value xsi:type='PQ' unit='ug/L' value='622.0'/>");
tmp.push("</observation>");
tmp.push("</entry>");
tmp.push("</section>");
tmp.push("</component>");
tmp.push("</structuredBody>");
tmp.push("</component>");
tmp.push("</ClinicalDocument>");
var data = tmp.join("");
var document = {
headers:{
"content-type":"text/xml",
"content-transfer-encoding":"binary",
"content-id":"<1.urn:uuid:[email protected]>"
},
data:data
}
callback(null, document);
}
}
Register the callbacks with mhd. As mhd is an express.app it can be started as usual:
function start(){
console.log('Starting service');
mhd.registerAuditRecordWriter(auditRecordWriter);
mhd.registerRepositoryAdapter(repositoryAdapter);
var svc = http.createServer(mhd);
svc.listen(1337);
console.log('Service listening on http://127.0.0.1:1337');
}
start();
The server can then be used to search for and retrieve documents. For example, to findDocuments:
http://127.0.0.1:1337/net.ihe/DocumentDossier/search?PatientID=223568611%5E%5E%5E%262.16.840.1.113883.2.1.3.9.1.0.0%26ISO
to getDocumentDossier:
http://127.0.0.1:1337/net.ihe/DocumentDossier/urn:uuid:50a0807a-10a0-7c10-6296-71ed0c235b31/?PatientID=223568611%5E%5E%5E%262.16.840.1.113883.2.1.3.9.1.0.0%26ISO
to getDocument:
http://127.0.0.1:1337/net.ihe/Document/urn:uuid:50a0807a-10a0-7c10-6296-71ed0c235b31/?PatientID=223568611%5E%5E%5E%262.16.840.1.113883.2.1.3.9.1.0.0%26ISO
Acknowledgements
Development supported by Black Pear Software Ltd
Work funded in part by NHS Information Sharing Challenge Fund