Skip to content

Commit 53af79e

Browse files
Added WithLinkNotFoundCallback from main branch (#511)
Co-authored-by: cah <lubomir.capucha@kistler.com>
1 parent 27b5464 commit 53af79e

15 files changed

Lines changed: 329 additions & 77 deletions

client/client.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import (
2828
"github.com/plgd-dev/device/v2/client/core"
2929
"github.com/plgd-dev/device/v2/client/core/otm"
3030
"github.com/plgd-dev/device/v2/pkg/net/coap"
31+
"github.com/plgd-dev/device/v2/schema"
3132
"github.com/plgd-dev/go-coap/v3/net/blockwise"
3233
"github.com/plgd-dev/go-coap/v3/options"
3334
coapSync "github.com/plgd-dev/go-coap/v3/pkg/sync"
@@ -397,3 +398,29 @@ func NewDeviceOwnerFromConfig(cfg *Config, dialTLS core.DialTLS, dialDTLS core.D
397398
}
398399
return newDeviceOwnershipNone(), nil
399400
}
401+
402+
func (c *Client) GetDeviceLinkForHref(
403+
ctx context.Context,
404+
deviceID string,
405+
href string,
406+
discoveryCfg core.DiscoveryConfiguration,
407+
callback LinkNotFoundCallback,
408+
) (*core.Device, schema.ResourceLink, error) {
409+
d, links, err := c.GetDevice(ctx, deviceID, WithDiscoveryConfiguration(discoveryCfg))
410+
if err != nil {
411+
return nil, schema.ResourceLink{}, err
412+
}
413+
414+
link, err := core.GetResourceLink(links, href)
415+
if err != nil {
416+
if callback.linkNotFoundCallback != nil {
417+
link, err = callback.linkNotFoundCallback(links, href)
418+
if err != nil {
419+
return nil, schema.ResourceLink{}, err
420+
}
421+
} else {
422+
return nil, schema.ResourceLink{}, err
423+
}
424+
}
425+
return d, link, nil
426+
}

client/core/provisionDevice_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ func TestSettingCloudResource(t *testing.T) {
126126
AuthorizationProvider: "testAuthorizationProvider",
127127
URL: "testURL",
128128
AuthorizationCode: "testAuthorizationCode",
129+
CloudID: "00000000-0000-0000-0000-000000000000",
129130
}
130131
err = pc.SetCloudResource(context.Background(), r)
131132
require.NoError(t, err)

client/createResource.go

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,10 @@ func (c *Client) CreateResource(
4545
cfg = o.applyOnCreate(cfg)
4646
}
4747

48-
d, links, err := c.GetDevice(ctx, deviceID, WithDiscoveryConfiguration(cfg.discoveryConfiguration))
48+
device, link, err := c.GetDeviceLinkForHref(ctx, deviceID, href, cfg.discoveryConfiguration, LinkNotFoundCallback{linkNotFoundCallback: cfg.linkNotFoundCallback})
4949
if err != nil {
5050
return err
5151
}
5252

53-
link, err := core.GetResourceLink(links, href)
54-
if err != nil {
55-
return err
56-
}
57-
58-
return d.UpdateResourceWithCodec(ctx, link, cfg.codec, request, response, cfg.opts...)
53+
return device.UpdateResourceWithCodec(ctx, link, cfg.codec, request, response, cfg.opts...)
5954
}

client/createResource_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222

