diff --git a/bridge/device/thingDescription/thingDescription.go b/bridge/device/thingDescription/thingDescription.go index f770f185..b5b8f077 100644 --- a/bridge/device/thingDescription/thingDescription.go +++ b/bridge/device/thingDescription/thingDescription.go @@ -1,6 +1,7 @@ package thingDescription import ( + "errors" "net/http" "net/url" @@ -99,9 +100,20 @@ func (p PropertyElementOperations) ToSupportedOperations() resources.SupportedOp return ops | resources.SupportedOperationRead | resources.SupportedOperationWrite } -func createForm(hrefUri *url.URL, covMethod string, op thingDescription.StickyDescription, contentType message.MediaType) thingDescription.FormElementProperty { +type CreateFormFunc func(hrefUri *url.URL, op thingDescription.StickyDescription, contentType message.MediaType) (thingDescription.FormElementProperty, bool) + +func CreateCOAPForm(hrefUri *url.URL, op thingDescription.StickyDescription, contentType message.MediaType) (thingDescription.FormElementProperty, bool) { + methods := map[thingDescription.StickyDescription]string{ + thingDescription.Readproperty: http.MethodGet, + thingDescription.Writeproperty: http.MethodPost, + thingDescription.Observeproperty: http.MethodGet, + } + method, ok := methods[op] + if !ok { + return thingDescription.FormElementProperty{}, false + } additionalFields := map[string]interface{}{ - "cov:method": covMethod, + "cov:method": method, "cov:accept": float64(contentType), } ops := []string{string(op)} @@ -117,24 +129,46 @@ func createForm(hrefUri *url.URL, covMethod string, op thingDescription.StickyDe StringArray: ops, }, AdditionalFields: additionalFields, - } + }, true } -func SetForms(hrefUri *url.URL, ops resources.SupportedOperation, contentType message.MediaType) []thingDescription.FormElementProperty { +type CreateFormsFunc func(hrefUri *url.URL, ops resources.SupportedOperation, contentType message.MediaType) []thingDescription.FormElementProperty + +func CreateCOAPForms(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)) + form, ok := CreateCOAPForm(hrefUri, thingDescription.Writeproperty, contentType) + if ok { + forms = append(forms, form) + } } if ops.HasOperation(resources.SupportedOperationRead) { - forms = append(forms, createForm(hrefUri, http.MethodGet, thingDescription.Readproperty, contentType)) + form, ok := CreateCOAPForm(hrefUri, thingDescription.Readproperty, contentType) + if ok { + forms = append(forms, form) + } } if ops.HasOperation(resources.SupportedOperationObserve) { - forms = append(forms, createForm(hrefUri, http.MethodGet, thingDescription.Observeproperty, contentType)) + form, ok := CreateCOAPForm(hrefUri, thingDescription.Observeproperty, contentType) + if ok { + forms = append(forms, form) + } } 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) { +func GetPropertyHref(deviceID uuid.UUID, href string) (*url.URL, error) { + if len(href) == 0 { + return nil, errors.New("href is empty") + } + hrefStr := href + if deviceID != uuid.Nil { + hrefStr += "?di=" + deviceID.String() + } + return url.Parse(hrefStr) +} + +func PatchPropertyElement(prop thingDescription.PropertyElement, types []string, deviceID uuid.UUID, href string, ops resources.SupportedOperation, contentType message.MediaType, createForms CreateFormsFunc) (thingDescription.PropertyElement, error) { if len(types) > 0 { prop.Type = &thingDescription.TypeDeclaration{ StringArray: types, @@ -144,26 +178,18 @@ func PatchPropertyElement(prop thingDescription.PropertyElement, types []string, prop.Observable = BoolToPtr(propOps.Observable) prop.ReadOnly = BoolToPtr(propOps.ReadOnly) prop.WriteOnly = BoolToPtr(propOps.WriteOnly) - if !setForm { + if createForms == nil { return prop, nil } opsStrs := SupportedOperationToTDOperations(ops) if len(opsStrs) == 0 { return prop, nil } - var hrefUri *url.URL - if len(href) > 0 { - hrefStr := href - if deviceID != uuid.Nil { - hrefStr += "?di=" + deviceID.String() - } - var err error - hrefUri, err = url.Parse(hrefStr) - if err != nil { - return thingDescription.PropertyElement{}, err - } + hrefUri, err := GetPropertyHref(deviceID, href) + if err != nil { + return thingDescription.PropertyElement{}, err } - prop.Forms = SetForms(hrefUri, ops, contentType) + prop.Forms = createForms(hrefUri, ops, contentType) return prop, nil } diff --git a/bridge/resources/thingDescription/ocfResources.go b/bridge/resources/thingDescription/ocfResources.go index ca704490..9cdd7def 100644 --- a/bridge/resources/thingDescription/ocfResources.go +++ b/bridge/resources/thingDescription/ocfResources.go @@ -40,27 +40,27 @@ func GetOCFResourcePropertyElement(resourceHref string) (thingDescription.Proper return prop, true } -func patchResourcePropertyElement(pe thingDescription.PropertyElement, deviceID uuid.UUID, resourceTypes []string, resourceHref string, contentType message.MediaType) (thingDescription.PropertyElement, error) { +func patchResourcePropertyElement(pe thingDescription.PropertyElement, deviceID uuid.UUID, resourceTypes []string, resourceHref string, contentType message.MediaType, createForms bridgeTD.CreateFormsFunc) (thingDescription.PropertyElement, error) { propOps := bridgeTD.GetPropertyElementOperations(pe) - return bridgeTD.PatchPropertyElement(pe, resourceTypes, true, deviceID, resourceHref, propOps.ToSupportedOperations(), contentType) + return bridgeTD.PatchPropertyElement(pe, resourceTypes, deviceID, resourceHref, propOps.ToSupportedOperations(), contentType, createForms) } -func PatchDeviceResourcePropertyElement(pe thingDescription.PropertyElement, deviceID uuid.UUID, baseURL string, contentType message.MediaType, deviceType string) (thingDescription.PropertyElement, error) { +func PatchDeviceResourcePropertyElement(pe thingDescription.PropertyElement, deviceID uuid.UUID, baseURL string, contentType message.MediaType, deviceType string, createForms bridgeTD.CreateFormsFunc) (thingDescription.PropertyElement, error) { var types []string if deviceType != "" { types = []string{schemaDevice.ResourceType, deviceType} } - return patchResourcePropertyElement(pe, deviceID, types, baseURL+schemaDevice.ResourceURI, contentType) + return patchResourcePropertyElement(pe, deviceID, types, baseURL+schemaDevice.ResourceURI, contentType, createForms) } -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 PatchMaintenanceResourcePropertyElement(pe thingDescription.PropertyElement, deviceID uuid.UUID, baseURL string, contentType message.MediaType, createForms bridgeTD.CreateFormsFunc) (thingDescription.PropertyElement, error) { + return patchResourcePropertyElement(pe, deviceID, []string{schemaMaintenance.ResourceType}, baseURL+schemaMaintenance.ResourceURI, contentType, createForms) } -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 PatchCloudResourcePropertyElement(pe thingDescription.PropertyElement, deviceID uuid.UUID, baseURL string, contentType message.MediaType, createForms bridgeTD.CreateFormsFunc) (thingDescription.PropertyElement, error) { + return patchResourcePropertyElement(pe, deviceID, []string{schemaCloud.ResourceType}, baseURL+schemaCloud.ResourceURI, contentType, createForms) } -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) +func PatchCredentialResourcePropertyElement(pe thingDescription.PropertyElement, deviceID uuid.UUID, baseURL string, contentType message.MediaType, createForms bridgeTD.CreateFormsFunc) (thingDescription.PropertyElement, error) { + return patchResourcePropertyElement(pe, deviceID, []string{schemaCredential.ResourceType}, baseURL+schemaCredential.ResourceURI, contentType, createForms) } diff --git a/bridge/test/test.go b/bridge/test/test.go index 8edcf8c9..eed3e3e1 100644 --- a/bridge/test/test.go +++ b/bridge/test/test.go @@ -120,8 +120,12 @@ func GetPropertyElement(td wotTD.ThingDescription, device bridgeDeviceTD.Device, if !ok { return wotTD.PropertyElement{}, false } - propElement, err := bridgeDeviceTD.PatchPropertyElement(propElement, resource.GetResourceTypes(), endpoint != "", device.GetID(), resource.GetHref(), - resource.SupportsOperations(), contentType) + var f bridgeDeviceTD.CreateFormsFunc + if endpoint != "" { + f = bridgeDeviceTD.CreateCOAPForms + } + propElement, err := bridgeDeviceTD.PatchPropertyElement(propElement, resource.GetResourceTypes(), device.GetID(), resource.GetHref(), + resource.SupportsOperations(), contentType, f) return propElement, err == nil } @@ -163,7 +167,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, "") + deviceResource, err := thingDescriptionResource.PatchDeviceResourcePropertyElement(deviceResource, deviceID, baseURL, message.AppCBOR, "", bridgeDeviceTD.CreateCOAPForms) if err != nil { return nil, err } @@ -174,7 +178,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) + maintenanceResource, err = thingDescriptionResource.PatchMaintenanceResourcePropertyElement(maintenanceResource, deviceID, baseURL, message.AppCBOR, bridgeDeviceTD.CreateCOAPForms) if err != nil { return nil, err } @@ -185,7 +189,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) + cloudResource, err = thingDescriptionResource.PatchCloudResourcePropertyElement(cloudResource, deviceID, baseURL, message.AppCBOR, bridgeDeviceTD.CreateCOAPForms) if err != nil { return nil, err } @@ -197,7 +201,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) + credentialResource, err = thingDescriptionResource.PatchCredentialResourcePropertyElement(credentialResource, deviceID, baseURL, message.AppCBOR, bridgeDeviceTD.CreateCOAPForms) if err != nil { return nil, err } diff --git a/cmd/bridge-device/config.yaml b/cmd/bridge-device/config.yaml index 098c4e00..846338b3 100644 --- a/cmd/bridge-device/config.yaml +++ b/cmd/bridge-device/config.yaml @@ -3,8 +3,8 @@ apis: id: 8f596b43-29c0-4147-8b40-e99268ab30f7 name: "my-bridge-example" externalAddresses: - - "127.0.0.1:15683" - - "[::1]:15683" + - "127.0.0.1:35683" + - "[::1]:35683" maxMessageSize: 2097152 log: level: "info" diff --git a/cmd/bridge-device/device/device.go b/cmd/bridge-device/device/device.go index e64519d3..e82b8cb9 100644 --- a/cmd/bridge-device/device/device.go +++ b/cmd/bridge-device/device/device.go @@ -42,10 +42,10 @@ func GetPropertyDescriptionForTestResource() thingDescription.PropertyElement { } } -func PatchTestResourcePropertyElement(pe thingDescription.PropertyElement, deviceID uuid.UUID, href string, contentType message.MediaType) (thingDescription.PropertyElement, error) { +func PatchTestResourcePropertyElement(pe thingDescription.PropertyElement, deviceID uuid.UUID, href string, contentType message.MediaType, createForms bridgeTD.CreateFormsFunc) (thingDescription.PropertyElement, error) { propOps := bridgeTD.GetPropertyElementOperations(pe) - return bridgeTD.PatchPropertyElement(pe, []string{TestResourceType}, true, deviceID, href, - propOps.ToSupportedOperations(), contentType) + return bridgeTD.PatchPropertyElement(pe, []string{TestResourceType}, deviceID, href, + propOps.ToSupportedOperations(), contentType, createForms) } func GetAdditionalProperties() map[string]interface{} { diff --git a/cmd/bridge-device/main.go b/cmd/bridge-device/main.go index bb63d54c..96b45a08 100644 --- a/cmd/bridge-device/main.go +++ b/cmd/bridge-device/main.go @@ -97,7 +97,11 @@ 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) + var f thingDescription.CreateFormsFunc + if endpoint != "" { + f = thingDescription.CreateCOAPForms + } + propElement, err := thingDescription.PatchPropertyElement(propElement, resource.GetResourceTypes(), dev.GetID(), resource.GetHref(), resource.SupportsOperations(), message.AppCBOR, f) return propElement, err == nil }