Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom object creation #597

Closed
YassineElyk opened this issue Oct 17, 2018 · 30 comments
Closed

Custom object creation #597

YassineElyk opened this issue Oct 17, 2018 · 30 comments
Labels
question Any question about leshan

Comments

@YassineElyk
Copy link

Hi everyone,
I'm a beginner so please bare with me.
I would like to create a new custom object in Leshan. I would like to know if it is obligatory to only use the existing IPSO data models. Is it possible for me to create my own model and implement it? How can I make the server able to deal with the new objects/ressources?

@sbernard31 sbernard31 added the question Any question about leshan label Oct 18, 2018
@sbernard31
Copy link
Contributor

Hi,
You didn't search too much as less ;)
1 month ago, we get exactly the same question : #570.

But the good point is that your question motivate me to create documentation about that.
See https://github.com/eclipse/leshan/wiki/Adding-new-objects.

I also add this to the F.A.Q..

I hope this help.

(Please close this issue, if you get enough information)

@YassineElyk
Copy link
Author

thank you very much for the help, I would like to know one more thing and excuse me if my question is dumb, how can I set different names for the different instances, meaning the names that will show up on the server? Thanks!

@sbernard31
Copy link
Contributor

sbernard31 commented Oct 19, 2018

In LWM2M, there is no name for instances. Instances is identified by number.

And so in leshan-server-demo there is no name to display.

If you create your own object, you can imagine that one of its resources is the name. And so a server could read this resource to get the name of the instance. But this will be only for your custom objects.

@YassineElyk
Copy link
Author

Is there a way to associate a particular number identifier for a certain instance?

@sbernard31
Copy link
Contributor

sbernard31 commented Oct 19, 2018

When the server create a new instance using CREATE request you can chose the Id.
If the server don't give any id, the client will generate it automatically. (currently you can not chose it)

At initialization, you can not chose it too. 😞

Could you describe your use case, and we could think together how to modify the API to make it possible if needed?

@YassineElyk
Copy link
Author

YassineElyk commented Oct 19, 2018

Ok thank you,
So in my case I have some devices that are connected to a gateway and that I want to configure with Leshan.
For each object I would like to have multiple instances, an instance for every device. I would like to provide each instance with a unique ID number so that in the server I can identify which instance is that of a certain device without adding a resource for this type of identification.
I do not want to add a resource for now in case there is a need to use IPSO standard objects.

@sbernard31
Copy link
Contributor

sbernard31 commented Oct 19, 2018

How do you create those object instances using a LwM2mInstanceEnablerFactory ?

@YassineElyk
Copy link
Author

Looking at the code of LwM2mInstanceEnablerFactory I thought I can't pass two different classes for instantiating each instance of an object. But it works apparently, I use this:

initializer.setInstancesForObject(OBJECT_ID, new class1(), new class2());

Now I need to show in the server wich instance is associated with a certain device without adding a new resource.

@sbernard31
Copy link
Contributor

You are using different class for the same object ? I could not understand why you want to do that ?
Generally you create 1 java class for 1 LWM2M object and so 1 java instance of this class for 1 lwm2m object instance.
(If you can share code like a github repository, I could maybe better understand what you try to achieve)

@YassineElyk
Copy link
Author

So let's say an object implements a certain type of resources X, and I would like to have access for this type of resources for each device.
I create multiple instances that each have a different class. the first instance for example will implement a class_device_1 that will know how to have the information from device 1 and feed it to my resource X
the second instance will have class_device_2 for device 2 etc...
I don't have any complete code for now I hope this conveys my ideas well.

@sbernard31
Copy link
Contributor

It's a bit clearer but not totally.
I ask myself how this behaves with DELETE and CREATE instance ?

(Just to let you know there are some IPSO objects with an application type resource, this would be the kind of resource you would like to make the difference between your device ? E.g Generic Sensor)

@YassineElyk
Copy link
Author

Can you please elaborate on this? How will it be problematic?

@sbernard31
Copy link
Contributor

When the server send a CREATE request on an object, Leshan device should create a new instance of this object. Generally the LwM2mInstanceEnablerFactory is used to create this instance how do you know which kind of class you will instantiate ?

@YassineElyk
Copy link
Author

YassineElyk commented Oct 24, 2018

I see what you mean and I honestly cannot understand the use of remote instance creation from the server if we already do that in the code using setInstancesForObject ? I will try to look into this problem though.

@sbernard31
Copy link
Contributor

setInstanceForObject is for creating the instance at start up, but a server can DELETE or CREATE instances too. To be honest, I suspect there is some use case where creating an instance from Server does not really make sense...

That's why I tried at the beginning to understand your "concrete" use case.

@saurav-pratik-ext-smo-pna

@sbernard31

I was going through this as I also need to have multiple instances of of a custom object.

I can create it using below code:
initializer.setInstancesForObject(ID_CUSTOM_NOTIFICATION, new CustomNotification(),new CustomNotification());
I can see that it create two instances on the server webpage.

