diff --git a/bridge/device/thingDescription/thingDescription.go b/bridge/device/thingDescription/thingDescription.go index 30353948..f770f185 100644 --- a/bridge/device/thingDescription/thingDescription.go +++ b/bridge/device/thingDescription/thingDescription.go @@ -1,11 +1,13 @@ package thingDescription import ( + "net/http" "net/url" "github.com/fredbi/uri" "github.com/google/uuid" "github.com/plgd-dev/device/v2/bridge/resources" + "github.com/plgd-dev/go-coap/v3/message" "github.com/web-of-things-open-source/thingdescription-go/thingDescription" ) @@ -97,7 +99,42 @@ func (p PropertyElementOperations) ToSupportedOperations() resources.SupportedOp return ops | resources.SupportedOperationRead | resources.SupportedOperationWrite } -func PatchPropertyElement(prop thingDescription.PropertyElement, types []string, setForm bool, deviceID uuid.UUID, href string, ops resources.SupportedOperation, contentType string) (thingDescription.PropertyElement, error) { +func createForm(hrefUri *url.URL, covMethod string, op thingDescription.StickyDescription, contentType message.MediaType) thingDescription.FormElementProperty { + additionalFields := map[string]interface{}{ + "cov:method": covMethod, + "cov:accept": float64(contentType), + } + ops := []string{string(op)} + if op == thingDescription.Observeproperty { + additionalFields["subprotocol"] = "cov:observe" + ops = append(ops, string(thingDescription.Unobserveproperty)) + } + + return thingDescription.FormElementProperty{ + ContentType: StringToPtr(contentType.String()), + Href: *hrefUri, + Op: &thingDescription.FormElementPropertyOp{ + StringArray: ops, + }, + AdditionalFields: additionalFields, + } +} + +func SetForms(hrefUri *url.URL, ops resources.SupportedOperation, contentType message.MediaType) []thingDescription.FormElementProperty { + forms := make([]thingDescription.FormElementProperty, 0, 3) + if ops.HasOperation(resources.SupportedOperationWrite) { + forms = append(forms, createForm(hrefUri, http.MethodPost, thingDescription.Writeproperty, contentType)) + } + if ops.HasOperation(resources.SupportedOperationRead) { + forms = append(forms, createForm(hrefUri, http.MethodGet, thingDescription.Readproperty, contentType)) + } + if ops.HasOperation(resources.SupportedOperationObserve) { + forms = append(forms, createForm(hrefUri, http.MethodGet, thingDescription.Observeproperty, contentType)) + } + return forms +} + +func PatchPropertyElement(prop thingDescription.PropertyElement, types []string, setForm bool, deviceID uuid.UUID, href string, ops resources.SupportedOperation, contentType message.MediaType) (thingDescription.PropertyElement, error) { if len(types) > 0 { prop.Type = &thingDescription.TypeDeclaration{ StringArray: types, @@ -126,16 +163,7 @@ func PatchPropertyElement(prop thingDescription.PropertyElement, types []string, return thingDescription.PropertyElement{}, err } } - form := thingDescription.FormElementProperty{ - ContentType: StringToPtr(contentType), - Op: &thingDescription.FormElementPropertyOp{ - StringArray: opsStrs, - }, - } - if hrefUri != nil { - form.Href = *hrefUri - } - prop.Forms = []thingDescription.FormElementProperty{form} + prop.Forms = SetForms(hrefUri, ops, contentType) return prop, nil } diff --git a/bridge/resources/thingDescription/ocfResources.go b/bridge/resources/thingDescription/ocfResources.go index cdd1817e..ca704490 100644 --- a/bridge/resources/thingDescription/ocfResources.go +++ b/bridge/resources/thingDescription/ocfResources.go @@ -9,6 +9,7 @@ import ( schemaCredential "github.com/plgd-dev/device/v2/schema/credential" schemaDevice "github.com/plgd-dev/device/v2/schema/device" schemaMaintenance "github.com/plgd-dev/device/v2/schema/maintenance" + "github.com/plgd-dev/go-coap/v3/message" "github.com/web-of-things-open-source/thingdescription-go/thingDescription" ) @@ -39,12 +40,12 @@ func GetOCFResourcePropertyElement(resourceHref string) (thingDescription.Proper return prop, true } -func patchResourcePropertyElement(pe thingDescription.PropertyElement, deviceID uuid.UUID, resourceTypes []string, resourceHref, contentType string) (thingDescription.PropertyElement, error) { +func patchResourcePropertyElement(pe thingDescription.PropertyElement, deviceID uuid.UUID, resourceTypes []string, resourceHref string, contentType message.MediaType) (thingDescription.PropertyElement, error) { propOps := bridgeTD.GetPropertyElementOperations(pe) return bridgeTD.PatchPropertyElement(pe, resourceTypes, true, deviceID, resourceHref, propOps.ToSupportedOperations(), contentType) } -func PatchDeviceResourcePropertyElement(pe thingDescription.PropertyElement, deviceID uuid.UUID, baseURL, contentType string, deviceType string) (thingDescription.PropertyElement, error) { +func PatchDeviceResourcePropertyElement(pe thingDescription.PropertyElement, deviceID uuid.UUID, baseURL string, contentType message.MediaType, deviceType string) (thingDescription.PropertyElement, error) { var types []string if deviceType != "" { types = []string{schemaDevice.ResourceType, deviceType} @@ -52,14 +53,14 @@ func PatchDeviceResourcePropertyElement(pe thingDescription.PropertyElement, dev return patchResourcePropertyElement(pe, deviceID, types, baseURL+schemaDevice.ResourceURI, contentType) } -func PatchMaintenanceResourcePropertyElement(pe thingDescription.PropertyElement, deviceID uuid.UUID, baseURL, contentType string) (thingDescription.PropertyElement, error) { +func PatchMaintenanceResourcePropertyElement(pe thingDescription.PropertyElement, deviceID uuid.UUID, baseURL string, contentType message.MediaType) (thingDescription.PropertyElement, error) { return patchResourcePropertyElement(pe, deviceID, []string{schemaMaintenance.ResourceType}, baseURL+schemaMaintenance.ResourceURI, contentType) } -func PatchCloudResourcePropertyElement(pe thingDescription.PropertyElement, deviceID uuid.UUID, baseURL, contentType string) (thingDescription.PropertyElement, error) { +func PatchCloudResourcePropertyElement(pe thingDescription.PropertyElement, deviceID uuid.UUID, baseURL string, contentType message.MediaType) (thingDescription.PropertyElement, error) { return patchResourcePropertyElement(pe, deviceID, []string{schemaCloud.ResourceType}, baseURL+schemaCloud.ResourceURI, contentType) } -func PatchCredentialResourcePropertyElement(pe thingDescription.PropertyElement, deviceID uuid.UUID, baseURL, contentType string) (thingDescription.PropertyElement, error) { +func PatchCredentialResourcePropertyElement(pe thingDescription.PropertyElement, deviceID uuid.UUID, baseURL string, contentType message.MediaType) (thingDescription.PropertyElement, error) { return patchResourcePropertyElement(pe, deviceID, []string{schemaCredential.ResourceType}, baseURL+schemaCredential.ResourceURI, contentType) } diff --git a/bridge/resources/thingDescription/resource_test.go b/bridge/resources/thingDescription/resource_test.go index 82716b80..6b182d87 100644 --- a/bridge/resources/thingDescription/resource_test.go +++ b/bridge/resources/thingDescription/resource_test.go @@ -99,7 +99,7 @@ func getEndpoint(t *testing.T, c *client.Client, deviceID string) string { func getPatchedTD(td wotTD.ThingDescription, d service.Device, epURI string) wotTD.ThingDescription { return bridgeDeviceTD.PatchThingDescription(td, d, epURI, func(resourceHref string, resource bridgeDeviceTD.Resource) (wotTD.PropertyElement, bool) { - return bridgeTest.GetPropertyElement(td, d, epURI, resourceHref, resource, message.AppCBOR.String()) + return bridgeTest.GetPropertyElement(td, d, epURI, resourceHref, resource, message.AppCBOR) }) } diff --git a/bridge/test/test.go b/bridge/test/test.go index 341942fc..8edcf8c9 100644 --- a/bridge/test/test.go +++ b/bridge/test/test.go @@ -115,7 +115,7 @@ func makeDeviceConfig(id uuid.UUID, cloudEnabled bool, credentialEnabled bool) d return cfg } -func GetPropertyElement(td wotTD.ThingDescription, device bridgeDeviceTD.Device, endpoint string, resourceHref string, resource bridgeDeviceTD.Resource, contentType string) (wotTD.PropertyElement, bool) { +func GetPropertyElement(td wotTD.ThingDescription, device bridgeDeviceTD.Device, endpoint string, resourceHref string, resource bridgeDeviceTD.Resource, contentType message.MediaType) (wotTD.PropertyElement, bool) { propElement, ok := td.Properties[resourceHref] if !ok { return wotTD.PropertyElement{}, false @@ -149,7 +149,7 @@ func NewBridgedDeviceWithThingDescription(t *testing.T, s *service.Service, id s } newTD := bridgeDeviceTD.PatchThingDescription(*td, device, endpoint, func(resourceHref string, resource bridgeDeviceTD.Resource) (wotTD.PropertyElement, bool) { - return GetPropertyElement(*td, device, endpoint, resourceHref, resource, message.AppCBOR.String()) + return GetPropertyElement(*td, device, endpoint, resourceHref, resource, message.AppCBOR) }) return &newTD })) @@ -163,7 +163,7 @@ func getOCFResourcesProperties(deviceID uuid.UUID, baseURL string, cloudEnabled, if !ok { return nil, errors.New("device resource not found") } - deviceResource, err := thingDescriptionResource.PatchDeviceResourcePropertyElement(deviceResource, deviceID, baseURL, message.AppCBOR.String(), "") + deviceResource, err := thingDescriptionResource.PatchDeviceResourcePropertyElement(deviceResource, deviceID, baseURL, message.AppCBOR, "") if err != nil { return nil, err } @@ -174,7 +174,7 @@ func getOCFResourcesProperties(deviceID uuid.UUID, baseURL string, cloudEnabled, return nil, errors.New("maintenance resource not found") } properties[schemaMaintenance.ResourceURI] = maintenanceResource - maintenanceResource, err = thingDescriptionResource.PatchMaintenanceResourcePropertyElement(maintenanceResource, deviceID, baseURL, message.AppCBOR.String()) + maintenanceResource, err = thingDescriptionResource.PatchMaintenanceResourcePropertyElement(maintenanceResource, deviceID, baseURL, message.AppCBOR) if err != nil { return nil, err } @@ -185,7 +185,7 @@ func getOCFResourcesProperties(deviceID uuid.UUID, baseURL string, cloudEnabled, if !ok { return nil, errors.New("cloud resource not found") } - cloudResource, err = thingDescriptionResource.PatchCloudResourcePropertyElement(cloudResource, deviceID, baseURL, message.AppCBOR.String()) + cloudResource, err = thingDescriptionResource.PatchCloudResourcePropertyElement(cloudResource, deviceID, baseURL, message.AppCBOR) if err != nil { return nil, err } @@ -197,7 +197,7 @@ func getOCFResourcesProperties(deviceID uuid.UUID, baseURL string, cloudEnabled, if !ok { return nil, errors.New("credential resource not found") } - credentialResource, err = thingDescriptionResource.PatchCredentialResourcePropertyElement(credentialResource, deviceID, baseURL, message.AppCBOR.String()) + credentialResource, err = thingDescriptionResource.PatchCredentialResourcePropertyElement(credentialResource, deviceID, baseURL, message.AppCBOR) if err != nil { return nil, err } diff --git a/cmd/bridge-device/device/device.go b/cmd/bridge-device/device/device.go index 3d5c879f..e64519d3 100644 --- a/cmd/bridge-device/device/device.go +++ b/cmd/bridge-device/device/device.go @@ -7,6 +7,7 @@ import ( "github.com/google/uuid" bridgeTD "github.com/plgd-dev/device/v2/bridge/device/thingDescription" + "github.com/plgd-dev/go-coap/v3/message" "github.com/web-of-things-open-source/thingdescription-go/thingDescription" ) @@ -41,7 +42,7 @@ func GetPropertyDescriptionForTestResource() thingDescription.PropertyElement { } } -func PatchTestResourcePropertyElement(pe thingDescription.PropertyElement, deviceID uuid.UUID, href, contentType string) (thingDescription.PropertyElement, error) { +func PatchTestResourcePropertyElement(pe thingDescription.PropertyElement, deviceID uuid.UUID, href string, contentType message.MediaType) (thingDescription.PropertyElement, error) { propOps := bridgeTD.GetPropertyElementOperations(pe) return bridgeTD.PatchPropertyElement(pe, []string{TestResourceType}, true, deviceID, href, propOps.ToSupportedOperations(), contentType) diff --git a/cmd/bridge-device/main.go b/cmd/bridge-device/main.go index fa2115d3..bb63d54c 100644 --- a/cmd/bridge-device/main.go +++ b/cmd/bridge-device/main.go @@ -97,7 +97,7 @@ func patchPropertyElement(td wotTD.ThingDescription, dev *device.Device, endpoin if !ok { return wotTD.PropertyElement{}, false } - propElement, err := thingDescription.PatchPropertyElement(propElement, resource.GetResourceTypes(), endpoint != "", dev.GetID(), resource.GetHref(), resource.SupportsOperations(), message.AppCBOR.String()) + propElement, err := thingDescription.PatchPropertyElement(propElement, resource.GetResourceTypes(), endpoint != "", dev.GetID(), resource.GetHref(), resource.SupportsOperations(), message.AppCBOR) return propElement, err == nil } diff --git a/go.mod b/go.mod index 396e2a8c..b99f7a5c 100644 --- a/go.mod +++ b/go.mod @@ -20,7 +20,7 @@ require ( github.com/plgd-dev/kit/v2 v2.0.0-20211006190727-057b33161b90 github.com/stretchr/testify v1.9.0 github.com/ugorji/go/codec v1.2.12 - github.com/web-of-things-open-source/thingdescription-go v0.0.0-20240510090525-772cd4ad3459 + github.com/web-of-things-open-source/thingdescription-go v0.0.0-20240510130416-741fef736e1e go.uber.org/atomic v1.11.0 golang.org/x/sync v0.7.0 google.golang.org/grpc v1.63.2 diff --git a/go.sum b/go.sum index 898e1f20..08cc6127 100644 --- a/go.sum +++ b/go.sum @@ -139,8 +139,8 @@ github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZ github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.12.0/go.mod h1:229t1eWu9UXTPmoUkbpN/fctKPBY4IJoFXQnxHGXy6E= github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= -github.com/web-of-things-open-source/thingdescription-go v0.0.0-20240510090525-772cd4ad3459 h1:5JIsujthXmSrKC318Y6UJRyQ2yysV0cuen70fL9LW3U= -github.com/web-of-things-open-source/thingdescription-go v0.0.0-20240510090525-772cd4ad3459/go.mod h1:L/jWuWf+v7rmuFykpUP/runRXTnnA0QdGGgou8vzPrw= +github.com/web-of-things-open-source/thingdescription-go v0.0.0-20240510130416-741fef736e1e h1:blQyU8WqqyRcBmaAPLiU5cTg9BSQu04CJZ/ffEzgI1s= +github.com/web-of-things-open-source/thingdescription-go v0.0.0-20240510130416-741fef736e1e/go.mod h1:L/jWuWf+v7rmuFykpUP/runRXTnnA0QdGGgou8vzPrw= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=