/** * Lookup the unit from the VIB (VIF or VIFE) */ public static function vib_unit_lookup($vib, $vib_nvife, $vif) { if ($vif == 0xfd) { if ($vib_nvife == 0) { return "Missing VIF extension"; } else { if ($vib_nvife == 0x10) { // VIFE = E001 0000 Customer location return "Customer location"; } else { if ($vib_nvife == 0xc) { // E000 1100 Model / Version return "Model / Version"; } else { if ($vib_nvife == 0x11) { // VIFE = E001 0001 Customer return "Customer"; } else { if ($vib_nvife == 0x9) { // VIFE = E001 0110 Password return "Password"; } else { if ($vib_nvife == 0xb) { // VIFE = E000 1011 Parameter set identification return "Parameter set identification"; } else { if (($vib_nvife & 0x70) == 0x40) { // VIFE = E100 nnnn 10^(nnnn-9) V $n = $vib_nvife & 0xf; return "10^(" . mbus_utils::unit_prefix($n - 9) . ") V"; } else { if (($vib_nvife & 0x70) == 0x50) { // VIFE = E101 nnnn 10nnnn-12 A $n = $vib_nvife & 0xf; return "10^(" . mbus_utils::unit_prefix($n - 12) . ") A"; } else { if (($vib_nvife & 0xf0) == 0x70) { // VIFE = E111 nnn Reserved return "Reserved VIF extension"; } else { return "Unrecongized VIF extension: " . $vib_nvife; } } } } } } } } } return ""; } return mbus_utils::vif_unit_lookup($vif); // no extention, use VIF }
private function parseVariableData() { $i = 19; $record_num = 0; //mbus_utils::mylog("Read and parse variable data blocks from dataarray[$i-" . ($this->dataarray_len - 2) . "]"); while ($i < $this->dataarray_len - 2) { $record_num++; $this->varrecords[$record_num]["general"]["StartBytePosition"] = $i; $dif = $this->dataarray[$i]; $record_data_len = $dif & 0x7; $this->varrecords[$record_num]["dif"]["Data"] = mbus_utils::ByteToHex($dif); $this->varrecords[$record_num]["dif"]["DataLength"] = $record_data_len; if ($record_data_len == 0) { //mbus_utils::mylog("0x20 indicates no data, skip reading VIF."); $i++; unset($this->varrecords[$record_num]); // Clear any data from the record. $record_num--; continue; } $this->varrecords[$record_num]["dif"]["DataTypeOrLength"] = mbus_utils::getDataFieldType($dif); $this->varrecords[$record_num]["dif"]["ExtensionBitSet"] = ($dif & 0x80) == 0x80 ? "Yes" : "No"; $this->varrecords[$record_num]["dif"]["StorageNumLSB"] = $dif & 0x40; /** * The manufacturer data header (MDH) is made up by the character 0Fh or 1Fh and indicates the beginning of the manufacturer * specific part of the user data and should be omitted, if there is no manufacturer specific data. */ if (($dif & 0xff) == 0xf || ($dif & 0xff) == 0x1f) { if (($dif & 0xff) == 0x1f) { mbus_utils::mylog("0x1F indicates manufacturer specific part of the user data and more data to follow..."); } else { // mbus_utils::mylog("0x0F indicates manufacturer specific part of the user data and no more data."); } $this->varrecords[$record_num]["dif"]["data_type"] = "Manufacturer Data"; $i++; //mbus_utils::mylog("Just copy the remaining data as it is vendor specific"); while ($i < $this->dataarray_len - 2) { $this->varrecords[$record_num]["data"][] = $this->dataarray[$i]; $i++; // Increment byte pointer. } $this->varrecords[$record_num]["general"]["EndBytePosition"] = $i - 1; continue; } // DIFE // If bit 8 is set then this means there is another DIFE to come. $dife_count = 1; while (($this->dataarray[$i] & 0x80) == 0x80) { //mbus_utils::mylog("Found DIF extension " . $i); $i++; // Increment byte pointer. $dife = $this->dataarray[$i]; $this->varrecords[$record_num]["dife"][$dife_count]["Data"] = mbus_utils::ByteToHex($dife); $this->varrecords[$record_num]["dife"][$dife_count]["ExtensionBitSet"] = ($dife & 0x80) == 0x80 ? "Yes" : "No"; $this->varrecords[$record_num]["dife"][$dife_count]["Unit"] = $dife & 0x40; $this->varrecords[$record_num]["dife"][$dife_count]["Tariff"] = $dife & 0x30; $this->varrecords[$record_num]["dife"][$dife_count]["storage_num_msb"] = mbus_utils::ByteToHex($dife & 0xf); $dife_count++; } $i++; // Increment byte pointer. // VIF (Value Information Block) $vif = $this->dataarray[$i]; $this->varrecords[$record_num]['vif']['Data'] = mbus_utils::ByteToHex($vif); $this->varrecords[$record_num]["vif"]["ExtensionBitSet"] = ($vif & 0x80) == 0x80 ? "Yes" : "No"; $this->varrecords[$record_num]["vif"]["UnitAndMultiplier"] = mbus_utils::ByteToHex($vif & 0x7f); // VIFE //mbus_utils::mylog("VIF extension value [" . dechex(($this->dataarray[$i]) & 0x80) . "]"); $vife_count = 1; while (($this->dataarray[$i] & 0x80) == 0x80) { //mbus_utils::mylog("Found VIF extension " . $i); $this->varrecords[$record_num]['vife'][$vife_count]['data'] = mbus_utils::ByteToHex($this->dataarray[$i + 1]); $vife_count++; $i++; // Increment byte pointer. } $i++; // Increment byte pointer to first byte of real data. // If Variable Length data field, then need to determine the length. if (($dif & 0xd) == 0xd) { // mbus_utils::mylog("Calculate data length from the first byte of actual data."); if ($this->dataarray[$i] <= 0xbf) { $record_data_len = $this->dataarray[$i++]; // Note that 0x0A is a newline ascii character and it seems to be after the characters but not included in the length! $this->varrecords[$record_num]["dif"]["data_type"] = 'Variable ASCII String'; if ($this->dataarray[$i + $record_data_len] == 0xa) { //mbus_utils::mylog("Found new line at end of string that is not included in the length. Adding 1 to length."); $record_data_len += 1; } } else { if ($this->dataarray[$i] >= 0xc0 && $this->dataarray[$i] <= 0xcf) { $record_data_len = ($this->dataarray[$i++] - 0xc0) * 2; $this->varrecords[$record_num]["dif"]["data_type"] = 'Variable Postive BCD'; } else { if ($this->dataarray[$i] >= 0xd0 && $this->dataarray[$i] <= 0xdf) { $record_data_len = ($this->dataarray[$i++] - 0xd0) * 2; $this->varrecords[$record_num]["dif"]["data_type"] = 'Variable Negative BCD'; } else { if ($this->dataarray[$i] >= 0xe0 && $this->dataarray[$i] <= 0xef) { $record_data_len = $this->dataarray[$i++] - 0xe0; $this->varrecords[$record_num]["dif"]["data_type"] = 'Variable Binary'; } else { if ($this->dataarray[$i] >= 0xf0 && $this->dataarray[$i] <= 0xfa) { $record_data_len = $this->dataarray[$i++] - 0xf0; $this->varrecords[$record_num]["dif"]["data_type"] = 'Variable Floating Point'; } } } } } } //mbus_utils::mylog("Copy [" . $record_data_len . "] bytes of data."); $this->varrecords[$record_num]['dif']['Function'] = mbus_utils::getFunctionField(($dif & 0x30) >> 4); $this->varrecords[$record_num]['vif']['Unit'] = mbus_utils::vif_unit_lookup($vif); if ($this->varrecords[$record_num]['vif']['Unit'] == 'Plain Text' && $this->varrecords[$record_num]["dif"]["data_type"] != 'Variable ASCII String') { // First byte of data is length. $record_data_len = $this->dataarray[$i++]; // Get the value for the VIF data type. $this->varrecords[$record_num]["vif"]["DataLength"] = $record_data_len; for ($j = 0; $j < $record_data_len; $j++) { $this->varrecords[$record_num]["data"][] = $this->dataarray[$i]; $i++; } // Replace "Plain Text" with unit from data. $this->varrecords[$record_num]['vif']['Unit'] = mbus_utils::getValue($dif, $vif, $this->varrecords[$record_num]["data"]); // Set the actual value data length to the dif record. $record_data_len = $this->varrecords[$record_num]["dif"]["DataLength"]; // Set $vif to nothing so it doesn't think the next bit of data is plain text. $vif = 0x0; // Clear data out. unset($this->varrecords[$record_num]["data"]); } // Must be after parsing DIF and VIF as both of these can determine length. $this->varrecords[$record_num]["dif"]["DataLength"] = $record_data_len; //mbus_utils::mylog("Record [" . $record_num . "] Length [" . $record_data_len . "]"); for ($j = 0; $j < $record_data_len; $j++) { $this->varrecords[$record_num]["data"][] = $this->dataarray[$i]; $i++; } $this->varrecords[$record_num]['Value'] = mbus_utils::getValue($dif, $vif, $this->varrecords[$record_num]["data"]); $this->varrecords[$record_num]["general"]["EndBytePosition"] = $i - 1; $sbp = $this->varrecords[$record_num]['general']['StartBytePosition']; $ebp = $this->varrecords[$record_num]['general']['EndBytePosition']; if ($sbp < $ebp) { for ($i = $sbp; $i <= $ebp; $i++) { $this->varrecords[$record_num]['general']['DataInclHeader'] .= mbus_utils::ByteToHex($this->dataarray[$i]); } } } return true; }