Skip to content

Commit

Permalink
feat: Add new FilterBySourceName function (#731)
Browse files Browse the repository at this point in the history
* refactor: Remove V1 API code and swagger

Also reworked V2 code to remove `v2` in paths

closes #720

BREAKING CHANGE: V1 API's no longer supported

Signed-off-by: lenny <[email protected]>
  • Loading branch information
lenny-goodell authored Mar 4, 2021
1 parent 7e0294b commit 3ee2f0b
Show file tree
Hide file tree
Showing 11 changed files with 218 additions and 107 deletions.
5 changes: 3 additions & 2 deletions app-service-template/functions/sample_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,12 @@ func TestSample_OutputXML(t *testing.T) {
}

func createTestEvent(t *testing.T) dtos.Event {
deviceName := "MyDevice"
profileName := "MyProfile"
deviceName := "MyDevice"
sourceName := "MySource"
resourceName := "MyResource"

event := dtos.NewEvent(profileName, deviceName)
event := dtos.NewEvent(profileName, deviceName, sourceName)
err := event.AddSimpleReading(resourceName, v2.ValueTypeInt32, int32(1234))
require.NoError(t, err)

Expand Down
2 changes: 1 addition & 1 deletion app-service-template/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ go 1.15

require (
github.com/edgexfoundry/app-functions-sdk-go/v2 v2.0.0-dev.14
github.com/edgexfoundry/go-mod-core-contracts/v2 v2.0.0-dev.35
github.com/edgexfoundry/go-mod-core-contracts/v2 v2.0.0-dev.42
github.com/google/uuid v1.2.0
github.com/stretchr/testify v1.7.0
)
Expand Down
18 changes: 18 additions & 0 deletions appsdk/configurable.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
const (
ProfileNames = "profilenames"
DeviceNames = "devicenames"
SourceNames = "sourcenames"
ResourceNames = "resourcenames"
FilterOut = "filterout"
EncryptionKey = "key"
Expand Down Expand Up @@ -120,6 +121,23 @@ func (dynamic AppFunctionsSDKConfigurable) FilterByDeviceName(parameters map[str
return transform.FilterByDeviceName
}

// FilterBySourceName - Specify the source names (resources and/or commands) of interest to filter for data coming from certain sensors.
// The Filter by Source Name transform looks at the Event in the message and looks at the source names of interest list,
// provided by this function, and filters out those messages whose Event is for source names not in the
// source names of interest.
// This function will return an error and stop the pipeline if a non-edgex
// event is received or if no data is received.
// For example, data generated by a motor does not get passed to functions only interested in data from a thermostat.
// This function is a configuration function and returns a function pointer.
func (dynamic AppFunctionsSDKConfigurable) FilterBySourceName(parameters map[string]string) appcontext.AppFunction {
transform, ok := dynamic.processFilterParameters("FilterBySourceName", parameters, SourceNames)
if !ok {
return nil
}

return transform.FilterBySourceName
}

// FilterByResourceName - Specify the resource name of interest to filter for data from certain types of IoT objects,
// such as temperatures, motion, and so forth, that may come from an array of sensors or devices. The Filter by resource name assesses
// the data in each Event and Reading, and removes readings that have a resource name that is not in the list of
Expand Down
30 changes: 30 additions & 0 deletions appsdk/configurable_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,36 @@ func TestFilterByDeviceName(t *testing.T) {
}
}

func TestFilterBySourceName(t *testing.T) {
configurable := AppFunctionsSDKConfigurable{
Sdk: &AppFunctionsSDK{
LoggingClient: lc,
},
}

tests := []struct {
name string
params map[string]string
expectNil bool
}{
{"Non Existent Parameters", map[string]string{"": ""}, true},
{"Empty Parameters", map[string]string{SourceNames: ""}, false},
{"Valid Parameters", map[string]string{SourceNames: "R1, C2, R4"}, false},
{"Empty FilterOut Parameters", map[string]string{SourceNames: "R1, C2, R4", FilterOut: ""}, true},
{"Valid FilterOut Parameters", map[string]string{SourceNames: "R1, C2, R4", FilterOut: "true"}, false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
trx := configurable.FilterBySourceName(tt.params)
if tt.expectNil {
assert.Nil(t, trx, "return result from FilterBySourceName should be nil")
} else {
assert.NotNil(t, trx, "return result from FilterBySourceName should not be nil")
}
})
}
}

func TestFilterByResourceName(t *testing.T) {
configurable := AppFunctionsSDKConfigurable{
Sdk: &AppFunctionsSDK{
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ require (
bitbucket.org/bertimus9/systemstat v0.0.0-20180207000608-0eeff89b0690
github.com/diegoholiveira/jsonlogic v1.0.1-0.20200220175622-ab7989be08b9
github.com/eclipse/paho.mqtt.golang v1.2.0
github.com/edgexfoundry/go-mod-bootstrap/v2 v2.0.0-dev.13
github.com/edgexfoundry/go-mod-core-contracts/v2 v2.0.0-dev.35
github.com/edgexfoundry/go-mod-bootstrap/v2 v2.0.0-dev.14
github.com/edgexfoundry/go-mod-core-contracts/v2 v2.0.0-dev.42
github.com/edgexfoundry/go-mod-messaging/v2 v2.0.0-dev.3
github.com/edgexfoundry/go-mod-registry/v2 v2.0.0-dev.3
github.com/fxamacker/cbor/v2 v2.2.0
Expand Down
3 changes: 2 additions & 1 deletion internal/runtime/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -288,8 +288,9 @@ func (gr *GolangRuntime) unmarshalV1EventToV2Event(envelope types.MessageEnvelop
v2Event := dtos.Event{
Versionable: commonDTO.NewVersionable(),
Id: v1Event.ID,
DeviceName: v1Event.Device,
ProfileName: "Unknown",
DeviceName: v1Event.Device,
SourceName: "Unknown",
Created: v1Event.Created,
Origin: v1Event.Origin,
Tags: v1Event.Tags,
Expand Down
6 changes: 4 additions & 2 deletions internal/runtime/runtime_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ var testAddEventRequest = createAddEventRequest()
var testV2Event = testAddEventRequest.Event

func createAddEventRequest() requests.AddEventRequest {
event := dtos.NewEvent("Thermostat", "FamilyRoomThermostat")
event := dtos.NewEvent("Thermostat", "FamilyRoomThermostat", "Temperature")
event.AddSimpleReading("Temperature", v2.ValueTypeInt64, int64(72))
request := requests.NewAddEventRequest(event)
return request
Expand Down Expand Up @@ -252,7 +252,7 @@ func TestProcessMessageThreeCustomTransformsOneFail(t *testing.T) {

func TestProcessMessageTransformError(t *testing.T) {
// Error expected from FilterByDeviceName
expectedError := "type received is not an Event"
expectedError := "FilterByDeviceName: type received is not an Event"
expectedErrorCode := http.StatusUnprocessableEntity

// Send a RegistryInfo to the pipeline, instead of an Event
Expand Down Expand Up @@ -544,6 +544,7 @@ func TestGolangRuntime_processEventPayload(t *testing.T) {
expectedV2Event := testV2Event
expectedV2EventFromV1Event := testV2Event
expectedV2EventFromV1Event.ProfileName = "Unknown"
expectedV2EventFromV1Event.SourceName = "Unknown"
expectedV2EventFromV1Event.Readings = []dtos.BaseReading{testV2Event.Readings[0]}
expectedV2EventFromV1Event.Readings[0].ProfileName = "Unknown"

Expand Down Expand Up @@ -592,6 +593,7 @@ func TestGolangRuntime_unmarshalV1EventToV2Event(t *testing.T) {

expectedEvent := testV2Event
expectedEvent.ProfileName = "Unknown"
expectedEvent.SourceName = "Unknown"
expectedEvent.Readings[0].ProfileName = "Unknown"

tests := []struct {
Expand Down
2 changes: 1 addition & 1 deletion internal/trigger/messagebus/messaging_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ var addEventRequest = createTestEventRequest()
var expectedEvent = addEventRequest.Event

func createTestEventRequest() requests.AddEventRequest {
event := dtos.NewEvent("thermostat", "LivingRoomThermostat")
event := dtos.NewEvent("thermostat", "LivingRoomThermostat", "temperature")
_ = event.AddSimpleReading("temperature", v2.ValueTypeInt64, int64(38))
request := requests.NewAddEventRequest(event)
return request
Expand Down
12 changes: 6 additions & 6 deletions pkg/transforms/conversion_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func TestTransformToXML(t *testing.T) {
eventIn := dtos.Event{
DeviceName: deviceName1,
}
expectedResult := `<Event><ApiVersion></ApiVersion><Id></Id><DeviceName>device1</DeviceName><ProfileName></ProfileName><Created>0</Created><Origin>0</Origin></Event>`
expectedResult := `<Event><ApiVersion></ApiVersion><Id></Id><DeviceName>device1</DeviceName><ProfileName></ProfileName><SourceName></SourceName><Created>0</Created><Origin>0</Origin></Event>`
conv := NewConversion()

continuePipeline, result := conv.TransformToXML(context, eventIn)
Expand Down Expand Up @@ -60,7 +60,7 @@ func TestTransformToXMLMultipleParametersValid(t *testing.T) {
eventIn := dtos.Event{
DeviceName: deviceName1,
}
expectedResult := `<Event><ApiVersion></ApiVersion><Id></Id><DeviceName>device1</DeviceName><ProfileName></ProfileName><Created>0</Created><Origin>0</Origin></Event>`
expectedResult := `<Event><ApiVersion></ApiVersion><Id></Id><DeviceName>device1</DeviceName><ProfileName></ProfileName><SourceName></SourceName><Created>0</Created><Origin>0</Origin></Event>`
conv := NewConversion()
continuePipeline, result := conv.TransformToXML(context, eventIn, "", "", "")
require.NotNil(t, result)
Expand All @@ -76,7 +76,7 @@ func TestTransformToXMLMultipleParametersTwoEvents(t *testing.T) {
eventIn2 := dtos.Event{
DeviceName: deviceName2,
}
expectedResult := `<Event><ApiVersion></ApiVersion><Id></Id><DeviceName>device2</DeviceName><ProfileName></ProfileName><Created>0</Created><Origin>0</Origin></Event>`
expectedResult := `<Event><ApiVersion></ApiVersion><Id></Id><DeviceName>device2</DeviceName><ProfileName></ProfileName><SourceName></SourceName><Created>0</Created><Origin>0</Origin></Event>`
conv := NewConversion()
continuePipeline, result := conv.TransformToXML(context, eventIn2, eventIn1, "", "")

Expand All @@ -91,7 +91,7 @@ func TestTransformToJSON(t *testing.T) {
eventIn := dtos.Event{
DeviceName: deviceName1,
}
expectedResult := `{"apiVersion":"","id":"","deviceName":"device1","profileName":"","origin":0,"readings":null}`
expectedResult := `{"apiVersion":"","id":"","deviceName":"device1","profileName":"","sourceName":"","origin":0,"readings":null}`
conv := NewConversion()
continuePipeline, result := conv.TransformToJSON(context, eventIn)

Expand Down Expand Up @@ -120,7 +120,7 @@ func TestTransformToJSONMultipleParametersValid(t *testing.T) {
eventIn := dtos.Event{
DeviceName: deviceName1,
}
expectedResult := `{"apiVersion":"","id":"","deviceName":"device1","profileName":"","origin":0,"readings":null}`
expectedResult := `{"apiVersion":"","id":"","deviceName":"device1","profileName":"","sourceName":"","origin":0,"readings":null}`
conv := NewConversion()
continuePipeline, result := conv.TransformToJSON(context, eventIn, "", "", "")
assert.NotNil(t, result)
Expand All @@ -137,7 +137,7 @@ func TestTransformToJSONMultipleParametersTwoEvents(t *testing.T) {
eventIn2 := dtos.Event{
DeviceName: deviceName2,
}
expectedResult := `{"apiVersion":"","id":"","deviceName":"device2","profileName":"","origin":0,"readings":null}`
expectedResult := `{"apiVersion":"","id":"","deviceName":"device2","profileName":"","sourceName":"","origin":0,"readings":null}`
conv := NewConversion()
continuePipeline, result := conv.TransformToJSON(context, eventIn2, eventIn1, "", "")

Expand Down
Loading

0 comments on commit 3ee2f0b

Please sign in to comment.