From c13f5d060823c3846e51280517eba95442681a1c Mon Sep 17 00:00:00 2001 From: Chris Hung Date: Wed, 17 Mar 2021 16:18:44 +0800 Subject: [PATCH] feat: add CBOR support in EventClient for binary reading Signed-off-by: Chris Hung --- v2/clients/http/device.go | 3 ++- v2/clients/http/deviceprofile.go | 3 ++- v2/clients/http/deviceservice.go | 3 ++- v2/clients/http/deviceservicecallback.go | 5 +++-- v2/clients/http/event.go | 17 ++++++++++++++- v2/clients/http/provisionwatcher.go | 3 ++- v2/clients/http/utils/common.go | 27 ++++++++++++++++++------ v2/clients/http/utils/request.go | 14 ++++++------ v2/constants.go | 7 ++++++ 9 files changed, 62 insertions(+), 20 deletions(-) diff --git a/v2/clients/http/device.go b/v2/clients/http/device.go index 8956ccf9..b066d8bc 100644 --- a/v2/clients/http/device.go +++ b/v2/clients/http/device.go @@ -7,6 +7,7 @@ import ( "strconv" "strings" + "github.com/edgexfoundry/go-mod-core-contracts/v2/clients" "github.com/edgexfoundry/go-mod-core-contracts/v2/errors" "github.com/edgexfoundry/go-mod-core-contracts/v2/v2" "github.com/edgexfoundry/go-mod-core-contracts/v2/v2/clients/http/utils" @@ -28,7 +29,7 @@ func NewDeviceClient(baseUrl string) interfaces.DeviceClient { } func (dc DeviceClient) Add(ctx context.Context, reqs []requests.AddDeviceRequest) (res []common.BaseWithIdResponse, err errors.EdgeX) { - err = utils.PostRequest(ctx, &res, dc.baseUrl+v2.ApiDeviceRoute, reqs) + err = utils.PostRequest(ctx, &res, dc.baseUrl+v2.ApiDeviceRoute, reqs, clients.ContentTypeJSON) if err != nil { return res, errors.NewCommonEdgeXWrapper(err) } diff --git a/v2/clients/http/deviceprofile.go b/v2/clients/http/deviceprofile.go index 25f368a0..598b9bf3 100644 --- a/v2/clients/http/deviceprofile.go +++ b/v2/clients/http/deviceprofile.go @@ -12,6 +12,7 @@ import ( "strconv" "strings" + "github.com/edgexfoundry/go-mod-core-contracts/v2/clients" "github.com/edgexfoundry/go-mod-core-contracts/v2/errors" "github.com/edgexfoundry/go-mod-core-contracts/v2/v2" "github.com/edgexfoundry/go-mod-core-contracts/v2/v2/clients/http/utils" @@ -34,7 +35,7 @@ func NewDeviceProfileClient(baseUrl string) interfaces.DeviceProfileClient { func (client *DeviceProfileClient) Add(ctx context.Context, reqs []requests.DeviceProfileRequest) ([]common.BaseWithIdResponse, errors.EdgeX) { var responses []common.BaseWithIdResponse - err := utils.PostRequest(ctx, &responses, client.baseUrl+v2.ApiDeviceProfileRoute, reqs) + err := utils.PostRequest(ctx, &responses, client.baseUrl+v2.ApiDeviceProfileRoute, reqs, clients.ContentTypeJSON) if err != nil { return responses, errors.NewCommonEdgeXWrapper(err) } diff --git a/v2/clients/http/deviceservice.go b/v2/clients/http/deviceservice.go index 1ffd8165..3420ca1e 100644 --- a/v2/clients/http/deviceservice.go +++ b/v2/clients/http/deviceservice.go @@ -7,6 +7,7 @@ import ( "strconv" "strings" + "github.com/edgexfoundry/go-mod-core-contracts/v2/clients" "github.com/edgexfoundry/go-mod-core-contracts/v2/errors" "github.com/edgexfoundry/go-mod-core-contracts/v2/v2" "github.com/edgexfoundry/go-mod-core-contracts/v2/v2/clients/http/utils" @@ -29,7 +30,7 @@ func NewDeviceServiceClient(baseUrl string) interfaces.DeviceServiceClient { func (dsc DeviceServiceClient) Add(ctx context.Context, reqs []requests.AddDeviceServiceRequest) ( res []common.BaseWithIdResponse, err errors.EdgeX) { - err = utils.PostRequest(ctx, &res, dsc.baseUrl+v2.ApiDeviceServiceRoute, reqs) + err = utils.PostRequest(ctx, &res, dsc.baseUrl+v2.ApiDeviceServiceRoute, reqs, clients.ContentTypeJSON) if err != nil { return res, errors.NewCommonEdgeXWrapper(err) } diff --git a/v2/clients/http/deviceservicecallback.go b/v2/clients/http/deviceservicecallback.go index 0dcc9baa..f298d2b6 100644 --- a/v2/clients/http/deviceservicecallback.go +++ b/v2/clients/http/deviceservicecallback.go @@ -9,6 +9,7 @@ import ( "context" "path" + "github.com/edgexfoundry/go-mod-core-contracts/v2/clients" "github.com/edgexfoundry/go-mod-core-contracts/v2/errors" "github.com/edgexfoundry/go-mod-core-contracts/v2/v2" "github.com/edgexfoundry/go-mod-core-contracts/v2/v2/clients/http/utils" @@ -30,7 +31,7 @@ func NewDeviceServiceCallbackClient(baseUrl string) interfaces.DeviceServiceCall func (client *deviceServiceCallbackClient) AddDeviceCallback(ctx context.Context, request requests.AddDeviceRequest) (common.BaseResponse, errors.EdgeX) { var response common.BaseResponse - err := utils.PostRequest(ctx, &response, client.baseUrl+v2.ApiDeviceCallbackRoute, request) + err := utils.PostRequest(ctx, &response, client.baseUrl+v2.ApiDeviceCallbackRoute, request, clients.ContentTypeJSON) if err != nil { return response, errors.NewCommonEdgeXWrapper(err) } @@ -67,7 +68,7 @@ func (client *deviceServiceCallbackClient) UpdateDeviceProfileCallback(ctx conte func (client *deviceServiceCallbackClient) AddProvisionWatcherCallback(ctx context.Context, request requests.AddProvisionWatcherRequest) (common.BaseResponse, errors.EdgeX) { var response common.BaseResponse - err := utils.PostRequest(ctx, &response, client.baseUrl+v2.ApiWatcherCallbackRoute, request) + err := utils.PostRequest(ctx, &response, client.baseUrl+v2.ApiWatcherCallbackRoute, request, clients.ContentTypeJSON) if err != nil { return response, errors.NewCommonEdgeXWrapper(err) } diff --git a/v2/clients/http/event.go b/v2/clients/http/event.go index 2db14e98..a84a50f7 100644 --- a/v2/clients/http/event.go +++ b/v2/clients/http/event.go @@ -8,9 +8,11 @@ package http import ( "context" "net/url" + "os" "path" "strconv" + "github.com/edgexfoundry/go-mod-core-contracts/v2/clients" "github.com/edgexfoundry/go-mod-core-contracts/v2/errors" "github.com/edgexfoundry/go-mod-core-contracts/v2/v2" "github.com/edgexfoundry/go-mod-core-contracts/v2/v2/clients/http/utils" @@ -35,7 +37,20 @@ func (ec *eventClient) Add(ctx context.Context, req requests.AddEventRequest) ( common.BaseWithIdResponse, errors.EdgeX) { path := path.Join(v2.ApiEventRoute, url.QueryEscape(req.Event.ProfileName), url.QueryEscape(req.Event.DeviceName), url.QueryEscape(req.Event.SourceName)) var br common.BaseWithIdResponse - err := utils.PostRequest(ctx, &br, ec.baseUrl+path, req) + var encoding string + + for _, r := range req.Event.Readings { + if r.ValueType == v2.ValueTypeBinary { + encoding = clients.ContentTypeCBOR + break + } + } + + if v := os.Getenv(v2.EnvEncodeAllEvents); v == v2.ValueTrue { + encoding = clients.ContentTypeCBOR + } + + err := utils.PostRequest(ctx, &br, ec.baseUrl+path, req, encoding) if err != nil { return br, errors.NewCommonEdgeXWrapper(err) } diff --git a/v2/clients/http/provisionwatcher.go b/v2/clients/http/provisionwatcher.go index 6441dfb5..66bd2aae 100644 --- a/v2/clients/http/provisionwatcher.go +++ b/v2/clients/http/provisionwatcher.go @@ -12,6 +12,7 @@ import ( "strconv" "strings" + "github.com/edgexfoundry/go-mod-core-contracts/v2/clients" "github.com/edgexfoundry/go-mod-core-contracts/v2/errors" "github.com/edgexfoundry/go-mod-core-contracts/v2/v2" "github.com/edgexfoundry/go-mod-core-contracts/v2/v2/clients/http/utils" @@ -33,7 +34,7 @@ func NewProvisionWatcherClient(baseUrl string) interfaces.ProvisionWatcherClient } func (pwc ProvisionWatcherClient) Add(ctx context.Context, reqs []requests.AddProvisionWatcherRequest) (res []common.BaseWithIdResponse, err errors.EdgeX) { - err = utils.PostRequest(ctx, &res, pwc.baseUrl+v2.ApiProvisionWatcherRoute, reqs) + err = utils.PostRequest(ctx, &res, pwc.baseUrl+v2.ApiProvisionWatcherRoute, reqs, clients.ContentTypeJSON) if err != nil { return res, errors.NewCommonEdgeXWrapper(err) } diff --git a/v2/clients/http/utils/common.go b/v2/clients/http/utils/common.go index 3f5c0b41..a8d63166 100644 --- a/v2/clients/http/utils/common.go +++ b/v2/clients/http/utils/common.go @@ -1,5 +1,5 @@ // -// Copyright (C) 2020 IOTech Ltd +// Copyright (C) 2020-2021 IOTech Ltd // // SPDX-License-Identifier: Apache-2.0 @@ -17,6 +17,8 @@ import ( "net/url" "path/filepath" + "github.com/fxamacker/cbor/v2" + "github.com/edgexfoundry/go-mod-core-contracts/v2/clients" "github.com/edgexfoundry/go-mod-core-contracts/v2/errors" @@ -79,18 +81,29 @@ func createRequest(ctx context.Context, httpMethod string, baseUrl string, reque return req, nil } -func createRequestWithRawData(ctx context.Context, httpMethod string, url string, data interface{}) (*http.Request, errors.EdgeX) { - jsonEncodedData, err := json.Marshal(data) - if err != nil { - return nil, errors.NewCommonEdgeX(errors.KindContractInvalid, "failed to encode input data to JSON", err) +func createRequestWithRawData(ctx context.Context, httpMethod string, url string, data interface{}, encoding string) (*http.Request, errors.EdgeX) { + var err error + var encodedData []byte + + if encoding == clients.ContentTypeJSON || encoding == "" { + encoding = clients.ContentTypeJSON + encodedData, err = json.Marshal(data) + if err != nil { + return nil, errors.NewCommonEdgeX(errors.KindContractInvalid, "failed to encode input data to JSON", err) + } + } else if encoding == clients.ContentTypeCBOR { + encodedData, err = cbor.Marshal(data) + if err != nil { + return nil, errors.NewCommonEdgeX(errors.KindContractInvalid, "failed to encode input data to CBOR", err) + } } content := FromContext(ctx, clients.ContentType) if content == "" { - content = clients.ContentTypeJSON + content = encoding } - req, err := http.NewRequest(httpMethod, url, bytes.NewReader(jsonEncodedData)) + req, err := http.NewRequest(httpMethod, url, bytes.NewReader(encodedData)) if err != nil { return nil, errors.NewCommonEdgeX(errors.KindClientError, "failed to create a http request", err) } diff --git a/v2/clients/http/utils/request.go b/v2/clients/http/utils/request.go index ec65d58a..152c0e03 100644 --- a/v2/clients/http/utils/request.go +++ b/v2/clients/http/utils/request.go @@ -1,5 +1,5 @@ // -// Copyright (C) 2020 IOTech Ltd +// Copyright (C) 2020-2021 IOTech Ltd // // SPDX-License-Identifier: Apache-2.0 @@ -11,6 +11,7 @@ import ( "net/http" "net/url" + "github.com/edgexfoundry/go-mod-core-contracts/v2/clients" "github.com/edgexfoundry/go-mod-core-contracts/v2/errors" ) @@ -31,14 +32,15 @@ func GetRequest(ctx context.Context, returnValuePointer interface{}, baseUrl str return nil } -// Helper method to make the post JSON request and return the body +// Helper method to make the post JSON/CBOR request and return the body func PostRequest( ctx context.Context, returnValuePointer interface{}, url string, - data interface{}) errors.EdgeX { + data interface{}, + encoding string) errors.EdgeX { - req, err := createRequestWithRawData(ctx, http.MethodPost, url, data) + req, err := createRequestWithRawData(ctx, http.MethodPost, url, data, encoding) if err != nil { return errors.NewCommonEdgeXWrapper(err) } @@ -60,7 +62,7 @@ func PutRequest( url string, data interface{}) errors.EdgeX { - req, err := createRequestWithRawData(ctx, http.MethodPut, url, data) + req, err := createRequestWithRawData(ctx, http.MethodPut, url, data, clients.ContentTypeJSON) if err != nil { return errors.NewCommonEdgeXWrapper(err) } @@ -82,7 +84,7 @@ func PatchRequest( url string, data interface{}) errors.EdgeX { - req, err := createRequestWithRawData(ctx, http.MethodPatch, url, data) + req, err := createRequestWithRawData(ctx, http.MethodPatch, url, data, clients.ContentTypeJSON) if err != nil { return errors.NewCommonEdgeXWrapper(err) } diff --git a/v2/constants.go b/v2/constants.go index 4bdc7635..74ab708c 100644 --- a/v2/constants.go +++ b/v2/constants.go @@ -154,6 +154,8 @@ const ( CommaSeparator = "," ValueYes = "yes" ValueNo = "no" + ValueTrue = "true" + ValueFalse = "false" ) // Constants related to Reading ValueTypes @@ -205,3 +207,8 @@ const ( ReadWrite_W = "W" ReadWrite_RW = "RW" ) + +// Constants for Edgex Environment variable +const ( + EnvEncodeAllEvents = "EDGEX_ENCODE_ALL_EVENTS_CBOR" +)