My question is how can we read /write these objects separately at once. Read/write api does not talk about instance ID. It only gives option for resourceId. I need to frame a json file using contents of resource Ids 1 and 2

Is there a way to find instance ID and get all values of that instance at once.

@Override
	public WriteResponse write(int resourceId, LwM2mResource value) {
		LOG.info("Write for Notification " + resourceId + " value " + value);
		switch (resourceId) {
		case 0:
			fireResourcesChange(resourceId);
			return WriteResponse.success();
			
		case 1:
                         // do something
			fireResourcesChange(resourceId);
			return WriteResponse.success();
		case2:
			// do something
			fireResourcesChange(resourceId);
			return WriteResponse.success();

		default:
			return super.write(resourceId, value);
		}
	}

@sbernard31
Copy link
Contributor

@sauravpratik I don't really understand what you want to do.

At client side the idea is to provide a way to implement how to write or read a resource.

But at server side you can target object, object instances or resources with a READ request or object instances or resources with WRITE request.

When object or object instances is targeted, leshan-client will call write/read methods for all resources of the instance and will return only 1 response with all the value.

@saurav-pratik-ext-smo-pna
Copy link

saurav-pratik-ext-smo-pna commented Nov 9, 2018

@sbernard31
Apologies for the lack of clarity in the query.

I need to create multiple instance (lets say 2) of my custom defined object , say CustomEvent(). Its has 3 resource Ids which I have defined in CustomEvent() class.

I can create it using below code:

               
		CustomEvent instanceOne = new CustomEvent();
                CustomEvent instanceTwo = new CustomEvent();
		initializer.setInstancesForObject(ID_CUSTOM_EVENT, instanceOne, instanceTwo);
        	List<LwM2mObjectEnabler> enablers = initializer.create(SECURITY, SERVER, DEVICE, LOCATION,ID_CUSTOM_EVENT);

This creates two instance of CustomEvent() on Leshan Server and Instance Ids are assigned as 0 and 1.

Question 1: Is it possible to provide Instance Id to object from client rather that server assigning it as 0 and 1 ?
I want to assign is via client as I wanted to use these 2 instances for different purpose.

Looks like answer is NO as mentioned in the same thread. Is there a possible way ?


CustomEvent() handles read and write interfaces and returns ReadResponse/WriteResponse.

When server writes the complete Instance (say 0) at once by filling all 3 resources , the client code handles it in .

@Override
	public WriteResponse write(int resourceId, LwM2mResource value) {
		LOG.info("Write for Notification " + resourceId + " value " + value);
		switch (resourceId) {
		case 0:
			fireResourcesChange(resourceId);
			return WriteResponse.success();
			
		case 1:
                         // do something
			fireResourcesChange(resourceId);
			return WriteResponse.success();
		case2:
			// do something
			fireResourcesChange(resourceId);
			return WriteResponse.success();

		default:
			return super.write(resourceId, value);
		}
	}

Question 2 : Is it possible to get Instance Id (0 or 1) here ?
I see it provides just the resource Id and LwM2mResource value. Based on the Instance ID , I want to take some action as I have defined these 2 instances for different purposes?

This looks possible by modifying adding below function to public interface LwM2mInstanceEnabler

WriteResponse write(int id, LwM2mResource writeResource, WriteRequest request);

Here from WriteRequest request - I can get the instance path. Ex:

@Override
public  WriteResponse write(int id, LwM2mResource writeResource, WriteRequest request)
    {
    	LOG.info("Write on Device Resourcessss " + id + " value " + writeResource);
    	LwM2mPath path = request.getPath();
    	LOG.info("Instand ID " + path.getObjectInstanceId());
    	
    	return WriteResponse.success();   	
    }

Do you suggest this approach ?


Question 3:

