Beispiel #1
2
void app_start(int, char**) {

	// setup the EthernetInterface
	eth.init();	// DHCP
	eth.connect();
	
	// initialize the ipv4 tcp/ip stack
	lwipv4_socket_init();

	// setup the M2MInterface
	srand(time(NULL));
	uint16_t port = rand() % 65535 + 12345;
	srv = M2MInterfaceFactory::create_interface(observer,endpoint,type,
		lifetime,port,domain,M2MInterface::UDP,M2MInterface::LwIP_IPv4,context_address);

	// setup the Security object		
	sec = M2MInterfaceFactory::create_security(M2MSecurity::M2MServer);
	sec->set_resource_value(M2MSecurity::M2MServerUri,address);
	sec->set_resource_value(M2MSecurity::SecurityMode, M2MSecurity::NoSecurity);

	// setup the Device object
	dev = M2MInterfaceFactory::create_device();
	dev->create_resource(M2MDevice::Manufacturer,"Freescale");
	dev->create_resource(M2MDevice::DeviceType,"frdm-k64f");
	dev->create_resource(M2MDevice::ModelNumber,"M64FN1MOVLL12");
	dev->create_resource(M2MDevice::SerialNumber,"EB1524XXXX");

	// setup the sensor objects
	obj = M2MInterfaceFactory::create_object("loc");
	M2MObjectInstance* ins = obj->create_object_instance();
	M2MResource* resx = ins->create_dynamic_resource("x","accel",M2MResourceInstance::INTEGER,true);
	resx->set_operation(M2MBase::GET_PUT_ALLOWED);
	resx->set_value((const uint8_t*)"0",1);
	M2MResource* resy = ins->create_dynamic_resource("y","accel",M2MResourceInstance::INTEGER,true);
	resy->set_operation(M2MBase::GET_PUT_ALLOWED);
	resy->set_value((const uint8_t*)"0",1);

	
	// Assemble the list of objects to register
	M2MObjectList list;
	list.push_back(dev);
	list.push_back(obj);

	// setup registration event
	Ticker timer;
	timer.attach(&reg,&Registrar::update,20);

	// enable accelerometer
	printf("Initializied accelerometer\r\n");
	accel.enable();
	Ticker sampler;
	sampler.attach(sample,5);

	// schedule 
	FunctionPointer1<void, M2MObjectList> fp(&reg, &Registrar::setup);
	minar::Scheduler::postCallback(fp.bind(list));
	minar::Scheduler::postCallback(sample).period(minar::milliseconds(10000));
	minar::Scheduler::start();
}
Beispiel #2
0
bool M2MServer::set_resource_value(ServerResource resource,
                                   uint32_t value)
{
    bool success = false;
    M2MResource* res = get_resource(resource);
    if(res) {
        if(M2MServer::ShortServerID == resource     ||
           M2MServer::Lifetime == resource          ||
           M2MServer::DefaultMinPeriod == resource  ||
           M2MServer::DefaultMaxPeriod == resource  ||
           M2MServer::DisableTimeout == resource    ||
           M2MServer::NotificationStorage == resource) {
            // If it is any of the above resource
            // set the value of the resource.
            char *buffer = (char*)malloc(20);
            if(buffer) {
                int size = snprintf(buffer, 20,"%ld",(long int)value);
                success = res->set_value((const uint8_t*)buffer,
                                         (const uint32_t)size);
                free(buffer);
            }
        }
    }
    return success;
}
Beispiel #3
0
bool M2MLWClient::set_resource_value(const char *name,
                                     const char *value,
                                     uint16_t object_instance)
{
    bool success = false;
    String name_string;
    String value_string;
    if(name) {
        name_string += name;
    }
    if(value) {
        value_string += value;
    }

    if(_object && name_string.length() > 0) {
        M2MObjectInstance *inst = _object->object_instance(object_instance);
        if(inst) {
            M2MResource *res = inst->resource(name_string);
            if (res) {
                if (res->set_value((const uint8_t*)value_string.c_str(), value_string.size())) {
                    success = true;
                }
            }
        }
    }
    return success;
}
 M2MObject* create_led_object() {
     _sdw_led_object = M2MInterfaceFactory::create_object("311");
     
     if (_sdw_led_object) {
         M2MObjectInstance* inst = _sdw_led_object->create_object_instance();
         if (inst) {
             M2MResource* res = inst->create_dynamic_resource("5850",
                                                              "LED",
                                                              M2MResourceInstance::STRING,
                                                              false);
             if (res) {
                 char buffer[10] = "";
                 memset(buffer,0,10);
                 strcpy(buffer,"0");
                 if (__led == 1) strcpy(buffer,"1");
                 
                 // set the value of the LED 
                 res->set_operation(M2MBase::GET_PUT_ALLOWED);   // we allow GET and PUT of the LED
                 res->set_value((const uint8_t*)buffer,
                                (const uint32_t)strlen(buffer));
             }
         }
     }
     return _sdw_led_object;
 }
