minor changes and internationalization for prior commit
[openemr.git] / ccdaservice / serveccda.njs
blobcf889d9c3dd4b1ff6672a306476154a3a2bfb228
1 /**
2  *
3  * Copyright (C) 2016-2017 Jerry Padgett <sjpadgett@gmail.com>
4  *
5  * LICENSE: This program is free software: you can redistribute it and/or modify
6  *  it under the terms of the GNU Affero General Public License as
7  *  published by the Free Software Foundation, either version 3 of the
8  *  License, or (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU Affero General Public License for more details.
14  *
15  *  You should have received a copy of the GNU Affero General Public License
16  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  *
18  * @package OpenEMR
19  * @author Jerry Padgett <sjpadgett@gmail.com>
20  * @link http://www.open-emr.org
21  */
23 "use strict";
24 var net = require('net');
25 var to_json = require('xmljson').to_json;
26 //var bb = require('blue-button'); //for use set global-not needed here
27 var bbg = require('blue-button-generate');
28 //var bbm = require('blue-button-model'); //for use set global-not needed here
30 var server = net.createServer();
31 var conn = ''; // make our connection scope global to script
32 // some useful routines for populating template sections
33 function validate(toValidate, ref, retObj) {
34         for (var p in ref) {
35                 if (typeof ref[p].dataType === "undefined") {
36                         retObj[p] = {};
37                         if (!toValidate[p]) toValidate[p] = {};
38                         validate(toValidate[p], ref[p], retObj[p]);
39                 } else {
40                         if (typeof toValidate === "undefined") toValidate = {};
41                         var trimmed = trim(toValidate[p]);
42                         retObj[p] = typeEnforcer(ref[p].dataType, trimmed);
43                 }
44         }
45         return retObj;
47 function typeEnforcer(type, val){
48         var validVal;
49         switch (type) {
50         case "boolean":
51                 if (typeof val === "string") {
52                         validVal = val.toLowerCase() === "true";
53                 } else {
54                         validVal = !!val;
55                 }
56                 break;
57         case "string":
58                 if ( (val === null) || (val === "undefined") || (typeof val === "undefined") ) {
59                         validVal = '';
60                 } else if (typeof val == "object") {
61                         validVal = '';
62                 } else {
63                         validVal = trim(String(val));
64                 }
65                 break;
66         case "array":
67                 if (typeof val === 'undefined' || val === null) {
68                         validVal = [];
69                 } else if (Array.isArray(val)) {
70                         validVal = [];
71                         val.forEach(function(v) {
72                                 validVal.push(trim(v));
73                         });
74                 } else {
75                         validVal = [trim(val)];
76                 }
77                 break;
78         case "integer":
79                 var asInt = parseInt(val, 10);
80                 if (isNaN(asInt)) asInt = 0;
81                 validVal = asInt;
82                 break;
83         case "number":
84                 var asNum = parseFloat(val);
85                 if (isNaN(asNum)) asNum = 0;
86                 validVal = asNum;
87                 break;
88         }
89         return validVal;
91 function trim(s) {
92         if (typeof s === 'string') return s.trim();
93         return s;
95 function safeId(s) {
96         return trim(s).toLowerCase().replace(/[^a-zA-Z0-9]+/g, '-').replace(/\-+$/, '');
98 function fDate(str) {
99         /*
100          * Format dates to js required yyyy-mm-dd + zero hundred hours Yes I freely
101          * admit, I'm lazy!
102          */
103         str = String(str); // at least ensure string so cast it...
104         if (Number(str) === 0){return "0000-01-01T00:00:00.000Z";}
105         if (str.length === 8 || (str.length === 14 && (1 * str.substring(12, 14)) === 0)) {
106                 // case yyyymmdd or yyyymmdd000000 called effectivetime by ccm.
107                 return [ str.slice(0, 4), str.slice(4, 6), str.slice(6, 8) ].join('-') + 'T00:00:00.000Z';
108         } else if (str.length === 10 && (1 * str.substring(0, 2)) <= 12) {
109                 // case mm/dd/yyyy or mm-dd-yyyy
110                 return [ str.slice(6, 10), str.slice(0, 2), str.slice(3, 5) ].join('-') + 'T00:00:00.000Z';
111         } else if (str.length === 14 && (1 * str.substring(12, 14)) > 0) {
112                 // maybe a real time so parse
113         }
114         return str + 'T00:00:00.000Z';
116 function isOne(who) {
117         try{
118                 if (who !== null && typeof who === 'object') {
119                         return who.hasOwnProperty('extension') ? 1 : Object.keys(who).length;
120                 }
121         }
122         catch(e){ return false;}
123         return 0;
125 function headReplace(content) {
126         var r = '<?xml version="1.0" encoding="UTF-8"?>\n' + 
127                         '<ClinicalDocument xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:hl7-org:v3 http://xreg2.nist.gov:8080/hitspValidation/schema/cdar2c32/infrastructure/cda/C32_CDA.xsd"' + 
128                         ' xmlns="urn:hl7-org:v3" xmlns:mif="urn:hl7-org:v3/mif">\n';
129         r += content.substr(194);
130         return r;
132 // Data model for Blue Button
133 function populateDemographic(pd, g) {
134         return {
135                 "name" : {
136                         "middle" : [ pd.mname ],
137                         "last" : pd.lname,
138                         "first" : pd.fname
139                 },
140                 "dob" : {
141                         "point" : {
142                                 "date" : fDate(pd.dob),
143                                 "precision" : "day"
144                         }
145                 },
146                 "gender" : pd.gender,
147                 "identifiers" : [ {
148                         "identifier" : "2.16.840.1.113883.19.5.99999.2",
149                         "extension" : "998991"
150                 }, {
151                         "identifier" : "2.16.840.1.113883.4.1",
152                         "extension" : pd.ssn
153                 } ],
154                 "marital_status" : pd.status,
155                 "addresses" : [ {
156                         "street_lines" : [ pd.street ],
157                         "city" : pd.city,
158                         "state" : pd.state,
159                         "zip" : pd.postalCode,
160                         "country" : pd.country,
161                         "use" : "primary home"
162                 } ],
163                 "phone" : [ {
164                         "number" : pd.phone_home,
165                         "type" : "primary home"
166                 } ],
167                 "race" : "White",
168                 "ethnicity" : pd.ethnicity,
169                 "languages" : [ {
170                         "language" : pd.language,
171                         "preferred" : true,
172                         "mode" : "Expressed spoken",
173                         "proficiency" : "Good"
174                 } ],
175                 "religion" : pd.religion,
176                 "birthplace" : {
177                         "city" : "",
178                         "state" : "",
179                         "zip" : "",
180                         "country" : ""
181                 },
182                 "guardians" : [ {
183                         "relation" : g.relation,
184                         "addresses" : [ {
185                                 "street_lines" : [ g.address ],
186                                 "city" : g.city,
187                                 "state" : g.state,
188                                 "zip" : g.postalCode,
189                                 "country" : g.country,
190                                 "use" : "primary home"
191                         } ],
192                         "names" : [ {
193                                 //"last" : "",
194                                 //"first" : ""
195                                 "name" : g.name
196                         } ],
197                         "phone" : [ {
198                                 "number" : g.telecom,
199                                 "type" : "primary home"
200                         } ]
201                 } ]
202         };
205 function populateMedication(pd) {
206         return {
207                 "date_time" : {
208                         "low" : {
209                                 "date" : fDate(pd.start_date),
210                                 "precision" : "day"
211                         },
212                         "high" : {
213                                 "date" : fDate(pd.end_date),
214                                 "precision" : "day"
215                         }
216                 },
217                 "identifiers" : [ {
218                         "identifier" : "cdbd33f0-6cde-11db-9fe1-0800200c9a66"
219                 } ],
220                 "status" : pd.status,
221                 "sig" : pd.direction,
222                 "product" : {
223                         "identifiers" : [ {
224                                 "identifier" : "2a620155-9d11-439e-92b3-5d9815ff4ee8"
225                         } ],
226                         "unencoded_name" : pd.drug,
227                         "product" : {
228                                 "name" : pd.drug,
229                                 "code" : pd.rxnorm,
230                                 "translations" : [ {
231                                         "name" : pd.drug,
232                                         "code" : pd.rxnorm,
233                                         "code_system_name" : "RXNORM"
234                                 } ],
235                                 "code_system_name" : "RXNORM"
236                         },
237                         "manufacturer" : "UNK"
238                 },
239                 "supply" : {
240                         "date_time" : {
241                                 "low" : {
242                                         "date" : fDate(pd.start_date),
243                                         "precision" : "day"
244                                 }
245                         },
246                         "repeatNumber" : "NI",
247                         "quantity" : "NI",
248                         "author" : {
249                                 "identifiers" : [ {
250                                         "identifier" : "2a620155-9d11-439e-92b3-5d9815fe4de8"
251                                 } ],
252                                 "name" : {
253                                         "prefix" : pd.title,
254                                         "last" : pd.lname,
255                                         "first" : pd.fname
256                                 }
257                         }
258                 },
259                 "administration" : {
260                         "route" : {
261                                 "name" : pd.route,
262                                 "code" : pd.route_code,
263                                 "code_system_name" : "Medication Route FDA"
264                         },
265                         "form" : {
266                                 "name" : pd.form,
267                                 "code" : pd.form_code,
268                                 "code_system_name" : "Medication Route FDA"
269                         },
270                         "dose" : {
271                                 "value" : parseFloat(pd.dosage),
272                                 "unit" : pd.unit
273                         },
274                         "rate" : {
275                                 "value" : 90,
276                                 "unit" : "ml/min"
277                         },
278                         "interval" : {
279                                 "period" : {
280                                         "value" : parseFloat(pd.dosage),
281                                         "unit" : pd.interval
282                                 },
283                                 "frequency" : true
284                         }
285                 },
286                 "performer" : {
287                         "organization" : [ {
288                                 "identifiers" : [ {
289                                         "identifier" : "2.16.840.1.113883.19.5.9999.1393"
290                                 } ],
291                                 "name" : [ pd.performer_name ]
292                         } ]
293                 },
294                 "drug_vehicle" : {
295                         "name" : pd.form,
296                         "code" : pd.form_code,
297                         "code_system_name" : "RXNORM"
298                 },
299                 "precondition" : {
300                         "code" : {
301                                 "code" : "ASSERTION",
302                                 "code_system_name" : "ActCode"
303                         },
304                         "value" : {
305                                 "name" : "",
306                                 "code" : "NI",
307                                 "code_system_name" : "SNOMED CT"
308                         }
309                 },
310                 "indication" : {
311                         "identifiers" : [ {
312                                 "identifier" : "db734647-fc99-424c-a864-7e3cda82e703",
313                                 "extension" : "45665"
314                         } ],
315                         "code" : {
316                                 "name" : "Finding",
317                                 "code" : "404684003",
318                                 "code_system_name" : "SNOMED CT"
319                         },
320                         "date_time" : {
321                                 "low" : {
322                                         "date" : fDate(pd.start_date),
323                                         "precision" : "day"
324                                 }
325                         },
326                         "value" : {
327                                 "name" : pd.indications,
328                                 "code" : "NI",
329                                 "code_system_name" : "SNOMED CT"
330                         }
331                 },
332                 "dispense" : {
333                         "identifiers" : [ {
334                                 "identifier" : "1.2.3.4.56789.1",
335                                 "extension" : "cb734647-fc99-424c-a864-7e3cda82e704"
336                         } ],
337                         "performer" : {
338                                 "identifiers" : [ {
339                                         "identifier" : "2.16.840.1.113883.19.5.9999.456",
340                                         "extension" : "2981823"
341                                 } ],
342                                 "address" : [ {
343                                         "street_lines" : [ pd.address ],
344                                         "city" : pd.city,
345                                         "state" : pd.state,
346                                         "zip" : pd.zip,
347                                         "country" : "US"
348                                 } ],
349                                 "organization" : [ {
350                                         "identifiers" : [ {
351                                                 "identifier" : "2.16.840.1.113883.19.5.9999.1393"
352                                         } ],
353                                         "name" : [ pd.performer_name ]
354                                 } ]
355                         }
356                 }
357         };
360 function populateEncounter(pd) {
361         return {
362                 "encounter" : {
363                         "name" : pd.encounter_procedures ? pd.encounter_procedures.procedures.text : 'NI',
364                         "code" : pd.encounter_procedures ? pd.encounter_procedures.procedures.code : 'NI',
365                         "code_system_name" : "CPT",
366                         "translations" : [ {
367                                 "name" : "NI",
368                                 "code" : "NI",
369                                 "code_system_name" : "NI"
370                         } ]
371                 },
372                 "identifiers" : [ {
373                         "identifier" : pd.sha_extension
374                 } ],
375                 "date_time" : {
376                         "point" : {
377                                 "date" : fDate(pd.date_formatted),
378                                 "precision" : "second"
379                         }
380                 },
381                 "performers" : [ {
382                         "identifiers" : [ {
383                                 "identifier" : pd.facility_sha_extension
384                         } ],
385                         "code" : [ {
386                                 "name" : pd.physician_type,
387                                 "code" : "NI",
388                                 "code_system_name" : "SNOMED CT"
389                         } ]
390                 } ],
391                 "locations" : [ {
392                         "name" : pd.location,
393                         "location_type" : {
394                                 "name" : pd.location_details,
395                                 "code" : "NI",
396                                 "code_system_name" : "HealthcareServiceLocation"
397                         },
398                         "address" : [ {
399                                 "street_lines" : [ pd.facility_address ],
400                                 "city" : pd.facility_city,
401                                 "state" : pd.facility_state,
402                                 "zip" : pd.facility_zip,
403                                 "country" : pd.facility_country
404                         } ]
405                 } ],
406                 "findings" : [ {
407                         "identifiers" : [ {
408                                 "identifier" : "",
409                                 "extension" : ""
410                         } ],
411                         "value" : {
412                                 "name" : pd.encounter_reason,
413                                 "code" : "NI",
414                                 "code_system_name" : "SNOMED CT"
415                         },
416                         "date_time" : {
417                                 "low" : {
418                                         "date" : fDate(pd.date_formatted),
419                                         "precision" : "day"
420                                 }
421                         }
422                 } ]
423         };
426 function populateAllergy(pd) {
427         return {
428                 "identifiers" : [ {
429                         "identifier" : "36e3e930-7b14-11db-9fe1-0800200c9a66"
430                 } ],
431                 "date_time" : {
432                         "point" : {
433                                 "date" : fDate(pd.startdate),
434                                 "precision" : "day"
435                         }
436                 },
437                 "observation" : {
438                         "identifiers" : [ {
439                                 "identifier" : "4adc1020-7b14-11db-9fe1-0800200c9a66"
440                         } ],
441                         "allergen" : {
442                                 "name" : pd.title,
443                                 "code" : pd.rxnorm_code,
444                                 "code_system_name" : "RXNORM"
445                         },
446                         "intolerance" : {
447                                 "name" : "Propensity to adverse reactions to drug",
448                                 "code" : pd.snomed_code,
449                                 "code_system_name" : "SNOMED CT"
450                         },
451                         "date_time" : {
452                                 "low" : {
453                                         "date" : fDate(pd.startdate),
454                                         "precision" : "day"
455                                 }
456                         },
457                         "status" : {
458                                 "name" : pd.allergy_status,
459                                 "code" : pd.status_code,
460                                 "code_system_name" : "SNOMED CT"
461                         },
462                         "reactions" : [ {
463                                 "identifiers" : [ {
464                                         "identifier" : "4adc1020-7b14-11db-9fe1-0800200c9a64"
465                                 } ],
466                                 "date_time" : {
467                                         "low" : {
468                                                 "date" : fDate(pd.startdate),
469                                                 "precision" : "day"
470                                         },
471                                         "high" : {
472                                                 "date" : fDate(pd.enddate),
473                                                 "precision" : "day"
474                                         }
475                                 },
476                                 "reaction" : {
477                                         "name" : pd.reaction_text,
478                                         "code" : pd.reaction_code,
479                                         "code_system_name" : "SNOMED CT"
480                                 },
481                                 "severity" : {
482                                         "code" : {
483                                                 "name" : pd.outcome,
484                                                 "code" : pd.outcome_code,
485                                                 "code_system_name" : "SNOMED CT"
486                                         },
487                                         "interpretation" : {
488                                                 "name" : "UNK",
489                                                 "code" : "NI",
490                                                 "code_system_name" : "Observation Interpretation"
491                                         }
492                                 }
493                         } ],
494                         "severity" : {
495                                 "code" : {
496                                         "name" : pd.outcome,
497                                         "code" : pd.outcome_code,
498                                         "code_system_name" : "SNOMED CT"
499                                 },
500                                 "interpretation" : {
501                                         "name" : "UNK",
502                                         "code" : "NI",
503                                         "code_system_name" : "Observation Interpretation"
504                                 }
505                         }
506                 }
507         };
510 function populateProblem(pd) {
511         return {
512                 "date_time" : {
513                         "low" : {
514                                 "date" : fDate(pd.start_date_table),
515                                 "precision" : "day"
516                         },
517                         "high" : {
518                                 "date" : fDate(pd.end_date),
519                                 "precision" : "day"
520                         }
521                 },
522                 "identifiers" : [ {
523                         "identifier" : pd.sha_extension
524                 } ],
525                 "problem" : {
526                         "code" : {
527                                 "name" : pd.title,
528                                 "code" : pd.code,
529                                 "code_system_name" : "ICD10"
530                         },
531                         "date_time" : {
532                                 "low" : {
533                                         "date" : fDate(pd.start_date_table),
534                                         "precision" : "day"
535                                 },
536                                 "high" : {
537                                         "date" : fDate(pd.end_date),
538                                         "precision" : "second"
539                                 }
540                         }
541                 },
542                 "onset_age" : pd.age,
543                 "onset_age_unit" : "Year",
544                 "status" : {
545                         "name" : pd.status_table,
546                         "date_time" : {
547                                 "low" : {
548                                         "date" : fDate(pd.start_date_table),
549                                         "precision" : "day"
550                                 },
551                                 "high" : {
552                                         "date" : fDate(pd.end_date),
553                                         "precision" : "second"
554                                 }
555                         }
556                 },
557                 "patient_status" : pd.observation,
558                 "source_list_identifiers" : [ {
559                         "identifier" : "ec8a6ff8-ed4b-4f7e-82c3-e98e58b45de7"
560                 } ]
561         };
565 function populateProcedure(pd) {
566         return {
567                 "procedure" : {
568                         "name" : pd.description,
569                         "code" : pd.code,
570                         "code_system_name" : "CPT"
571                 },
572                 "identifiers" : [ {
573                         "identifier" : "d68b7e32-7810-4f5b-9cc2-acd54b0fd85d"
574                 } ],
575                 "status" : "",
576                 "date_time" : {
577                         "point" : {
578                                 "date" : fDate(pd.date),
579                                 "precision" : "day"
580                         }
581                 },
582                 "body_sites" : [ {
583                         "name" : "",
584                         "code" : "",
585                         "code_system_name" : ""
586                 } ],
587                 "specimen" : {
588                         "identifiers" : [ {
589                                 "identifier" : "c2ee9ee9-ae31-4628-a919-fec1cbb58683"
590                         } ],
591                         "code" : {
592                                 "name" : "",
593                                 "code" : "",
594                                 "code_system_name" : "SNOMED CT"
595                         }
596                 },
597                 "performers" : [ {
598                         "identifiers" : [ {
599                                 "identifier" : "2.16.840.1.113883.19.5.9999.456",
600                                 "extension" : "2981823"
601                         } ],
602                         "address" : [ {
603                                 "street_lines" : [ pd.address ],
604                                 "city" : pd.city,
605                                 "state" : pd.state,
606                                 "zip" : pd.zip,
607                                 "country" : "NI"
608                         } ],
609                         "phone" : [ {
610                                 "number" : pd.work_phone,
611                                 "type" : "work place"
612                         } ],
613                         "organization" : [ {
614                                 "identifiers" : [ {
615                                         "identifier" : "2.16.840.1.113883.19.5.9999.1393"
616                                 } ],
617                                 "name" : [ pd.facility_name ],
618                                 "address" : [ {
619                                         "street_lines" : [ pd.facility_address ],
620                                         "city" : pd.facility_city,
621                                         "state" : pd.facility_state,
622                                         "zip" : pd.facility_zip,
623                                         "country" : pd.facility_country
624                                 } ],
625                                 "phone" : [ {
626                                         "number" : pd.facility_phone,
627                                         "type" : "work place"
628                                 } ]
629                         } ]
630                 } ],
631                 "procedure_type" : "procedure"
632         };
635 function populateResult(pd) {
636         return {
637                 "identifiers" : [ {
638                         "identifier" : "107c2dc0-67a5-11db-bd13-0800200c9a66"
639                 } ],
640                 "result" : {
641                         "name" : pd.title,
642                         "code" : pd.test_code || "NI",
643                         "code_system_name" : "LOINC"
644                 },
645                 "date_time" : {
646                         "point" : {
647                                 "date" : fDate(pd.date_ordered_table),
648                                 "precision" : "day"
649                         }
650                 },
651                 "status" : pd.order_status,
652                 "reference_range" : {
653                         "low" : pd.subtest.range,
654                         "high" : pd.subtest.range,
655                         "unit" : pd.subtest.unit
656                 },
657                 "interpretations" : [ pd.subtest.result_value ],
658                 "value" : parseFloat(pd.subtest.result_value),
659                 "unit" : pd.subtest.unit
660         };
663 function getResultSet(results) {
664         var resultSet = {
665                 "identifiers" : [ {
666                         "identifier" : "7d5a02b0-67a4-11db-bd13-0800200c9a66"
667                 } ],
668                 "result_set" : {
669                         "name" : "Get this data.",
670                         "code" : "NI",
671                         "code_system_name" : "SNOMED CT"
672                 }
673         };
674         var rs = [];
675         var many = [];
676         var theone = {};
677         var count = 0;
678         many.results = [];
679         try{
680                 count = isOne(results.result);
681         }catch(e){count = 0;}   
682         if (count > 1) {
683                 for ( var i in results.result) {
684                         theone[i] = populateResult(results.result[i]);
685                         many.results.push(theone[i]);
686                 }
687         } else if (count !== 0) {
688                 theone = populateResult(results.result);
689                 many.results.push(theone);
690         }
691         rs.results = Object.assign(resultSet);
692         rs.results.results = Object.assign(many.results);
693         return rs;
696 function getPlanOfCare(pd) {
697         return {
698                 "plan" : {
699                         "name" : pd.code_text,
700                         "code" : pd.code,
701                         "code_system_name" : "SNOMED CT"
702                 },
703                 "identifiers" : [ {
704                         "identifier" : "9a6d1bac-17d3-4195-89a4-1121bc809b4a"
705                 } ],
706                 "date_time" : {
707                         "center" : {
708                                 "date" : fDate(pd.date),
709                                 "precision" : "day"
710                         }
711                 },
712                 "type" : "observation",
713                 "status" : {
714                         "code" : pd.status
715                 },
716                 "subType" : pd.description
717         };
720 function populateVital(pd) {
721         return [ {
722                 "identifiers" : [ {
723                         "identifier" : "2.16.840.1.113883.3.140.1.0.6.10.14.1",
724                         "extension" : pd.extension_bps
725                 } ],
726                 "vital" : {
727                         "name" : "Blood Pressure Systolic",
728                         "code" : "8480-6",
729                         "code_system_name" : "LOINC"
730                 },
731                 "status" : "completed",
732                 "date_time" : {
733                         "point" : {
734                                 "date" : fDate(pd.effectivetime),
735                                 "precision" : "second"
736                         }
737                 },
738                 "value" : parseFloat(pd.bps),
739                 "unit" : "mm[Hg]"
740         }, {
741                 "identifiers" : [ {
742                         "identifier" : "2.16.840.1.113883.3.140.1.0.6.10.14.1",
743                         "extension" : pd.extension_bpd
744                 } ],
745                 "vital" : {
746                         "name" : "Blood Pressure Diastolic",
747                         "code" : "8462-4",
748                         "code_system_name" : "LOINC"
749                 },
750                 "status" : "completed",
751                 "date_time" : {
752                         "point" : {
753                                 "date" : fDate(pd.effectivetime),
754                                 "precision" : "second"
755                         }
756                 },
757                 "interpretations" : [ "UNK" ],
758                 "value" : parseFloat(pd.bpd),
759                 "unit" : "mm[Hg]"
760         }, {
761                 "identifiers" : [ {
762                         "identifier" : "2.16.840.1.113883.3.140.1.0.6.10.14.1",
763                         "extension" : pd.extension_pulse
764                 } ],
765                 "vital" : {
766                         "name" : "Heart Rate",
767                         "code" : "8867-4",
768                         "code_system_name" : "LOINC"
769                 },
770                 "status" : "completed",
771                 "date_time" : {
772                         "point" : {
773                                 "date" : fDate(pd.effectivetime),
774                                 "precision" : "second"
775                         }
776                 },
777                 "interpretations" : [ "UNK" ],
778                 "value" : parseFloat(pd.pulse),
779                 "unit" : "/min"
780         }, {
781                 "identifiers" : [ {
782                         "identifier" : "2.16.840.1.113883.3.140.1.0.6.10.14.1",
783                         "extension" : pd.extension_breath
784                 } ],
785                 "vital" : {
786                         "name" : "Respiratory Rate",
787                         "code" : "9279-1",
788                         "code_system_name" : "LOINC"
789                 },
790                 "status" : "completed",
791                 "date_time" : {
792                         "point" : {
793                                 "date" : fDate(pd.effectivetime),
794                                 "precision" : "second"
795                         }
796                 },
797                 "interpretations" : [ "UNK" ],
798                 "value" : parseFloat(pd.breath),
799                 "unit" : "/min"
800         }, {
801                 "identifiers" : [ {
802                         "identifier" : "2.16.840.1.113883.3.140.1.0.6.10.14.1",
803                         "extension" : pd.extension_temperature
804                 } ],
805                 "vital" : {
806                         "name" : "Body Temperature",
807                         "code" : "8310-5",
808                         "code_system_name" : "LOINC"
809                 },
810                 "status" : "completed",
811                 "date_time" : {
812                         "point" : {
813                                 "date" : fDate(pd.effectivetime),
814                                 "precision" : "second"
815                         }
816                 },
817                 "interpretations" : [ "UNK" ],
818                 "value" : parseFloat(pd.temperature),
819                 "unit" : "degF"
820         }, {
821                 "identifiers" : [ {
822                         "identifier" : "2.16.840.1.113883.3.140.1.0.6.10.14.1",
823                         "extension" : pd.extension_height
824                 } ],
825                 "vital" : {
826                         "name" : "Height",
827                         "code" : "8302-2",
828                         "code_system_name" : "LOINC"
829                 },
830                 "status" : "completed",
831                 "date_time" : {
832                         "point" : {
833                                 "date" : fDate(pd.effectivetime),
834                                 "precision" : "second"
835                         }
836                 },
837                 "interpretations" : [ "UNK" ],
838                 "value" : parseFloat(pd.height),
839                 "unit" : pd.unit_height
840         }, {
841                 "identifiers" : [ {
842                         "identifier" : "2.16.840.1.113883.3.140.1.0.6.10.14.1",
843                         "extension" : pd.extension_weight
844                 } ],
845                 "vital" : {
846                         "name" : "Weight Measured",
847                         "code" : "3141-9",
848                         "code_system_name" : "LOINC"
849                 },
850                 "status" : "completed",
851                 "date_time" : {
852                         "point" : {
853                                 "date" : fDate(pd.effectivetime),
854                                 "precision" : "second"
855                         }
856                 },
857                 "interpretations" : [ "UNK" ],
858                 "value" : parseFloat(pd.weight),
859                 "unit" : pd.unit_weight
860         }, {
861                 "identifiers" : [ {
862                         "identifier" : "2.16.840.1.113883.3.140.1.0.6.10.14.1",
863                         "extension" : pd.extension_BMI
864                 } ],
865                 "vital" : {
866                         "name" : "BMI (Body Mass Index)",
867                         "code" : "39156-5",
868                         "code_system_name" : "LOINC"
869                 },
870                 "status" : "completed",
871                 "date_time" : {
872                         "point" : {
873                                 "date" : fDate(pd.effectivetime),
874                                 "precision" : "second"
875                         }
876                 },
877                 "interpretations" : [ "UNK" ],
878                 "value" : parseFloat(pd.BMI),
879                 "unit" : "kg/m2"
880         } ];
883 function populateSocialHistory(pd) {
884         return {
885                 "date_time" : {
886                         "low" : {
887                                 "date" : fDate(pd.date),
888                                 "precision" : "day"
889                         },
890                         "high" : {
891                                 "date" : fDate(pd.date),
892                                 "precision" : "second"
893                         }
894                 },
895                 "identifiers" : [ {
896                         "identifier" : pd.sha_extension,
897                         "extension" : pd.extension
898                 } ],
899                 "code" : {
900                         "name" : pd.element
901                 },
902                 "value" : pd.description
903         };
906 function populateImmunization(pd) {
907         return {
908                 "date_time" : {
909                         "point" : {
910                                 "date" : fDate(pd.administered_on),
911                                 "precision" : "month"
912                         }
913                 },
914                 "identifiers" : [ {
915                         "identifier" : "e6f1ba43-c0ed-4b9b-9f12-f435d8ad8f92"
916                 } ],
917                 "status" : "complete",
918                 "product" : {
919                         "product" : {
920                                 "name" : pd.code_text,
921                                 "code" : pd.cvx_code,
922                                 "code_system_name" : "CVX",
923                                 "translations" : [ {
924                                         "name" : "NI",
925                                         "code" : "NI",
926                                         "code_system_name" : "CVX"
927                                 } ]
928                         },
929                         "lot_number" : "1",
930                         "manufacturer" : "UNK"
931                 },
932                 "administration" : {
933                         "route" : {
934                                 "name" : pd.route_of_administration,
935                                 "code" : pd.route_code,
936                                 "code_system_name" : "Medication Route FDA"
937                         },
938                         "dose" : {
939                                 "value" : 50,
940                                 "unit" : "mcg"
941                         }
942                 },
943                 "performer" : {
944                         "identifiers" : [ {
945                                 "identifier" : "2.16.840.1.113883.19.5.9999.456",
946                                 "extension" : "2981824"
947                         } ],
948                         "name" : [ {
949                                 "last" : pd.lname,
950                                 "first" : pd.fname
951                         } ],
952                         "address" : [ {
953                                 "street_lines" : [ pd.address ],
954                                 "city" : pd.city,
955                                 "state" : pd.state,
956                                 "zip" : pd.zip,
957                                 "country" : "US"
958                         } ],
959                         "organization" : [ {
960                                 "identifiers" : [ {
961                                         "identifier" : "2.16.840.1.113883.19.5.9999.1394"
962                                 } ],
963                                 "name" : [ pd.facility_name ]
964                         } ]
965                 },
966                 "instructions" : {
967                         "code" : {
968                                 "name" : "immunization education",
969                                 "code" : "171044003",
970                                 "code_system_name" : "SNOMED CT"
971                         },
972                         "free_text" : "Needs Attention for more data."
973                 }
974         };
977 function populatePayer(pd) {
978         return {
979                 "identifiers" : [ {
980                         "identifier" : "1fe2cdd0-7aad-11db-9fe1-0800200c9a66"
981                 } ],
982                 "policy" : {
983                         "identifiers" : [ {
984                                 "identifier" : "3e676a50-7aac-11db-9fe1-0800200c9a66"
985                         } ],
986                         "code" : {
987                                 "code" : "SELF",
988                                 "code_system_name" : "HL7 RoleCode"
989                         },
990                         "insurance" : {
991                                 "code" : {
992                                         "code" : "PAYOR",
993                                         "code_system_name" : "HL7 RoleCode"
994                                 },
995                                 "performer" : {
996                                         "identifiers" : [ {
997                                                 "identifier" : "2.16.840.1.113883.19"
998                                         } ],
999                                         "address" : [ {
1000                                                 "street_lines" : [ "123 Insurance Road" ],
1001                                                 "city" : "Blue Bell",
1002                                                 "state" : "MA",
1003                                                 "zip" : "02368",
1004                                                 "country" : "US",
1005                                                 "use" : "work place"
1006                                         } ],
1007                                         "phone" : [ {
1008                                                 "number" : "(781)555-1515",
1009                                                 "type" : "work place"
1010                                         } ],
1011                                         "organization" : [ {
1012                                                 "name" : [ "Good Health Insurance" ],
1013                                                 "address" : [ {
1014                                                         "street_lines" : [ "123 Insurance Road" ],
1015                                                         "city" : "Blue Bell",
1016                                                         "state" : "MA",
1017                                                         "zip" : "02368",
1018                                                         "country" : "US",
1019                                                         "use" : "work place"
1020                                                 } ],
1021                                                 "phone" : [ {
1022                                                         "number" : "(781)555-1515",
1023                                                         "type" : "work place"
1024                                                 } ]
1025                                         } ],
1026                                         "code" : [ {
1027                                                 "code" : "PAYOR",
1028                                                 "code_system_name" : "HL7 RoleCode"
1029                                         } ]
1030                                 }
1031                         }
1032                 },
1033                 "guarantor" : {
1034                         "code" : {
1035                                 "code" : "GUAR",
1036                                 "code_system_name" : "HL7 Role"
1037                         },
1038                         "identifiers" : [ {
1039                                 "identifier" : "329fcdf0-7ab3-11db-9fe1-0800200c9a66"
1040                         } ],
1041                         "name" : [ {
1042                                 "prefix" : "Mr.",
1043                                 "middle" : [ "Frankie" ],
1044                                 "last" : "Everyman",
1045                                 "first" : "Adam"
1046                         } ],
1047                         "address" : [ {
1048                                 "street_lines" : [ "17 Daws Rd." ],
1049                                 "city" : "Blue Bell",
1050                                 "state" : "MA",
1051                                 "zip" : "02368",
1052                                 "country" : "US",
1053                                 "use" : "primary home"
1054                         } ],
1055                         "phone" : [ {
1056                                 "number" : "(781)555-1212",
1057                                 "type" : "primary home"
1058                         } ]
1059                 },
1060                 "participant" : {
1061                         "code" : {
1062                                 "name" : "Self",
1063                                 "code" : "SELF",
1064                                 "code_system_name" : "HL7 Role"
1065                         },
1066                         "performer" : {
1067                                 "identifiers" : [ {
1068                                         "identifier" : "14d4a520-7aae-11db-9fe1-0800200c9a66",
1069                                         "extension" : "1138345"
1070                                 } ],
1071                                 "address" : [ {
1072                                         "street_lines" : [ "17 Daws Rd." ],
1073                                         "city" : "Blue Bell",
1074                                         "state" : "MA",
1075                                         "zip" : "02368",
1076                                         "country" : "US",
1077                                         "use" : "primary home"
1078                                 } ],
1079                                 "code" : [ {
1080                                         "name" : "Self",
1081                                         "code" : "SELF",
1082                                         "code_system_name" : "HL7 Role"
1083                                 } ]
1084                         },
1085                         "name" : [ {
1086                                 "prefix" : "Mr.",
1087                                 "middle" : [ "A." ],
1088                                 "last" : "Everyman",
1089                                 "first" : "Frank"
1090                         } ]
1091                 },
1092                 "policy_holder" : {
1093                         "performer" : {
1094                                 "identifiers" : [ {
1095                                         "identifier" : "2.16.840.1.113883.19",
1096                                         "extension" : "1138345"
1097                                 } ],
1098                                 "address" : [ {
1099                                         "street_lines" : [ "17 Daws Rd." ],
1100                                         "city" : "Blue Bell",
1101                                         "state" : "MA",
1102                                         "zip" : "02368",
1103                                         "country" : "US",
1104                                         "use" : "primary home"
1105                                 } ]
1106                         }
1107                 },
1108                 "authorization" : {
1109                         "identifiers" : [ {
1110                                 "identifier" : "f4dce790-8328-11db-9fe1-0800200c9a66"
1111                         } ],
1112                         "procedure" : {
1113                                 "code" : {
1114                                         "name" : "Colonoscopy",
1115                                         "code" : "73761001",
1116                                         "code_system_name" : "SNOMED CT"
1117                                 }
1118                         }
1119                 }
1120         };
1123 function populateHeader(pd){
1124         var head = {
1125             "identifiers": [
1126                 {
1127                     "identifier": "2.16.840.1.113883.19.5.99999.1",
1128                     "extension": "TT988"
1129                 }
1130             ],
1131             "confidentiality_code": {
1132                 "code": "N",
1133                 "name": "Normal",
1134                 "code_system_name": "Confidentiality Code"
1135             },
1136             "code": {
1137                 "name": "Continuity of Care Document",
1138                 "code": "34133-9",
1139                 "code_system_name": "LOINC"
1140             },
1141             "template": [
1142                 "2.16.840.1.113883.10.20.22.1.1",
1143                 "2.16.840.1.113883.10.20.22.1.2"
1144             ],
1145             "title": "Clinical: Health Summary",
1146             "date_time": {
1147                 "point": {
1148                     "date": pd.created_time_timezone,
1149                     "precision": "minute"
1150                 }
1151             },
1152             "author": {
1153                 "author": [
1154                     {
1155                         "identifiers": [
1156                             {
1157                                 "identifier": "2.16.840.1.113883.4.6",
1158                                 "extension": "99999999"
1159                             }
1160                         ],
1161                         "name": [
1162                             {
1163                                 "last": pd.author.lname,
1164                                 "first": pd.author.fname
1165                             }
1166                         ],
1167                         "address": [
1168                             {
1169                                 "street_lines": [
1170                                         pd.author.streetAddressLine
1171                                 ],
1172                                 "city": pd.author.city,
1173                                 "state": pd.author.state,
1174                                 "zip": pd.author.postalCode,
1175                                 "country": pd.author.country
1176                             }
1177                         ],
1178                         "phone": [
1179                             {
1180                                 "number": pd.author.telecom,
1181                                 "type": "work place"
1182                             }
1183                         ],
1184                         "code": [
1185                             {
1186                                 "name": "UNK",
1187                                 "code": "NI"
1188                             }
1189                         ]
1190                     }
1191                 ],
1192                 "date_time": {
1193                     "point": {
1194                         "date": "UNK",
1195                         "precision": "second"
1196                     }
1197                 }
1198             },
1199             "data_enterer": {
1200                 "identifiers": [
1201                     {
1202                         "identifier": "2.16.840.1.113883.4.6",
1203                         "extension": "999999943252"
1204                     }
1205                 ],
1206                 "name": [
1207                     {
1208                         "last": pd.data_enterer.lname,
1209                         "first": pd.data_enterer.fname
1210                     }
1211                 ],
1212                 "address": [
1213                         {
1214                         "street_lines": [
1215                                 pd.data_enterer.streetAddressLine
1216                         ],
1217                         "city": pd.data_enterer.city,
1218                         "state": pd.data_enterer.state,
1219                         "zip": pd.data_enterer.postalCode,
1220                         "country": pd.data_enterer.country
1221                     }
1222                 ],
1223                 "phone": [
1224                     {
1225                         "number": pd.data_enterer.telecom,
1226                         "type": "work place"
1227                     }
1228                 ]
1229             },
1230             "informant": {
1231                 "identifiers": [
1232                     {
1233                         "identifier": "2.16.840.1.113883.19.5",
1234                         "extension": "KP00017"
1235                     }
1236                 ],
1237                 "name": [
1238                     {
1239                         "last": pd.informer.lname,
1240                         "first": pd.informer.fname
1241                     }
1242                 ],
1243                 "address": [
1244                         {
1245                         "street_lines": [
1246                                 pd.informer.streetAddressLine
1247                         ],
1248                         "city": pd.informer.city,
1249                         "state": pd.informer.state,
1250                         "zip": pd.informer.postalCode,
1251                         "country": pd.informer.country
1252                     }
1253                 ],
1254                 "phone": [
1255                     {
1256                         "number": pd.informer.telecom,
1257                         "type": "work place"
1258                     }
1259                 ]
1260             },
1261             "service_event": {
1262                 "code": {
1263                     "name": "NI",
1264                     "code": "NI",
1265                     "code_system_name": "SNOMED CT"
1266                 },
1267                 "date_time": {
1268                     "low": {
1269                         "date": "UNK",
1270                         "precision": "minute"
1271                     },
1272                     "high": {
1273                         "date": pd.created_time_timezone,
1274                         "precision": "minute"
1275                     }
1276                 },
1277                 "performer": [
1278                     {
1279                         "performer": [
1280                             {
1281                                 "identifiers": [
1282                                     {
1283                                         "identifier": "2.16.840.1.113883.4.6",
1284                                         "extension": "PseudoMD-1"
1285                                     }
1286                                 ],
1287                                 "name": [ // Most likely not right - maybe should be provider
1288                                     {
1289                                         "last": pd.information_recipient.lname,
1290                                         "first": pd.information_recipient.fname
1291                                     }
1292                                 ],
1293                                 "address": [
1294                                     {
1295                                         "street_lines": [
1296                                                 pd.information_recipient.streetAddressLine
1297                                         ],
1298                                         "city": pd.information_recipient.city,
1299                                         "state": pd.information_recipient.state,
1300                                         "zip": pd.information_recipient.postalCode,
1301                                         "country": pd.information_recipient.country
1302                                     }
1303                                 ],
1304                                 "phone": [
1305                                     {
1306                                         "number": pd.information_recipient.telecom,
1307                                         "type": "work place"
1308                                     }
1309                                 ],
1310                                 "organization": [
1311                                     {
1312                                         "identifiers": [
1313                                             {
1314                                                 "identifier": "2.16.840.1.113883.19.5.9999.1393"
1315                                             }
1316                                         ],
1317                                         "name": [
1318                                                 pd.encounter_provider.facility_name
1319                                         ],
1320                                         "address": [
1321                                             {
1322                                                 "street_lines": [
1323                                                    pd.encounter_provider.facility_street
1324                                                 ],
1325                                                 "city": pd.encounter_provider.facility_city,
1326                                                 "state": pd.encounter_provider.facility_state,
1327                                                 "zip": pd.encounter_provider.facility_postal_code,
1328                                                 "country": pd.encounter_provider.facility_country_code
1329                                             }
1330                                         ],
1331                                         "phone": [
1332                                             {
1333                                                 "number": pd.encounter_provider.facility_phone,
1334                                                 "type": "primary work"
1335                                             }
1336                                         ]
1337                                     }
1338                                 ],
1339                                 "code": [
1340                                     {
1341                                         "name": "UNK",
1342                                         "code": "NI",
1343                                         "code_system_name": "Provider Codes"
1344                                     }
1345                                 ]
1346                             }
1347                         ],
1348                         "code": {
1349                             "name": "Primary Performer",
1350                             "code": "PP",
1351                             "code_system_name": "Provider Role"
1352                         }
1353                     }
1354                 ]
1355             }
1356         };
1357         return head;
1360 function genCcda(pd) {
1361         var doc = {};
1362         var data = {};
1363         var count = 0;
1364         var many = [];
1365         var theone = {};
1366         
1367         // Header -  @todo pd may be too large- break down to subsections
1368         var head = populateHeader(pd);
1369         data.head = Object.assign(head);
1370         // Demographics
1371         var demographic = populateDemographic(pd.patient, pd.guardian);
1372         data.demographics = Object.assign(demographic);
1373         // vitals
1374         many.vitals = [];
1375         try{
1376                 count = isOne(pd.history_physical.vitals_list.vitals);
1377         }catch(e){count = 0}
1378         if (count > 1) {
1379                 for ( var i in pd.history_physical.vitals_list.vitals) {
1380                         theone = populateVital(pd.history_physical.vitals_list.vitals[i]);
1381                         many.vitals.push.apply(many.vitals, theone);
1382                 }
1383         } else if (count === 1) {
1384                 theone = populateVital(pd.history_physical.vitals_list.vitals);
1385                 many.vitals.push(theone);
1386         }
1387         data.vitals = Object.assign(many.vitals);
1388         // Medications
1389         var meds = [];
1390         var m = {};
1391         meds.medications = [];
1392         try{
1393                 count = isOne(pd.medications.medication);
1394         }catch(e){count = 0}    
1395         if (count > 1) {
1396                 for ( var i in pd.medications.medication) {
1397                         m[i] = populateMedication(pd.medications.medication[i]);
1398                         meds.medications.push(m[i]);
1399                 }
1400         } else if (count !== 0) {
1401                 m = populateMedication(pd.medications.medication);
1402                 meds.medications.push(m);
1403         }
1404         data.medications = Object.assign(meds.medications);
1405         // Encounters
1406         var encs = [];
1407         var enc = {};
1408         encs.encounters = [];
1409         try{
1410                 count = isOne(pd.encounter_list.encounter);
1411         }catch(e){count = 0}    
1412         if (count > 1) {
1413                 for ( var i in pd.encounter_list.encounter) {
1414                         enc[i] = populateEncounter(pd.encounter_list.encounter[i]);
1415                         encs.encounters.push(enc[i]);
1416                 }
1417         } else if (count !== 0) {
1418                 enc = populateEncounter(pd.encounter_list.encounter);
1419                 encs.encounters.push(enc);
1420         }
1421         data.encounters = Object.assign(encs.encounters);
1422         // Allergies
1423         var allergies = [];
1424         var allergy = {};
1425         allergies.allergies = [];
1426         try{
1427                 count = isOne(pd.allergies.allergy);
1428         }catch(e){count = 0}
1429         if (count > 1) {
1430                 for ( var i in pd.allergies.allergy) {
1431                         allergy[i] = populateAllergy(pd.allergies.allergy[i]);
1432                         allergies.allergies.push(allergy[i]);
1433                 }
1434         } else if (count !== 0) {
1435                 allergy = populateAllergy(pd.allergies.allergy);
1436                 allergies.allergies.push(allergy);
1437         }
1438         data.allergies = Object.assign(allergies.allergies);
1439         // Problems
1440         var problems = [];
1441         var problem = {};
1442         problems.problems = [];
1443         try{
1444                 count = isOne(pd.problem_lists.problem);
1445         }catch(e){count = 0}
1446         if (count > 1) {
1447                 for ( var i in pd.problem_lists.problem) {
1448                         problem[i] = populateProblem(pd.problem_lists.problem[i]);
1449                         problems.problems.push(problem[i]);
1450                 }
1451         } else if (count !== 0) {
1452                 problem = populateProblem(pd.problem_lists.problem);
1453                 problems.problems.push(problem);
1454         }
1455         data.problems = Object.assign(problems.problems);
1456         // Procedures
1457         many = [];
1458         theone = {};
1459         many.procedures = [];
1460         try{
1461                 count = isOne(pd.procedures.procedure);
1462         }catch(e){count = 0}
1463         if (count > 1) {
1464                 for ( var i in pd.procedures.procedure) {
1465                         theone[i] = populateProcedure(pd.procedures.procedure[i]);
1466                         many.procedures.push(theone[i]);
1467                 }
1468         } else if (count !== 0) {
1469                 theone = populateProcedure(pd.procedures.procedure);
1470                 many.procedures.push(theone);
1471         }
1472         data.procedures = Object.assign(many.procedures);
1473         // Results
1474         data.results = Object.assign(getResultSet(pd.results)['results']);
1475         // Immunizations
1476         many = [];
1477         theone = {};
1478         many.immunizations = [];
1479         try{
1480                 count = isOne(pd.immunizations.immunization);
1481         }catch(e){count = 0;}
1482         if (count > 1) {
1483                 for ( var i in pd.immunizations.immunization) {
1484                         theone[i] = populateImmunization(pd.immunizations.immunization[i]);
1485                         many.immunizations.push(theone[i]);
1486                 }
1487         } else if (count !== 0) {
1488                 theone = populateImmunization(pd.immunizations.immunization);
1489                 many.immunizations.push(theone);
1490         }
1491         data.immunizations = Object.assign(many.immunizations);
1492         // Plan of Care
1493         many = [];
1494         theone = {};
1495         many.plan_of_care = [];
1496         try{
1497                 count = isOne(pd.planofcare); // ccm doesn't send array of items
1498         }catch(e){count = 0}
1499         if (count > 1) {
1500                 for ( var i in pd.planofcare.item) {
1501                         theone[i] = getPlanOfCare(pd.planofcare.item[i]);
1502                         many.plan_of_care.push(theone[i]);
1503                 }
1504         } else if (count !== 0) {
1505                 theone = getPlanOfCare(pd.planofcare.item);
1506                 many.plan_of_care.push(theone);
1507         }
1508         data.plan_of_care = Object.assign(many.plan_of_care);
1509         // Social History
1510         many = [];
1511         theone = {};
1512         many.social_history = [];
1513         try{
1514                 count = isOne(pd.history_physical.social_history.history_element);
1515         }catch(e){count = 0}
1516         if (count > 1) {
1517                 for ( var i in pd.history_physical.social_history.history_element) {
1518                         theone[i] = populateSocialHistory(pd.history_physical.social_history.history_element[i]);
1519                         many.social_history.push(theone[i]);
1520                 }
1521         } else if (count !== 0) {
1522                 theone = populateSocialHistory(pd.history_physical.social_history.history_element);
1523                 many.social_history.push(theone);
1524         }
1525         data.social_history = Object.assign(many.social_history);
1527         // ------------------------------------------ End Sections -------------------------------------------------//
1529         doc.data = Object.assign(data);
1531         var xml = bbg.generateCCD(doc);
1532         //console.log(xml)
1533         return xml;
1536 function processConnection( connection ) {
1537         conn = connection; // make it global
1538         var remoteAddress = conn.remoteAddress + ':' + conn.remotePort;
1539         console.log(remoteAddress);
1540         conn.setEncoding('utf8');
1541         function eventData(xml) {
1542                 xml = xml.replace(/(\u000b|\u001c)/gm, "").trim();
1543                 // Sanity check from service manager
1544                 if (xml === 'status' || xml.length < 80) {
1545                         conn.write("statusok" + String.fromCharCode(28) + "\r\r");
1546                         conn.end('');
1547                         return;
1548                 }
1549                 var doc = "";
1550                 to_json(xml, function(error, data) {
1551                         // console.log(JSON.stringify(data, null, 4));
1552                         if (error) { // need try catch
1553                                 console.log(error);
1554                                 return;
1555                         }
1556                         doc = genCcda( data.CCDA );
1557                 });
1558                 doc = headReplace(doc);
1559                 doc = doc.toString().replace(/(\u000b|\u001c|\r)/gm, "").trim();
1560                 //console.log(doc)
1561                 // var justuwait = new Date(new Date().getTime() + 1 * 1000);
1562                 // while(justuwait > new Date()){}
1563                 // Document length is anywhere from 50k to 125K so lets not flood poor ole php's socket buffer
1564                 // not really throttled though...
1565                 var chunk = "";
1566                 var numChunks = Math.ceil(doc.length / 1024);
1567                 for (var i = 0, o = 0; i < numChunks; ++i, o += 1024) {
1568                         chunk = doc.substr(o, 1024);
1569                         conn.write(chunk);
1570                 }
1571                 // Php is sensitive to ending read stream and CCM chops last three bytes
1572                 // empty string ends read and char 28 is xfer end (php doesn't care but CCM used so, I will also).
1573                 conn.write(String.fromCharCode(28) + "\r\r" + '');
1574                 conn.end();
1575                 /*By parsing doc just created we can see any nullFlavors or missing parts
1576                 console.log("total=" + conn.bytesWritten);
1577                 remove for production - test validation of doc just created
1578                 var data = bb.parse(doc);
1579                 console.log(JSON.stringify(data.errors, null, 4));*/
1580         }
1581         function eventCloseConn() {
1582                 //console.log('connection from %s closed', remoteAddress);
1583         }
1584         function eventErrorConn(err) {
1585                 //console.log('Connection %s error: %s', remoteAddress, err.message);
1586         }
1587         // Connection Events //
1588         conn.on('data', eventData);
1589         conn.once('close', eventCloseConn);
1590         conn.on('error', eventErrorConn);
1592 function setUp(server) {
1593         server.on('connection', processConnection);
1594         server.listen(6661, 'localhost', function() {
1595                 //console.log('server listening to %j', server.address());
1596         });
1598 setUp(server);