| /////////////////////////////////////////////////////////////////////////////// |
| // |
| // Copyright (c) 2000-2019 Ericsson Telecom AB |
| // |
| // All rights reserved. This program and the accompanying materials |
| // are made available under the terms of the Eclipse Public License v2.0 |
| // which accompanies this distribution, and is available at |
| // https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html |
| /////////////////////////////////////////////////////////////////////////////// |
| // File: LWM2M_TLV_EncDec.ttcn |
| // Description: |
| // Rev: R1A |
| // Prodnr: CNL 113 859 |
| // Updated: 2019-08-27 |
| // Contact: http://ttcn.ericsson.se |
| /////////////////////////////////////////////////////////////////////////////// |
| module LWM2M_TLV_EncDec |
| { |
| import from LWM2M_TLV_Types all; |
| import from LightweightM2M_Types all; |
| |
| modulepar boolean tsp_LWM2M_TLV_EncDec_debug := false; |
| const boolean c_LWM2M_TLV_debugSwitch := false; |
| |
| function f_dec_LwM2M_TLV_Resources(in octetstring p_raw_msg) return LWM2M_TLV_Resources { |
| var integer v_procedBits := 0; |
| var bitstring v_msgInBits := oct2bit(p_raw_msg); |
| var LWM2M_TLV_Resources v_ret_tlvs := {}; |
| |
| while(v_procedBits != lengthof(v_msgInBits)) { |
| v_ret_tlvs[sizeof(v_ret_tlvs)] := f_dec_LwM2M_TLV_Resource(v_msgInBits, v_procedBits); |
| } |
| |
| return v_ret_tlvs; |
| } |
| |
| //TODO: Multiple resource TLV |
| function f_dec_LwM2M_TLV_Resource(in bitstring p_raw_msg, inout integer p_firstBit) return LWM2M_TLV_Resource |
| { |
| var LWM2M_TLV_Resource v_ret_tlv; |
| |
| f_TLV_debug("-----------------------------TLV Decoding-----------------------------"); |
| f_dec_TLV_Type(substr(p_raw_msg, p_firstBit, 8), v_ret_tlv.tlv_type); |
| p_firstBit := p_firstBit + 8; |
| |
| v_ret_tlv.id := bit2int(substr(p_raw_msg, p_firstBit, v_ret_tlv.tlv_type.length_of_id)) |
| p_firstBit := p_firstBit + 8; |
| |
| if(v_ret_tlv.tlv_type.type_of_length == 0) { |
| v_ret_tlv.length_of_value := v_ret_tlv.tlv_type.length_of_value; |
| } |
| else{ |
| v_ret_tlv.length_of_value := bit2int(substr(p_raw_msg, p_firstBit, v_ret_tlv.tlv_type.type_of_length)) * 8; |
| p_firstBit := p_firstBit + v_ret_tlv.tlv_type.type_of_length; |
| } |
| f_TLV_debug(log2str("tlv_type: ", v_ret_tlv)); |
| |
| var bitstring v_rawValue := substr(p_raw_msg, p_firstBit, v_ret_tlv.length_of_value); |
| //f_TLV_debug(log2str("v_rawValue: ", v_rawValue)); |
| |
| if(v_ret_tlv.tlv_type.type_of_id == OBJECT_INSTANCE or v_ret_tlv.tlv_type.type_of_id == MULTIPLE_RESOURCE){ |
| f_TLV_debug("Decoding internal TLV"); |
| var integer v_tmpLength := 0; |
| var integer idx := 0; |
| while(v_tmpLength != lengthof(v_rawValue)){ |
| v_ret_tlv.tlv_value.internal_tlvs[idx] := f_dec_LwM2M_TLV_Resource(v_rawValue, v_tmpLength); |
| idx := idx + 1; |
| } |
| p_firstBit := p_firstBit + v_ret_tlv.length_of_value; |
| } |
| else { |
| v_ret_tlv.tlv_value.raw_resource_value := v_rawValue; |
| p_firstBit := p_firstBit + v_ret_tlv.length_of_value; |
| } |
| f_TLV_debug(log2str("Decoded TLV: ", v_ret_tlv)); |
| return v_ret_tlv; |
| } |
| |
| function f_dec_TLV_Type(in bitstring p_bitstring, inout TLV_Type p_tlv_type) |
| { |
| p_tlv_type.length_of_value := bit2int(p_bitstring[5] & p_bitstring[6] & p_bitstring[7]) * 8; |
| p_tlv_type.type_of_length := bit2int(p_bitstring[3] & p_bitstring[4]) * 8; |
| p_tlv_type.length_of_id := bit2int(p_bitstring[2]) * 8 + 8; |
| |
| var bitstring v_tmp := p_bitstring[0] & p_bitstring[1] |
| if(v_tmp == '00'B) { |
| p_tlv_type.type_of_id := OBJECT_INSTANCE; |
| } |
| else if(v_tmp == '01'B) { |
| p_tlv_type.type_of_id := RESOURCE_INSTANCE; |
| } |
| else if(v_tmp == '10'B) { |
| p_tlv_type.type_of_id := MULTIPLE_RESOURCE; |
| } |
| else { |
| p_tlv_type.type_of_id := VALUE; |
| } |
| } |
| |
| function f_dec_resource_value(in bitstring p_raw_value, in Value_Type p_vType, inout LwM2M_ResourceValue p_res_value) |
| { |
| if(p_vType == STRING) { |
| var octetstring tmp := bit2oct(p_raw_value); |
| p_res_value.strValue := ""; |
| for(var integer i := 0; i < lengthof(tmp); i := i+1){ |
| p_res_value.strValue := p_res_value.strValue & int2char(oct2int(tmp[i])); |
| } |
| } |
| else if(p_vType == INTEGER) { |
| var integer tmp := decvalue(p_raw_value, p_res_value.intValue); |
| } |
| else if(p_vType == FLOAT) { |
| f_TLV_debug("Float type not yet handled"); |
| //TODO: float |
| p_res_value.floatValue := 0.0 |
| |
| } |
| else if(p_vType == OPAQUE) { |
| p_res_value.opaqueValue := bit2oct(p_raw_value); |
| } |
| else if(p_vType == BOOL) { |
| p_res_value.boolValue := int2bool(bit2int(p_raw_value)); |
| } |
| } |
| |
| function f_LwM2M_TLV_Resources_toResources(in LWM2M_TLV_Resources p_tlv_res, Location p_loc) return LwM2M_Resource_List |
| { |
| var LwM2M_Resource_List v_resource_list; |
| |
| f_TLV_debug(log2str("p_tlv_res: ", p_tlv_res)); |
| f_TLV_debug(log2str("p_loc: ", p_loc)); |
| |
| for(var integer i := 0; i < sizeof(p_tlv_res); i := i+1) |
| { |
| var LWM2M_TLV_Resource v_tmpTLV := p_tlv_res[i]; |
| |
| v_resource_list[i].objId := str2int(oct2char(unichar2oct(p_loc[0]))); |
| if(sizeof(p_loc) >= 2){ |
| v_resource_list[i].objInstId := str2int(oct2char(unichar2oct(p_loc[1]))); |
| } |
| |
| v_resource_list[i].observed := false; |
| v_resource_list[i].dataSample := omit; |
| |
| if(v_tmpTLV.tlv_type.type_of_id == VALUE or v_tmpTLV.tlv_type.type_of_id == RESOURCE_INSTANCE) |
| { |
| v_resource_list[i].id := v_tmpTLV.id; |
| var ObjectPath v_path := { v_resource_list[i].objId, v_resource_list[i].objInstId, v_resource_list[i].id } |
| |
| f_TLV_debug(log2str("Path: ", v_path)); |
| //v_resource_list[i].val.strValue := ""; |
| f_dec_resource_value(v_tmpTLV.tlv_value.raw_resource_value, f_get_ResourceType(v_path), v_resource_list[i].val); |
| } |
| else if(v_tmpTLV.tlv_type.type_of_id == OBJECT_INSTANCE) |
| { |
| v_resource_list[i].objInstId := v_tmpTLV.id; |
| if(v_tmpTLV.tlv_value.internal_tlvs[0].tlv_type.type_of_id == RESOURCE_INSTANCE) |
| { |
| var LwM2M_Resource_List v_tmp_resource_list; |
| v_tmp_resource_list := f_LwM2M_TLV_Resources_toResources(v_tmpTLV.tlv_value.internal_tlvs, p_loc); |
| for(var integer j := 0; j < sizeof(v_tmp_resource_list); j := j+ 1) { |
| v_resource_list[i + j] := v_tmp_resource_list[j]; |
| } |
| } |
| else |
| { |
| var LwM2M_Resource_List v_tmp_resource_list; |
| v_tmp_resource_list := f_LwM2M_TLV_Resources_toResources(v_tmpTLV.tlv_value.internal_tlvs, p_loc); |
| } |
| } |
| else if(v_tmpTLV.tlv_type.type_of_id == MULTIPLE_RESOURCE) |
| { |
| var LwM2M_Resource_List v_tmp_resource_list; |
| v_tmp_resource_list := f_LwM2M_TLV_Resources_toResources(v_tmpTLV.tlv_value.internal_tlvs, p_loc); |
| for(var integer j := 0; j < sizeof(v_tmp_resource_list); j := j+ 1) { |
| v_resource_list[i + j] := v_tmp_resource_list[j]; |
| } |
| } |
| } |
| |
| f_TLV_debug(log2str("v_resource_list: ", v_resource_list)); |
| |
| return v_resource_list; |
| } |
| |
| function f_get_ResourceType(in ObjectPath p_path) return Value_Type |
| { |
| var integer v_objId := p_path.objectId; |
| var integer v_resId := p_path.resourceId; |
| for(var integer i := 0; i < sizeof(c_LWM2M_Resource_Types); i:= i+1) |
| { |
| if(c_LWM2M_Resource_Types[i].objId == v_objId) |
| { |
| for(var integer j := 0; j < sizeof(c_LWM2M_Resource_Types[i].resType); j := j+1) |
| { |
| if(c_LWM2M_Resource_Types[i].resType[j].resId == v_resId) { |
| f_TLV_debug(log2str("Resource type found: ", c_LWM2M_Resource_Types[i].resType[j].valType)); |
| return c_LWM2M_Resource_Types[i].resType[j].valType; |
| } |
| } |
| } |
| } |
| f_TLV_debug("Resource type not found."); |
| return OPAQUE; |
| } |
| |
| function int2bool(integer p_int) return boolean |
| { |
| return (p_int mod 2 == 1) |
| } |
| |
| function f_TLV_debug(in @lazy charstring pl_message) |
| { |
| if (c_LWM2M_TLV_debugSwitch) { |
| if (tsp_LWM2M_TLV_EncDec_debug) { log(pl_message); } |
| } |
| } |
| } |