Beispiel #5
0
bool M2MSecurity::set_resource_value(SecurityResource resource,
                                     uint32_t value)
{
    bool success = false;
    M2MResource* res = get_resource(resource);
    if(res) {
        if(M2MSecurity::SecurityMode == resource        ||
           M2MSecurity::SMSSecurityMode == resource     ||
           M2MSecurity::M2MServerSMSNumber == resource  ||
           M2MSecurity::ShortServerID == resource       ||
           M2MSecurity::ClientHoldOffTime == resource) {
            // If it is any of the above resource
            // set the value of the resource.            
            char *buffer = (char*)malloc(BUFFER_SIZE);
            if(buffer) {
                uint32_t size = m2m::itoa_c(value, buffer);
                if (size <= BUFFER_SIZE) {
                    success = res->set_value((const uint8_t*)buffer, size);
                }
                free(buffer);
            }
        }
    }
    return success;
}
Beispiel #6
0
    M2MObject* create_generic_object() {
        _object = M2MInterfaceFactory::create_object("Test");
        if(_object) {
            M2MObjectInstance* inst = _object->create_object_instance();
            if(inst) {
                    M2MResource* res = inst->create_dynamic_resource("D",
                                                                     "ResourceTest",
                                                                     M2MResourceInstance::INTEGER,
                                                                     true);
                    char buffer[20];
                    int size = sprintf(buffer,"%d",_value);
                    res->set_operation(M2MBase::GET_PUT_ALLOWED);
                    res->set_value((const uint8_t*)buffer,
                                   (const uint32_t)size);
                    _value++;

                    inst->create_static_resource("S",
                                                 "ResourceTest",
                                                 M2MResourceInstance::STRING,
                                                 STATIC_VALUE,
                                                 sizeof(STATIC_VALUE)-1);
            }
        }
        return _object;
    }