@Override
	public WriteResponse write(int resourceId, LwM2mResource value) {
		LOG.info("Write for Notification " + resourceId + " value " + value);
		switch (resourceId) {
		case 0:
                case 1:

                default:
			return super.write(resourceId, value);

This piece of client code is called for each resource Id. Is it possible that once complete instance is updated/written by server then the client can gather data of each resource Id at once rather than one by one by reading case 0, case 1 etc ?

Thanks for your time for reading this

P.s I am using Leshan Client and Server Demo source code for testing this out.

@sbernard31
Copy link
Contributor

Question 1: Is it possible to provide Instance Id to object from client rather that server assigning it as 0 and 1 ?

Currently you can't, we could add this but currently I didn't really understand the need of this 😕

Question 2 : Is it possible to get Instance Id (0 or 1) here ?
I see it provides just the resource Id and LwM2mResource value. Based on the Instance ID , I want to take some action as I have defined these 2 instances for different purposes?

It seems your 2 instances have not exactly the same behavior. Why not using one of the resource to define the behavior and so you could use this resource to know what to do instead of the instance ID ?

E.g. adding a type resource to CustomEvent and when you create it :

CustomEvent instanceOne = new CustomEvent();
instanceOne.setType("A");
CustomEvent instanceTwo = new CustomEvent();
instanceOne.setType("B");

(I propose type but there is probably a better name depending of your use case, maybe target, source ... the thing which allow you to determine the behavior of your instance)

This way even at server side you can guess the type, you can even create or delete event instance from server.

Is it possible that once complete instance is updated/written by server then the client can gather data of each resource Id at once rather than one by one by reading case 0, case 1 etc ?

using ObjectEnabler and so LwM2mInstanceEnabler this is not possible. Could you explain why you need to do that ?

Anyway, the real contract to implement is LwM2mObjectEnabler \ BaseObjectEnabler at this level you can do almost everything you want but that also means that you should implement a lot of thing on your own.

ObjectEnabler+LwM2mInstanceEnabler is a try to make the life easier to implement most of LWM2M object but I'm afraid that we will not be able to cover all the usecases. That's why LwM2mObjectEnabler exists.

@saurav-pratik-ext-smo-pna
Copy link

saurav-pratik-ext-smo-pna commented Nov 12, 2018

@sbernard31

Thanks for your detailed response. Really appreciate it. And I completely agree that it's not possible to cover all use cases.

Regarding your responses to Questions:

  1. It's not possible currently to assign instance ID to object. Point noted.
  2. You suggested to assign type to object instance. I am currently doing the same and assigning different type to each instance based on my need. Thanks for this suggestion.
  3. You asked why I want complete object at once
    The reason is server keeps updating the object quite often via a script written at the server end ( not via server GUI).
    At the client side I need to read all resources of a particular instance and pass it to another layer. Now since resources ids are called one by one in switch case (write/read), its not possible to send complete object at once. Thats the main reason I wanted to read complete instance at once and pass it to other layer.

Thank You

@sbernard31
Copy link
Contributor

  1. So finally using a type like proposed in 2., you don't need this feature anymore right ? If I'm wrong could you explain a bit why you need it ?
  2. Good to ear :)
  3. For know the only solution is to directly implements LwM2mObjectEnabler / BaseObjectEnabler, but I will explore if there could be a good way to do that with ObjectEnabler / LwM2mInstanceEnabler.

@saurav-pratik-ext-smo-pna
Copy link

saurav-pratik-ext-smo-pna commented Nov 12, 2018

@sbernard31
Thanks for your response.

1 - Using a type definitely helps.

In future, it will be good to have this feature for unique requirements. Not urgent for sure.
Just for update, Wakama LwM2M client in C has this feature.I learnt this from my colleague who is working on C client. C client lets user declare the instance ID while creating the object.

3 - I will explore as well. Pls lemme know if you find a solution for it..

Thanks for your time and suggestions. Appreciated :)

@sbernard31
Copy link
Contributor

  1. Ok. I see 2 different needs/features.
    1.1 define ID at client initialization. (as you need)
    1.2 being able to choose an ID when server use CREATE request without giving any ID value.

  2. I will do it.

@saurav-pratik-ext-smo-pna

Thank You so much.

@sbernard31
Copy link
Contributor

@sauravpratik I create an experimental PR #616 to explore a possible solution for 3.

But this modify lot of thing about object creation and instance Id, so maybe this could be a better plan to start by implementing 1.

Anyway, let me know if #616 seems to be a good way for you.

@saurav-pratik-ext-smo-pna
Copy link

saurav-pratik-ext-smo-pna commented Nov 13, 2018

@sbernard31 - Completely agree to your point. Starting implementing 1 will be better plan.

#616 - It looks promising. I understand the changes. One input - It would be nice if both Read and Write operations are added together.

ReadResponse read(ServerIdentity identity); &
WriteResponse write(ServerIdentity identity); //

What do you suggest ?

Thanks for adding this. This will greatly help

@sbernard31
Copy link
Contributor

It would be nice if both Read and Write operations are added together.To be consistent

I plan to do that for almost all operation. I also plan to add ServerIdentity parameter to "resource operation" to make it consistent.

@saurav-pratik-ext-smo-pna

@sbernard31 Got your point. Thanks.

@sbernard31
Copy link
Contributor

@Yalayak, @sauravpratik

  1. I implemented a more flexible way to choose instance id in Add a way to support choose custom Id at client side. #640
  2. I completed a way to make atomic operation Add a way to make "atomic" operation (read/write) on LwM2mInstanceEnabler #616 (based on Add a way to support choose custom Id at client side. #640)

If you I have time to review this PR or give feedback about it, that would be really appreciated.

@sbernard31
Copy link
Contributor

@Yalayak @sauravpratik

I pushed #640 #616 in master so I believe we can close this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Any question about leshan
Projects
None yet
Development

No branches or pull requests

3 participants