2323
"github.com/plgd-dev/device/v2/client"
2424
"github.com/plgd-dev/device/v2/client/core"
25+
"github.com/plgd-dev/device/v2/schema"
2526
"github.com/plgd-dev/device/v2/schema/device"
2627
"github.com/plgd-dev/device/v2/schema/interfaces"
2728
"github.com/plgd-dev/device/v2/test"
@@ -60,6 +61,32 @@ func TestClientCreateResource(t *testing.T) {
6061
},
6162
}),
6263
},
64+
{
65+
name: "test link not found callback",
66+
args: args{
67+
deviceID: deviceID,
68+
href: "/link/not/found",
69+
body: test.MakeSwitchResourceDefaultData(),
70+
opts: []client.CreateOption{
71+
client.WithDiscoveryConfiguration(core.DefaultDiscoveryConfiguration()),
72+
client.WithLinkNotFoundCallback(func(links schema.ResourceLinks, href string) (schema.ResourceLink, error) {
73+
_, linkFound := links.GetResourceLink(href)
74+
require.False(t, linkFound)
75+
resourceLink, linkFound := links.GetResourceLink(test.TestResourceSwitchesHref)
76+
require.True(t, linkFound)
77+
return resourceLink, nil
78+
}),
79+
},
80+
},
81+
want: test.MakeSwitchResourceData(map[string]interface{}{
82+
"href": test.TestResourceSwitchesInstanceHref("2"),
83+
"rep": map[interface{}]interface{}{
84+
"if": []interface{}{interfaces.OC_IF_A, interfaces.OC_IF_BASELINE},
85+
"rt": []interface{}{types.BINARY_SWITCH},
86+
"value": false,
87+
},
88+
}),
89+
},
6390
{
6491
name: "invalid href",
6592
args: args{

client/deleteResource.go

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,10 @@ func (c *Client) DeleteResource(
4040
cfg = o.applyOnDelete(cfg)
4141
}
4242

43-
d, links, err := c.GetDevice(ctx, deviceID, WithDiscoveryConfiguration(cfg.discoveryConfiguration))
43+
device, link, err := c.GetDeviceLinkForHref(ctx, deviceID, href, cfg.discoveryConfiguration, LinkNotFoundCallback{linkNotFoundCallback: cfg.linkNotFoundCallback})
4444
if err != nil {
4545
return err
4646
}
4747

48-
link, err := core.GetResourceLink(links, href)
49-
if err != nil {
50-
return err
51-
}
52-
53-
return d.DeleteResourceWithCodec(ctx, link, cfg.codec, response, cfg.opts...)
48+
return device.DeleteResourceWithCodec(ctx, link, cfg.codec, response, cfg.opts...)
5449
}

client/deleteResource_test.go

Lines changed: 42 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"github.com/plgd-dev/device/v2/client"
2525
"github.com/plgd-dev/device/v2/client/core"
2626
"github.com/plgd-dev/device/v2/schema"
27+
"github.com/plgd-dev/device/v2/schema/configuration"
2728
"github.com/plgd-dev/device/v2/schema/device"
2829
"github.com/plgd-dev/device/v2/schema/interfaces"
2930
"github.com/plgd-dev/device/v2/schema/resources"
@@ -51,7 +52,28 @@ func createSwitches(ctx context.Context, t *testing.T, c *client.Client, deviceI
5152

5253
func TestClientDeleteResource(t *testing.T) {
5354
deviceID := test.MustFindDeviceByName(test.DevsimName)
54-
const switchID = "1"
55+
const (
56+
switchID_1 = "1"
57+
switchID_2 = "2"
58+
)
59+
60+
c, err := NewTestSecureClient()
61+
require.NoError(t, err)
62+
defer func() {
63+
errC := c.Close(context.Background())
64+
require.NoError(t, errC)
65+
}()
66+
ctx, cancel := context.WithTimeout(context.Background(), TestTimeout)
67+
defer cancel()
68+
deviceID, err = c.OwnDevice(ctx, deviceID, client.WithOTMs([]client.OTMType{client.OTMType_JustWorks}))
69+
require.NoError(t, err)
70+
defer disown(t, c, deviceID)
71+
72+
createSwitches(ctx, t, c, deviceID, 2)
73+
var nonDiscoverableResource map[string]interface{}
74+
err = c.CreateResource(ctx, deviceID, test.TestResourceSwitchesHref, test.MakeNonDiscoverableSwitchData(), &nonDiscoverableResource)
75+
require.NoError(t, err)
76+
5577
type args struct {
5678
deviceID string
5779
href string
@@ -66,10 +88,28 @@ func TestClientDeleteResource(t *testing.T) {
6688
name: "valid",
6789
args: args{
6890
deviceID: deviceID,
69-
href: test.TestResourceSwitchesInstanceHref(switchID),
91+
href: test.TestResourceSwitchesInstanceHref(switchID_1),
7092
opts: []client.DeleteOption{client.WithDiscoveryConfiguration(core.DefaultDiscoveryConfiguration())},
7193
},
7294
},
95+
{
96+
name: "delete non-discoverable resource",
97+
args: args{
98+
deviceID: deviceID,
99+
href: nonDiscoverableResource["href"].(string),
100+
opts: []client.DeleteOption{
101+
client.WithDiscoveryConfiguration(core.DefaultDiscoveryConfiguration()),
102+
// create the link for non-discoverable resource by utilizing the linkNotFoundCallback
103+
// as the only thing that we need in the link is the href and endpoints we will reuse
104+
// some known discoverable resource
105+
client.WithLinkNotFoundCallback(func(links schema.ResourceLinks, href string) (schema.ResourceLink, error) {
106+
resourceLink, _ := links.GetResourceLink(configuration.ResourceURI)
107+
resourceLink.Href = href
108+
return resourceLink, nil
109+
}),
110+
},
111+
},
112+
},
73113
{
74114
name: "invalid href",
75115
args: args{
@@ -88,20 +128,6 @@ func TestClientDeleteResource(t *testing.T) {
88128
},
89129
}
90130

91-
c, err := NewTestSecureClient()
92-
require.NoError(t, err)
93-
defer func() {
94-
errC := c.Close(context.Background())
95-
require.NoError(t, errC)
96-
}()
97-
ctx, cancel := context.WithTimeout(context.Background(), TestTimeout)
98-
defer cancel()
99-
deviceID, err = c.OwnDevice(ctx, deviceID, client.WithOTMs([]client.OTMType{client.OTMType_JustWorks}))
100-
require.NoError(t, err)
101-
defer disown(t, c, deviceID)
102-
103-
createSwitches(ctx, t, c, deviceID, 1)
104-
105131
for _, tt := range tests {
106132
t.Run(tt.name, func(t *testing.T) {
107133
err := c.DeleteResource(ctx, tt.args.deviceID, tt.args.href, nil, tt.args.opts...)

client/getResource.go

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,11 @@ func (c *Client) GetResource(
3939
for _, o := range opts {
4040
cfg = o.applyOnGet(cfg)
4141
}
42-
d, links, err := c.GetDevice(ctx, deviceID, WithDiscoveryConfiguration(cfg.discoveryConfiguration))
43-
if err != nil {
44-
return err
45-
}
4642

47-
link, err := core.GetResourceLink(links, href)
43+
device, link, err := c.GetDeviceLinkForHref(ctx, deviceID, href, cfg.discoveryConfiguration, LinkNotFoundCallback{linkNotFoundCallback: cfg.linkNotFoundCallback})
4844
if err != nil {
4945
return err
5046
}
5147

52-
return d.GetResourceWithCodec(ctx, link, cfg.codec, response, cfg.opts...)
48+
return device.GetResourceWithCodec(ctx, link, cfg.codec, response, cfg.opts...)
5349
}

client/getResource_test.go

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,22 @@ import (
4343

4444
func TestClientGetResource(t *testing.T) {
4545
deviceID := test.MustFindDeviceByName(test.DevsimName)
46+
c, err := NewTestSecureClient()
47+
require.NoError(t, err)
48+
defer func() {
49+
errC := c.Close(context.Background())
50+
require.NoError(t, errC)
51+
}()
52+
ctx, cancel := context.WithTimeout(context.Background(), TestTimeout)
53+
defer cancel()
54+
deviceID, err = c.OwnDevice(ctx, deviceID)
55+
require.NoError(t, err)
56+
defer disown(t, c, deviceID)
57+
58+
var nonDiscoverableResource map[string]interface{}
59+
err = c.CreateResource(ctx, deviceID, test.TestResourceSwitchesHref, test.MakeNonDiscoverableSwitchData(), &nonDiscoverableResource)
60+
require.NoError(t, err)
61+
4662
type args struct {
4763
deviceID string
4864
href string
@@ -85,6 +101,33 @@ func TestClientGetResource(t *testing.T) {
85101
},
86102
},
87103
},
104+
{
105+
name: "get non-discoverable resource",
106+
args: args{
107+
deviceID: deviceID,
108+
href: nonDiscoverableResource["href"].(string),
109+
opts: []client.GetOption{
110+
client.WithDiscoveryConfiguration(core.DefaultDiscoveryConfiguration()),
111+
// create the link for non-discoverable resource by utilizing the linkNotFoundCallback
112+
// as the only thing that we need in the link is the href and endpoints we will reuse
113+
// some known discoverable resource
114+
client.WithLinkNotFoundCallback(func(links schema.ResourceLinks, href string) (schema.ResourceLink, error) {
115+
resourceLink, ok := links.GetResourceLink(configuration.ResourceURI)
116+
if !ok {
117+
return schema.ResourceLink{}, fmt.Errorf("failed to get resource link: %w", err)
118+
}
119+
resourceLink.Href = href
120+
return resourceLink, nil
121+
}),
122+
},
123+
},
124+
want: coap.DetailedResponse[interface{}]{
125+
Code: codes.Content,
126+
Body: map[interface{}]interface{}{
127+
"value": false,
128+
},
129+
},
130+
},
88131
{
89132
name: "invalid href",
90133
args: args{
@@ -103,17 +146,6 @@ func TestClientGetResource(t *testing.T) {
103146
},
104147
}
105148

106-
c, err := NewTestSecureClient()
107-
require.NoError(t, err)
108-
defer func() {
109-
errC := c.Close(context.Background())
110-
require.NoError(t, errC)
111-
}()
112-
ctx, cancel := context.WithTimeout(context.Background(), TestTimeout)
113-
defer cancel()
114-
deviceID, err = c.OwnDevice(ctx, deviceID)
115-
require.NoError(t, err)
116-
defer disown(t, c, deviceID)
117149
for _, tt := range tests {
118150
t.Run(tt.name, func(t *testing.T) {
119151
var got coap.DetailedResponse[interface{}]

client/observeResource.go

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -225,22 +225,17 @@ func (c *Client) ObserveResource(
225225
return getObservationID(key, resourceObservationID.String()), nil
226226
}
227227

228-
d, links, err := c.GetDevice(ctx, deviceID, WithDiscoveryConfiguration(cfg.discoveryConfiguration))
228+
device, link, err := c.GetDeviceLinkForHref(ctx, deviceID, href, cfg.discoveryConfiguration, LinkNotFoundCallback{linkNotFoundCallback: cfg.linkNotFoundCallback})
229229
if err != nil {
230230
return "", err
231231
}
232232

233-
link, err := core.GetResourceLink(links, href)
233+
observationID, err = device.ObserveResourceWithCodec(ctx, link, observerCodec{contentFormat: cfg.codec.ContentFormat()}, h, cfg.opts...)
234234
if err != nil {
235235
return "", err
236236
}
237237

238-
observationID, err = d.ObserveResourceWithCodec(ctx, link, observerCodec{contentFormat: cfg.codec.ContentFormat()}, h, cfg.opts...)
239-
if err != nil {
240-
return "", err
241-
}
242-
243-
dev, _ := c.deviceCache.UpdateOrStoreDevice(d)
238+
dev, _ := c.deviceCache.UpdateOrStoreDevice(device)
244239
h.observationID = observationID
245240
h.device = dev
246241

0 commit comments

Comments
 (0)