Beispiel #7
0
M2MResource* M2MDevice::create_resource(DeviceResource resource, const String &value)
{
    M2MResource* res = NULL;
    String device_id = "";
    M2MBase::Operation operation = M2MBase::GET_ALLOWED;
    if(!is_resource_present(resource)) {
        switch(resource) {
            case Manufacturer:
               device_id = DEVICE_MANUFACTURER;
               break;
            case DeviceType:
                device_id = DEVICE_DEVICE_TYPE;
                break;
            case ModelNumber:
                device_id = DEVICE_MODEL_NUMBER;
                break;
            case SerialNumber:
                device_id = DEVICE_SERIAL_NUMBER;
                break;
            case HardwareVersion:
                device_id = DEVICE_HARDWARE_VERSION;
                break;
            case FirmwareVersion:
                device_id = DEVICE_FIRMWARE_VERSION;
                break;
            case SoftwareVersion:
                device_id = DEVICE_SOFTWARE_VERSION;
                break;
            case UTCOffset:
                device_id = DEVICE_UTC_OFFSET;
                operation = M2MBase::GET_PUT_ALLOWED;
                break;
            case Timezone:
                device_id = DEVICE_TIMEZONE;
                operation = M2MBase::GET_PUT_ALLOWED;
                break;
            default:
                break;
        }
    }
    if(!device_id.empty()) {
        if(_device_instance) {
            res = _device_instance->create_dynamic_resource(device_id,
                                                            OMA_RESOURCE_TYPE,
                                                            M2MResourceInstance::STRING,
                                                            false);

            if(res ) {
                res->set_operation(operation);
                res->set_value((const uint8_t*)value.c_str(),
                               (uint32_t)value.length());
            }
        }
    }
    return res;
}
Beispiel #8
0
bool M2MServer::set_resource_value(ServerResource resource,
                                   const String &value)
{
    bool success = false;
    M2MResource* res = get_resource(resource);
    if(res && (M2MServer::Binding == resource)) {
        success = res->set_value((const uint8_t*)value.c_str(),(uint32_t)value.length());
    }
    return success;
}
Beispiel #9
0
M2MResource* M2MDevice::create_resource(DeviceResource resource, int64_t value)
{
    M2MResource* res = NULL;
    String device_id = "";
    M2MBase::Operation operation = M2MBase::GET_ALLOWED;
    if(!is_resource_present(resource)) {
        switch(resource) {        
        case BatteryLevel:
            if(check_value_range(resource, value)) {
                device_id = DEVICE_BATTERY_LEVEL;
            }
            break;
        case BatteryStatus:
            if(check_value_range(resource, value)) {
                device_id = DEVICE_BATTERY_STATUS;
            }
            break;
        case MemoryFree:
            device_id = DEVICE_MEMORY_FREE;
            break;
        case MemoryTotal:
            device_id = DEVICE_MEMORY_TOTAL;
            break;
        case CurrentTime:
            device_id = DEVICE_CURRENT_TIME;
            operation = M2MBase::GET_PUT_ALLOWED;
            break;
        default:
            break;
        }
    }
    if(!device_id.empty()) {
        if(_device_instance) {
            res = _device_instance->create_dynamic_resource(device_id,
                                                            OMA_RESOURCE_TYPE,
                                                            M2MResourceInstance::INTEGER,
                                                            true);

            if(res) {
                char *buffer = (char*)malloc(BUFFER_SIZE);
                if(buffer) {
                    uint32_t size = m2m::itoa_c(value, buffer);
                    if (size <= BUFFER_SIZE) {
                        res->set_operation(operation);
                        res->set_value((const uint8_t*)buffer, size);
                    }
                    free(buffer);
                }
                res->set_register_uri(false);
            }
        }
    }
    return res;
}
Beispiel #10
0
bool M2MSecurity::set_resource_value(SecurityResource resource,
                                     const String &value)
{
    bool success = false;
    if(M2MSecurity::M2MServerUri == resource) {
        M2MResource* res = get_resource(resource);
        if(res) {
            success = res->set_value((const uint8_t*)value.c_str(),(uint32_t)value.length());
        }
    }
    return success;
}
    /*
     * When you press the button, we read the current value of the click counter
     * from mbed Device Connector, then up the value with one.
     */
    void handle_state_change(DoorIndicator::WarnStatus warnStatus) {
        M2MObjectInstance* inst = btn_object->object_instance();
        M2MResource* res = inst->resource("5501");

        printf("handle_state_change, new value of state is %d\r\n", (int) warnStatus);

        // serialize the value of counter as a string, and tell connector
        stringstream ss;
        ss << (int) warnStatus;
        std::string stringified = ss.str();
        res->set_value((uint8_t*)stringified.c_str(), stringified.length());
    }
