| /////////////////////////////////////////////////////////////////////////////// |
| // |
| // Copyright (c) 2000-2017 Ericsson Telecom AB |
| // |
| // All rights reserved. This program and the accompanying materials |
| // are made available under the terms of the Eclipse Public License v1.0 |
| // which accompanies this distribution, and is available at |
| // http://www.eclipse.org/legal/epl-v10.html |
| /////////////////////////////////////////////////////////////////////////////// |
| // File: LightweightM2M_CoAP_Binding.ttcn |
| // Description: |
| // Rev: R1A |
| // Prodnr: LPA 108 661 |
| // Updated: 2017-09-01 |
| // Contact: http://ttcn.ericsson.se |
| /////////////////////////////////////////////////////////////////////////////// |
| module LightweightM2M_CoAP_Binding { |
| |
| import from LightweightM2M_Types all; |
| import from CoAP_Types all; |
| |
| function f_enc_LWM2M_to_COAP(in LWM2M_PDU p_lwm2m, inout CoAP_ReqResp p_coap) |
| return boolean |
| { |
| if (ischosen(p_lwm2m.Register)) |
| { |
| p_coap := valueof(t_coap_base(METHOD_POST, CONFIRMABLE)); |
| |
| f_addOption(p_coap, { uri_path := "rd" }); |
| f_addOption(p_coap, { content_format := 40 }); |
| f_addOption(p_coap, { uri_query := "ep=" & p_lwm2m.Register.endpointClientName }); |
| |
| if (ispresent(p_lwm2m.Register.lifetime)) { |
| f_addOption(p_coap, { uri_query := "lt=" & int2str(p_lwm2m.Register.lifetime) }); |
| } |
| if (ispresent(p_lwm2m.Register.version)) { |
| f_addOption(p_coap, { uri_query := "lwm2m=" & p_lwm2m.Register.version }); |
| } |
| if (ispresent(p_lwm2m.Register.bindingMode)) { |
| f_addOption(p_coap, { uri_query := "b=" & f_BindingMode2str(p_lwm2m.Register.bindingMode) }); |
| } |
| if (ispresent(p_lwm2m.Register.smsNumber)) { |
| f_addOption(p_coap, { uri_query := "sms=" & int2str(p_lwm2m.Register.smsNumber) }); |
| } |
| if (sizeof(p_lwm2m.Register.objectsAndObjectInstances)>0) { |
| f_addOption(p_coap, { content_format := 40 }); |
| p_coap.payload := char2oct(f_ObjectPathList2str(p_lwm2m.Register.objectsAndObjectInstances)); |
| } |
| } |
| else if (ischosen(p_lwm2m.Update)) |
| { |
| p_coap := valueof(t_coap_base(METHOD_PUT, CONFIRMABLE)); |
| |
| f_addLocation(p_coap, p_lwm2m.Update.location); |
| |
| if (ispresent(p_lwm2m.Update.lifetime)) { |
| f_addOption(p_coap, { uri_query := "lt=" & int2str(p_lwm2m.Update.lifetime) }); |
| } |
| if (ispresent(p_lwm2m.Update.bindingMode)) { |
| f_addOption(p_coap, { uri_query := "b=" & f_BindingMode2str(p_lwm2m.Update.bindingMode) }); |
| } |
| if (ispresent(p_lwm2m.Update.smsNumber)) { |
| f_addOption(p_coap, { uri_query := "sms=" & int2str(p_lwm2m.Update.smsNumber) }); |
| } |
| if (sizeof(p_lwm2m.Update.objectsAndObjectInstances)>0) { |
| f_addOption(p_coap, { content_format := 40 }); |
| p_coap.payload := char2oct(f_ObjectPathList2str(p_lwm2m.Update.objectsAndObjectInstances)); |
| } |
| } |
| else if (ischosen(p_lwm2m.Deregister)) |
| { |
| p_coap := valueof(t_coap_base(METHOD_DELETE, CONFIRMABLE)); |
| |
| f_addLocation(p_coap, p_lwm2m.Deregister.location); |
| } |
| else if (ischosen(p_lwm2m.Response)) |
| { |
| p_coap := valueof(t_coap_base(f_int2Code(p_lwm2m.Response.code), ACKNOWLEDGEMENT)); |
| f_addLocation(p_coap, p_lwm2m.Response.location); |
| if (ispresent(p_lwm2m.Response.contentFormat)) { |
| f_addContentFormat(p_coap, p_lwm2m.Response.contentFormat); |
| } |
| //if (ispresent(p_lwm2m.Response.observe)) { |
| // f_addOption(p_coap, {observe := p_lwm2m.Response.observe.observe}); |
| // p_coap.token := p_lwm2m.Response.observe.token; |
| //} |
| p_coap.payload := f_enc_LwM2M_Resources_to_JSON(p_lwm2m.Response.resources); |
| } |
| else |
| { |
| log(%definitionId," Unhandled message type in LWM2M_PDU"); |
| return false; |
| } |
| return true; |
| } |
| |
| function f_dec_COAP_to_LWM2M(in CoAP_ReqResp p_coap, inout LWM2M_PDU p_lwm2m) |
| return boolean |
| { |
| if (p_coap.header.code.class > 0) |
| { |
| p_lwm2m := c_LWM2M_Response_init; |
| p_lwm2m.Response.code := f_Code2int(p_coap.header.code); |
| if (ispresent(p_coap.options)) { |
| f_fetchLocation(p_coap.options, p_lwm2m.Response.location); |
| } |
| return true; |
| } |
| else if (p_coap.header.code == METHOD_GET) |
| { |
| p_lwm2m := c_LWM2M_Read_init; |
| var Location v_loc := {}; |
| f_fetchUriPath(p_coap.options, v_loc); |
| f_LocationToObjectPath(v_loc, p_lwm2m.Read_.path); |
| f_fetchAccept(p_coap.options, p_lwm2m.Read_.accept); |
| var integer p_obs := -1; |
| /* |
| if (f_fetchObserve(p_coap.options, p_obs)) { |
| p_lwm2m.Read_.observe := { |
| observe := p_obs, |
| token := p_coap.token |
| } |
| } |
| */ |
| return true; |
| } |
| else if (p_coap.header.code == METHOD_PUT) |
| { |
| p_lwm2m := c_LWM2M_Write_init; |
| var Location v_loc := {}; |
| f_fetchUriPath(p_coap.options, v_loc); |
| f_LocationToObjectPath(v_loc, p_lwm2m.Write.path); |
| f_fetchContentFormat(p_coap.options, p_lwm2m.Write.contentFormat); |
| if (p_lwm2m.Write.contentFormat == 1543) |
| { // JSON |
| var LwM2M_JSON_Resources v_decoded_json; |
| v_decoded_json := f_dec_LwM2M_JSON_Resources(p_coap.payload); |
| action("Decoded json: ", v_decoded_json); |
| p_lwm2m.Write.resources := f_LwM2M_JSON_Resources_toResources(v_decoded_json); |
| p_lwm2m.Write.resources[0].objId := p_lwm2m.Write.path.objectId; |
| p_lwm2m.Write.resources[0].objInstId := p_lwm2m.Write.path.objectInstanceId; |
| p_lwm2m.Write.resources[0].id:= p_lwm2m.Write.path.resourceId; |
| } |
| return true; |
| } |
| else if (p_coap.header.code == METHOD_POST) |
| { |
| var Location v_loc := {}; |
| f_fetchUriPath(p_coap.options, v_loc); |
| if (sizeof(v_loc)==3) |
| { // Execute |
| p_lwm2m := c_LWM2M_Execute_init; |
| f_LocationToObjectPath(v_loc, p_lwm2m.Execute.path); |
| } |
| else |
| { // Create |
| p_lwm2m := c_LWM2M_Create_init; |
| f_LocationToObjectPath(v_loc, p_lwm2m.Execute.path); |
| } |
| return true; |
| } |
| else if (p_coap.header.code == METHOD_DELETE) |
| { |
| p_lwm2m := c_LWM2M_Delete_init; |
| var Location v_loc := {}; |
| f_fetchUriPath(p_coap.options, v_loc); |
| f_LocationToObjectPath(v_loc, p_lwm2m.Delete.path); |
| return true; |
| } |
| else |
| { |
| log(%definitionId," Unrecognized lwm2m pdu in coap ", p_coap); |
| return false; |
| } |
| return false; |
| } |
| |
| function f_ObjectPath2str(ObjectPath p_op) |
| return charstring |
| { |
| var charstring v_ret := "</" & int2str(p_op.objectId); |
| |
| if (ispresent(p_op.objectInstanceId)) { |
| v_ret := v_ret & "/" & int2str(p_op.objectInstanceId); |
| } |
| if (ispresent(p_op.resourceId)) { |
| v_ret := v_ret & "/" & int2str(p_op.resourceId); |
| } |
| |
| return v_ret & ">"; |
| } |
| |
| function f_ObjectPathList2str(ObjectPath_List p_ol) |
| return charstring |
| { |
| var charstring v_ret := ""; |
| for (var integer i:=0; i<sizeof(p_ol); i:=i+1) |
| { |
| v_ret := v_ret & f_ObjectPath2str(p_ol[i]); |
| if (i != sizeof(p_ol)-1) { v_ret := v_ret & "," } |
| } |
| return v_ret; |
| } |
| |
| function f_LocationToObjectPath(in Location p_location, inout ObjectPath p_path) |
| { |
| if (sizeof(p_location) >= 1) { p_path.objectId := str2int(oct2char(unichar2oct(p_location[0]))); } |
| else { p_path.objectId := -1 } |
| |
| if (sizeof(p_location) >= 2) { p_path.objectInstanceId := str2int(oct2char(unichar2oct(p_location[1]))); } |
| else { p_path.objectInstanceId := omit } |
| |
| if (sizeof(p_location) >= 3) { p_path.resourceId := str2int(oct2char(unichar2oct(p_location[2]))); } |
| else { p_path.resourceId := omit } |
| } |
| |
| function f_BindingMode2str(BindingMode p_b) |
| return charstring |
| { |
| if (p_b == U) { |
| return "U"; |
| } |
| else if (p_b == UQ) { |
| return "UQ"; |
| } |
| else if (p_b == S) { |
| return "S"; |
| } |
| else if (p_b == SQ) { |
| return "SQ"; |
| } |
| else if (p_b == US) { |
| return "US"; |
| } |
| else if (p_b == UQS) { |
| return "UQS"; |
| } |
| else { |
| log(%definitionId," Unrecognized binding mode: ", p_b) |
| return ""; |
| } |
| return ""; |
| } |
| |
| function f_addLocation(inout CoAP_ReqResp p_coap, in Location p_location) |
| { |
| for (var integer i:=0; i<sizeof(p_location); i:=i+1) |
| { |
| f_addOption(p_coap, { uri_path := p_location[i] } ); |
| } |
| } |
| |
| function f_addContentFormat(inout CoAP_ReqResp p_coap, in integer p_cf) |
| { |
| f_addOption(p_coap, { content_format := p_cf } ); |
| } |
| |
| function f_addOption(inout CoAP_ReqResp p_coap, in CoAP_Options p_option) |
| { |
| if (not ispresent(p_coap.options)) { p_coap.options := {} } |
| |
| p_coap.options[sizeof(p_coap.options)] := p_option; |
| } |
| |
| function f_Code2int(in Code p_code) |
| return integer |
| { |
| return p_code.class*100+p_code.detail; |
| } |
| |
| function f_int2Code(in integer p_code) |
| return Code |
| { |
| var Code v_ret; |
| v_ret.class := p_code/100; |
| v_ret.detail := p_code rem 100; |
| |
| return v_ret; |
| } |
| |
| function f_fetchLocation(in CoAP_OptionsList p_options, inout Location p_location) |
| { |
| for (var integer i:=0; i<sizeof(p_options); i:=i+1) { |
| if (ischosen(p_options[i].location_path)) { |
| p_location[sizeof(p_location)] := p_options[i].location_path; |
| } |
| } |
| } |
| |
| function f_fetchUriPath(in CoAP_OptionsList p_options, inout Location p_location) |
| { |
| for (var integer i:=0; i<sizeof(p_options); i:=i+1) { |
| if (ischosen(p_options[i].uri_path)) { |
| p_location[sizeof(p_location)] := p_options[i].uri_path; |
| } |
| } |
| } |
| |
| function f_fetchAccept(in CoAP_OptionsList p_options, inout Integer_List p_accept) |
| { |
| for (var integer i:=0; i<sizeof(p_options); i:=i+1) { |
| if (ischosen(p_options[i].accept)) { |
| p_accept[sizeof(p_accept)] := p_options[i].accept; |
| } |
| } |
| } |
| |
| /* |
| function f_fetchObserve(in CoAP_OptionsList p_options, inout integer p_observe) |
| return boolean |
| { |
| for (var integer i:=0; i<sizeof(p_options); i:=i+1) { |
| if (ischosen(p_options[i].observe)) { |
| p_observe := p_options[i].observe; |
| return true; |
| } |
| } |
| return false; |
| } |
| */ |
| |
| function f_fetchContentFormat(in CoAP_OptionsList p_options, inout integer p_cf) |
| { |
| for (var integer i:=0; i<sizeof(p_options); i:=i+1) { |
| if (ischosen(p_options[i].content_format)) { |
| p_cf := p_options[i].content_format; |
| } |
| } |
| } |
| |
| template CoAP_ReqResp t_coap_base(Code p_code, Type p_type) := |
| { |
| header := |
| { |
| version := 1, |
| msg_type := p_type, |
| code := p_code, |
| message_id := 0 |
| }, |
| token := ''O, |
| options := {}, |
| payload := omit |
| } |
| } |