title: Convert (ASN.1) BCD value to human-readable string
body: <p>Hi I have a hexadecimal value produced by decoding CDR file in which the property type is an Octet String data type (ANS.1 syntax). I want to convert/interpret the BCD(hexadecimal string) to human readable string value.</p>
  
  <p>Here's the output of the decoded cdr file using MARBEN ASN.1 CDR Converter.</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;CallEventRecord&gt;
     &lt;pGWRecord&gt;
        &lt;recordType&gt;85&lt;/recordType&gt;
        &lt;servedIMSI&gt;15650000000010F5&lt;/servedIMSI&gt;
        &lt;pGWAddress&gt;
           &lt;iPBinaryAddress&gt;
              &lt;iPBinV4Address&gt;674B8802&lt;/iPBinV4Address&gt;
           &lt;/iPBinaryAddress&gt;
        &lt;/pGWAddress&gt;
        &lt;chargingID&gt;10932225&lt;/chargingID&gt;
        &lt;servingNodeAddress&gt;
           &lt;iPBinaryAddress&gt;
              &lt;iPBinV4Address&gt;674B8802&lt;/iPBinV4Address&gt;
           &lt;/iPBinaryAddress&gt;
        &lt;/servingNodeAddress&gt;
        &lt;accessPointNameNI&gt;test.be.ph&lt;/accessPointNameNI&gt;
        &lt;pdpPDNType&gt;0001&lt;/pdpPDNType&gt;
        &lt;servedPDPPDNAddress&gt;
           &lt;iPAddress&gt;
              &lt;iPBinaryAddress&gt;
                 &lt;iPBinV4Address&gt;0A010505&lt;/iPBinV4Address&gt;
              &lt;/iPBinaryAddress&gt;
           &lt;/iPAddress&gt;
        &lt;/servedPDPPDNAddress&gt;
        &lt;dynamicAddressFlag&gt;
           &lt;true /&gt;
        &lt;/dynamicAddressFlag&gt;
        &lt;listOfTrafficVolumes&gt;
           &lt;ChangeOfCharCondition&gt;
              &lt;dataVolumeGPRSUplink&gt;775838&lt;/dataVolumeGPRSUplink&gt;
              &lt;dataVolumeGPRSDownlink&gt;1321848&lt;/dataVolumeGPRSDownlink&gt;
              &lt;changeCondition&gt;
                 &lt;recordClosure /&gt;
              &lt;/changeCondition&gt;
              &lt;changeTime&gt;1705161557142B0800&lt;/changeTime&gt;
           &lt;/ChangeOfCharCondition&gt;
        &lt;/listOfTrafficVolumes&gt;
        &lt;recordOpeningTime&gt;1705161547452B0800&lt;/recordOpeningTime&gt;
        &lt;duration&gt;569&lt;/duration&gt;
        &lt;causeForRecClosing&gt;16&lt;/causeForRecClosing&gt;
        &lt;recordSequenceNumber&gt;36&lt;/recordSequenceNumber&gt;
        &lt;nodeID&gt;isp.com&lt;/nodeID&gt;
        &lt;localSequenceNumber&gt;1000035&lt;/localSequenceNumber&gt;
        &lt;apnSelectionMode&gt;
           &lt;mSorNetworkProvidedSubscriptionVerified /&gt;
        &lt;/apnSelectionMode&gt;
        &lt;servedMSISDN&gt;368909000032&lt;/servedMSISDN&gt;
        &lt;chargingCharacteristics&gt;0800&lt;/chargingCharacteristics&gt;
        &lt;chChSelectionMode&gt;
           &lt;servingNodeSupplied /&gt;
        &lt;/chChSelectionMode&gt;
        &lt;servingNodePLMNIdentifier&gt;15F506&lt;/servingNodePLMNIdentifier&gt;
        &lt;rATType&gt;6&lt;/rATType&gt;
        &lt;mSTimeZone&gt;2300&lt;/mSTimeZone&gt;
        &lt;userLocationInformation&gt;1815F506000115F5060F424100&lt;/userLocationInformation&gt;
        &lt;servingNodeType&gt;
           &lt;ServingNodeType&gt;
              &lt;gTPSGW /&gt;
           &lt;/ServingNodeType&gt;
        &lt;/servingNodeType&gt;
     &lt;/pGWRecord&gt;
  &lt;/CallEventRecord&gt;
  </code></pre>
  
  <p>Like the <code>&lt;servedIMSI&gt;15650000000010F5&lt;/servedIMSI&gt;</code> and the <code>&lt;iPBinV4Address&gt;674B8802&lt;/iPBinV4Address&gt;</code>. For reference, the actual value of servedIMSI is 515600000000015 and for iPBinV4Address is 103.75.136.2. I am trying to figure out how can I be able to format the values to human readable string using nodejs.</p>
  
  <p>Below are ASN.1 specification for the said two properties</p>
  
  <pre><code>IPBinV4Address  ::= OCTET STRING (SIZE(4))
  
  IMSI ::= TBCD-STRING (SIZE (3..8))
  
  TBCD-STRING ::= OCTET STRING
      -- This type (Telephony Binary Coded Decimal String) is used to
      -- represent several digits from 0 through 9, *, #, a, b, c, two
      -- digits per octet, each digit encoded 0000 to 1001 (0 to 9),
      -- 1010 (*), 1011 (#), 1100 (a), 1101 (b) or 1110 (c); 1111 used
      -- as filler when there is an odd number of digits.
      -- bits 8765 of octet n encoding digit 2n
      -- bits 4321 of octet n encoding digit 2(n-1) +1
  </code></pre>
  
  <p>Any help will be appreciated.</p>