Beispiel #12
0
M2MResource* M2MDevice::create_resource(DeviceResource resource, int64_t value)
{
    M2MResource* res = NULL;
    String device_id = "";
    M2MBase::Operation operation = M2MBase::GET_ALLOWED;
    if(!is_resource_present(resource)) {
        switch(resource) {
        case BatteryLevel:
            if(0 <= value && value <= 100) {
                device_id = DEVICE_BATTERY_LEVEL;
            }
            break;
        case BatteryStatus:
            if(0 <= value && value <= 6) {
                device_id = DEVICE_BATTERY_STATUS;
            }
            break;
        case MemoryFree:
            device_id = DEVICE_MEMORY_FREE;
            break;
        case MemoryTotal:
            device_id = DEVICE_MEMORY_TOTAL;
            break;
        case CurrentTime:
            device_id = DEVICE_CURRENT_TIME;
            operation = M2MBase::GET_PUT_ALLOWED;
            break;
        default:
            break;
        }
    }
    if(!device_id.empty()) {
        if(_device_instance) {
            res = _device_instance->create_dynamic_resource(device_id,
                                                            OMA_RESOURCE_TYPE,
                                                            M2MResourceInstance::INTEGER,
                                                            false);

            if(res) {
                char *buffer = (char*)memory_alloc(20);
                if(buffer) {
                    int size = snprintf(buffer, 20,"%ld",value);

                    res->set_operation(operation);
                    res->set_value((const uint8_t*)buffer,
                                   (const uint32_t)size);
                    memory_free(buffer);
                }
            }
        }
    }
    return res;
}
Beispiel #13
0
// sample the accelerometer every second
static void sample(void) {
	char buffer[24];
	accel.getAxis(acc_raw);
	int len = 0;
	
	M2MObjectInstance* ins = obj->object_instance();

	// X
	len = snprintf(buffer,sizeof(buffer), "%d",acc_raw.x);
	printf("x: %s\r\n",buffer);
	if (! connected) return;
	M2MResource* resx = ins->resource("x");
	resx->set_value((uint8_t*)buffer,len);

	// Y
	len = snprintf(buffer,sizeof(buffer), "%d",acc_raw.y);
	printf("y: %s\r\n",buffer);
	if (! connected) return;
	M2MResource* resy = ins->resource("y");
	resy->set_value((uint8_t*)buffer,len);

}
bool M2MFirmware::set_resource_value(FirmwareResource resource,
                                     const uint8_t *value,
                                     const uint32_t length)
{
    bool success = false;
    M2MResource* res = get_resource(resource);
    if(res) {
        if(M2MFirmware::Package == resource) {
            success = res->set_value(value,length);
        }
    }
    return success;
}
Beispiel #15
0
M2MDevice::M2MDevice()
: M2MObject(M2M_DEVICE_ID)
{
    M2MBase::set_register_uri(false);
    M2MBase::set_operation(M2MBase::GET_ALLOWED);

    _device_instance = M2MObject::create_object_instance();
    _device_instance->set_operation(M2MBase::GET_ALLOWED);
    _device_instance->set_register_uri(true);
    if(_device_instance) {
        _device_instance->set_coap_content_type(COAP_CONTENT_OMA_TLV_TYPE);        
        M2MResource* res = _device_instance->create_dynamic_resource(DEVICE_REBOOT,
                                                                     OMA_RESOURCE_TYPE,
                                                                     M2MResourceInstance::OPAQUE,
                                                                     false);
        if(res) {
            res->set_operation(M2MBase::POST_ALLOWED);
            res->set_register_uri(false);
        }

        M2MResourceInstance* instance = _device_instance->create_dynamic_resource_instance(DEVICE_ERROR_CODE,
                                                                 OMA_RESOURCE_TYPE,
                                                                 M2MResourceInstance::INTEGER,
                                                                 true,0);
        if(instance) {
            M2MResource * dev_res = _device_instance->resource(DEVICE_ERROR_CODE);
            dev_res->set_register_uri(false);
            instance->set_operation(M2MBase::GET_ALLOWED);
            uint32_t size = 0;
            char *buffer = (char*)malloc(BUFFER_SIZE);
            if(buffer) {
                size = m2m::itoa_c(0, buffer);
                if (size <= BUFFER_SIZE)
                    instance->set_value((const uint8_t*)buffer, size);

                free(buffer);
            }
            instance->set_register_uri(false);
        }
        res = _device_instance->create_dynamic_resource(DEVICE_SUPPORTED_BINDING_MODE,
                                                        OMA_RESOURCE_TYPE,
                                                        M2MResourceInstance::STRING,
                                                        true);
        if(res) {
            res->set_operation(M2MBase::GET_ALLOWED);
            res->set_value((const uint8_t*)BINDING_MODE_UDP.c_str(),
                           (uint32_t)BINDING_MODE_UDP.length());
            res->set_register_uri(false);
        }
    }
}
    void update_resource() {
        if(_object) {
            M2MObjectInstance* inst = _object->object_instance();
            if(inst) {
                    M2MResource* res = inst->resource("D");

                    char buffer[20];
                    int size = sprintf(buffer,"%d",_value);
                    res->set_value((const uint8_t*)buffer,
                                   (const uint32_t)size);
                    _value++;
                }
        }
    }
Beispiel #17
0
bool M2MSecurity::set_resource_value(SecurityResource resource,
                                     const uint8_t *value,
                                     const uint16_t length)
{
    bool success = false;
    M2MResource* res = get_resource(resource);
    if(res) {
        if(M2MSecurity::PublicKey == resource           ||
           M2MSecurity::ServerPublicKey == resource     ||
           M2MSecurity::Secretkey == resource) {
            success = res->set_value(value,length);
        }
    }
    return success;
}
Beispiel #18
0
M2MResource* M2MSecurity::create_resource(SecurityResource resource, uint32_t value)
{
    M2MResource* res = NULL;
    String security_id = "";
    if(!is_resource_present(resource)) {
        switch(resource) {
            case SMSSecurityMode:
               security_id = SECURITY_SMS_SECURITY_MODE;
               break;
            case M2MServerSMSNumber:
                security_id = SECURITY_M2M_SERVER_SMS_NUMBER;
                break;
            case ShortServerID:
                security_id = SECURITY_SHORT_SERVER_ID;
                break;
            case ClientHoldOffTime:
                security_id = SECURITY_CLIENT_HOLD_OFF_TIME;
                break;
            default:
                break;
        }
    }
    if(!security_id.empty()) {
        if(_server_instance) {

            res = _server_instance->create_dynamic_resource(security_id,OMA_RESOURCE_TYPE,
                                                            M2MResourceInstance::INTEGER,
                                                            false);

            if(res) {
                res->set_operation(M2MBase::NOT_ALLOWED);
                char *buffer = (char*)malloc(BUFFER_SIZE);
                if(buffer) {
                    uint32_t size = m2m::itoa_c(value, buffer);
                    if (size <= BUFFER_SIZE) {
                        res->set_value((const uint8_t*)buffer, size);
                    }
                    free(buffer);
                }
            }
        }
    }
    return res;
}
bool M2MFirmware::set_resource_value(FirmwareResource resource,
                                       int64_t value)
{
    bool success = false;
    M2MResource* res = get_resource(resource);
    if(res) {
        if(M2MFirmware::State == resource          ||
           M2MFirmware::UpdateSupportedObjects == resource ||
           M2MFirmware::UpdateResult == resource) {
            // If it is any of the above resource
            // set the value of the resource.
            if (check_value_range(resource, value)) {
                
                success = res->set_value(value);
            }
        }
    }
    return success;
}
    /*
     * When you press the button, we read the current value of the click counter
     * from mbed Device Connector, then up the value with one.
     */
    void handle_button_click() {
        if (mbed_client.register_successful()) {
            M2MObjectInstance* inst = btn_object->object_instance();
            M2MResource* res = inst->resource("5501");

            // up counter
            counter++;
    #ifdef TARGET_K64F
            printf("handle_button_click, new value of counter is %d\n", counter);
    #else
            printf("simulate button_click, new value of counter is %d\n", counter);
    #endif
            // serialize the value of counter as a string, and tell connector
            char buffer[20];
            int size = sprintf(buffer,"%d",counter);
            res->set_value((uint8_t*)buffer, size);
        } else {
            printf("simulate button_click, device not registered\n");
        }
    }
bool M2MFirmware::set_resource_value(FirmwareResource resource,
                                   const String &value)
{
    bool success = false;
    M2MResource* res = get_resource(resource);
    if(res) {
        if(M2MFirmware::PackageUri == resource  ||
           M2MFirmware::PackageName == resource ||
           M2MFirmware::PackageVersion == resource) {
            if (value.size() < 256) {
                if(value.empty()) {
                    res->clear_value();
                    success = true;
                } else {
                    success = res->set_value((const uint8_t*)value.c_str(),(uint32_t)value.length());
                }
            }
        }
    }
    return success;
}
M2MResource* M2MFirmware::create_resource(FirmwareResource resource, const String &value)
{
    M2MResource* res = NULL;
    const char* firmware_id_ptr = "";
    M2MBase::Operation operation = M2MBase::GET_ALLOWED;
    if(!is_resource_present(resource)) {
        switch(resource) {
            case PackageName:
                firmware_id_ptr = FIRMWARE_PACKAGE_NAME;
                break;
            case PackageVersion:
                firmware_id_ptr = FIRMWARE_PACKAGE_VERSION;
                break;
            default:
                break;
        }
    }
    String firmware_id(firmware_id_ptr);

    if(!firmware_id.empty() && value.size() < 256) {
        if(_firmware_instance) {
            res = _firmware_instance->create_dynamic_resource(firmware_id,
                                                            OMA_RESOURCE_TYPE,
                                                            M2MResourceInstance::STRING,
                                                            false);

            if(res) {
                res->set_register_uri(false);
                res->set_operation(operation);
                if(value.empty()) {
                    res->clear_value();
                } else {
                    res->set_value((const uint8_t*)value.c_str(),
                                   (uint32_t)value.length());
                }
            }
        }
    }
    return res;
}
Beispiel #23
0
M2MResource* M2MServer::create_resource(ServerResource resource, uint32_t value)
{
    M2MResource* res = NULL;
    String server_id = "";
    if(!is_resource_present(resource)) {
        switch(resource) {
        case DefaultMinPeriod:
            server_id = SERVER_DEFAULT_MIN_PERIOD;
            break;
        case DefaultMaxPeriod:
            server_id = SERVER_DEFAULT_MAX_PERIOD;
            break;
        case DisableTimeout:
            server_id = SERVER_DISABLE_TIMEOUT;
            break;
        default:
            break;
        }
    }
    if(!server_id.empty()) {
        if(_server_instance) {
            res = _server_instance->create_dynamic_resource(server_id,
                                                            OMA_RESOURCE_TYPE,
                                                            M2MResourceInstance::INTEGER,
                                                            true);
            if(res) {
                res->set_operation(M2MBase::GET_PUT_POST_ALLOWED);
                // If resource is created then set the value.
                char *buffer = (char*)malloc(20);
                if(buffer) {
                    int size = snprintf(buffer, 20,"%ld",(long int)value);
                    res->set_value((const uint8_t*)buffer,(const uint32_t)size);
                    free(buffer);
                }
            }
        }
    }
    return res;
}
M2MResource* M2MFirmware::create_resource(FirmwareResource resource, int64_t value)
{
    M2MResource* res = NULL;
    const char* firmware_id_ptr = "";
    M2MBase::Operation operation = M2MBase::GET_ALLOWED;
    if(!is_resource_present(resource)) {
        switch(resource) {
        case UpdateSupportedObjects:
            if(check_value_range(resource, value)) {
                firmware_id_ptr = FIRMWARE_UPDATE_SUPPORTED_OBJECTS;
                operation = M2MBase::GET_PUT_ALLOWED;
            }
            break;
        default:
            break;
        }
    }

    const String firmware_id(firmware_id_ptr);
    
    if(!firmware_id.empty()) {
        if(_firmware_instance) {
            res = _firmware_instance->create_dynamic_resource(firmware_id,
                                                            OMA_RESOURCE_TYPE,
                                                            M2MResourceInstance::INTEGER,
                                                            false);

            if(res) {
                res->set_register_uri(false);

                res->set_operation(operation);
                res->set_value(value);
            }
        }
    }
    return res;
}
Beispiel #25
0
M2MDevice::M2MDevice()
: M2MObject(M2M_DEVICE_ID)
{
    _device_instance = M2MObject::create_object_instance();

    if(_device_instance) {
        _device_instance->set_coap_content_type(COAP_CONTENT_OMA_TLV_TYPE);

        M2MResource* res = _device_instance->create_dynamic_resource(DEVICE_REBOOT,
                                                                     OMA_RESOURCE_TYPE,
                                                                     M2MResourceInstance::OPAQUE,
                                                                     false);
        if(res) {
            res->set_operation(M2MBase::POST_ALLOWED);
        }

        M2MResourceInstance* instance = _device_instance->create_dynamic_resource_instance(DEVICE_ERROR_CODE,
                                                                 OMA_RESOURCE_TYPE,
                                                                 M2MResourceInstance::INTEGER,
                                                                 false,0);
        if(instance) {
            instance->set_operation(M2MBase::GET_ALLOWED);
            instance->set_value((const uint8_t*)ERROR_CODE_VALUE.c_str(),
                           (uint32_t)ERROR_CODE_VALUE.length());
        }
        res = _device_instance->create_dynamic_resource(DEVICE_SUPPORTED_BINDING_MODE,
                                                        OMA_RESOURCE_TYPE,
                                                        M2MResourceInstance::STRING,
                                                        false);
        if(res) {
            res->set_operation(M2MBase::GET_ALLOWED);
            res->set_value((const uint8_t*)BINDING_MODE_UDP.c_str(),
                           (uint32_t)BINDING_MODE_UDP.length());
        }
    }
}