From 3289943080de72d0a5a8f0456c28a6eecb5e1d47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ida=20=C5=A0tambuk?= Date: Tue, 24 Oct 2023 11:05:25 +0200 Subject: [PATCH] PropertyAlias: Add support for unassociated streams (#231) * Add support for unassociated streams * Prepare 1.12.0 --- CHANGELOG.md | 3 + package.json | 2 +- pkg/framer/property_value_history.go | 8 +- pkg/resource/query_resouce_provider.go | 20 +- .../test/property_value_aggregate_test.go | 126 +- .../test/property_value_history_test.go | 246 +- pkg/server/test/property_value_test.go | 78 +- pkg/sitewise/api/describe_asset.go | 3 +- pkg/sitewise/api/describe_asset_property.go | 5 +- pkg/sitewise/api/list_associated_assets.go | 3 +- pkg/sitewise/api/property_aggregate.go | 5 +- pkg/sitewise/api/property_history.go | 4 +- pkg/sitewise/api/property_interpolated.go | 6 +- pkg/sitewise/api/property_value.go | 5 +- pkg/sitewise/api/util.go | 38 +- ...describe-time-series-without-property.json | 9 + ...-boolean-disassociated-empty-response.json | 9 + ...-history-values-boolean-disassociated.json | 465 +++ ...s-boolean-associated-stream-A.golden.jsonc | 192 + ...n-with-disassociated-stream-A.golden.jsonc | 189 + ...iated-stream-empty-response-A.golden.jsonc | 71 + ...om-alias-disassociated-empty-response.json | 8 + ...story-values-from-alias-disassociated.json | 3259 +++++++++++++++++ ...m-alias-table-disassociated-A.golden.jsonc | 6 + ...isassociated-empty-response-A.golden.jsonc | 6 + ...as-timeseries-disassociated-A.golden.jsonc | 6 + ...isassociated-empty-response-A.golden.jsonc | 6 + .../property-value-disassociated.json | 21 + pkg/util/ids.go | 37 + src/DataSource.ts | 6 +- 30 files changed, 4785 insertions(+), 57 deletions(-) create mode 100644 pkg/testdata/describe-time-series-without-property.json create mode 100644 pkg/testdata/property-history-values-boolean-disassociated-empty-response.json create mode 100644 pkg/testdata/property-history-values-boolean-disassociated.json create mode 100644 pkg/testdata/property-history-values-from-alias-boolean-associated-stream-A.golden.jsonc create mode 100644 pkg/testdata/property-history-values-from-alias-boolean-with-disassociated-stream-A.golden.jsonc create mode 100644 pkg/testdata/property-history-values-from-alias-boolean-with-disassociated-stream-empty-response-A.golden.jsonc create mode 100644 pkg/testdata/property-history-values-from-alias-disassociated-empty-response.json create mode 100644 pkg/testdata/property-history-values-from-alias-disassociated.json create mode 100644 pkg/testdata/property-history-values-from-alias-table-disassociated-A.golden.jsonc create mode 100644 pkg/testdata/property-history-values-from-alias-table-disassociated-empty-response-A.golden.jsonc create mode 100644 pkg/testdata/property-history-values-from-alias-timeseries-disassociated-A.golden.jsonc create mode 100644 pkg/testdata/property-history-values-from-alias-timeseries-disassociated-empty-response-A.golden.jsonc create mode 100644 pkg/testdata/property-value-disassociated.json create mode 100644 pkg/util/ids.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e208fcf..0bb93240 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ All notable changes to this project will be documented in this file. +## v1.12.0 +- Query by property alias: Add support for unassociated streams in [#231](https://github.com/grafana/iot-sitewise-datasource/pull/231) + ## v1.11.1 - Revert "Replace deprecated setVariableQueryEditor with CustomVariableSupport" in [#229](https://github.com/grafana/iot-sitewise-datasource/pull/229) diff --git a/package.json b/package.json index 44d8df05..aa13a803 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "grafana-iot-sitewise-datasource", - "version": "1.11.1", + "version": "1.12.0", "description": "View IoT Sitewise data in grafana", "scripts": { "build": "webpack -c ./.config/webpack/webpack.config.ts --env production", diff --git a/pkg/framer/property_value_history.go b/pkg/framer/property_value_history.go index 277ceacf..650316ec 100644 --- a/pkg/framer/property_value_history.go +++ b/pkg/framer/property_value_history.go @@ -46,12 +46,16 @@ func (p AssetPropertyValueHistory) Frames(ctx context.Context, resources resourc } func (p AssetPropertyValueHistory) Frame(ctx context.Context, property *iotsitewise.DescribeAssetPropertyOutput, h []*iotsitewise.AssetPropertyValue) (*data.Frame, error) { - length := len(h) + // TODO: make this work with the API instead of ad-hoc dataType inference // https://github.com/grafana/iot-sitewise-datasource/issues/98#issuecomment-892947756 if *property.AssetProperty.DataType == *aws.String("?") { - property.AssetProperty.DataType = aws.String(getPropertyVariantValueType(h[0].Value)) + if length != 0 { + property.AssetProperty.DataType = aws.String(getPropertyVariantValueType(h[0].Value)) + } else { + property.AssetProperty.DataType = aws.String("") + } } timeField := fields.TimeField(length) diff --git a/pkg/resource/query_resouce_provider.go b/pkg/resource/query_resouce_provider.go index 1c4a1e47..5756d833 100644 --- a/pkg/resource/query_resouce_provider.go +++ b/pkg/resource/query_resouce_provider.go @@ -5,6 +5,7 @@ import ( "github.com/aws/aws-sdk-go/service/iotsitewise" "github.com/grafana/iot-sitewise-datasource/pkg/models" + "github.com/grafana/iot-sitewise-datasource/pkg/util" ) type queryResourceProvider struct { @@ -56,13 +57,26 @@ func (rp *queryResourceProvider) Property(ctx context.Context) (*iotsitewise.Des func (rp *queryResourceProvider) Properties(ctx context.Context) (map[string]*iotsitewise.DescribeAssetPropertyOutput, error) { properties := map[string]*iotsitewise.DescribeAssetPropertyOutput{} - for _, id := range rp.baseQuery.AssetIds { - prop, err := rp.resources.Property(ctx, id, rp.baseQuery.PropertyId, rp.baseQuery.PropertyAlias) + // if the query for a PropertyAlias doesn't have an assetId or propertyId, it means it's a disassociated stream + // in that case, we call Property() with empty values, which will set AssetProperty.Name to the alias + // and will set the EntryId to the alias (to access values in results) + if len(rp.baseQuery.AssetIds) == 0 && rp.baseQuery.PropertyId == "" && rp.baseQuery.PropertyAlias != "" { + prop, err := rp.resources.Property(ctx, "", "", rp.baseQuery.PropertyAlias) if err != nil { return nil, err } - properties[id] = prop + entryId := util.GetEntryId(rp.baseQuery) + properties[*entryId] = prop + } else { + for _, id := range rp.baseQuery.AssetIds { + prop, err := rp.resources.Property(ctx, id, rp.baseQuery.PropertyId, rp.baseQuery.PropertyAlias) + if err != nil { + return nil, err + } + properties[id] = prop + } } + return properties, nil } diff --git a/pkg/server/test/property_value_aggregate_test.go b/pkg/server/test/property_value_aggregate_test.go index 7cc97514..438f0dd8 100644 --- a/pkg/server/test/property_value_aggregate_test.go +++ b/pkg/server/test/property_value_aggregate_test.go @@ -23,16 +23,16 @@ import ( "github.com/grafana/iot-sitewise-datasource/pkg/sitewise/client/mocks" ) -func TestPropertyValueAggregate(t *testing.T) { - type test struct { - name string - query string - isExpression bool - expectedMaxPages int - expectedMaxResults int - expectedDescribeTimeSeriesWithContextArgs *iotsitewise.DescribeTimeSeriesInput - } +type test struct { + name string + query string + isExpression bool + expectedMaxPages int + expectedMaxResults int + expectedDescribeTimeSeriesWithContextArgs *iotsitewise.DescribeTimeSeriesInput +} +func TestPropertyValueAggregate(t *testing.T) { tests := []test{ { name: "query by asset id and property id", @@ -195,4 +195,112 @@ func TestPropertyValueAggregate(t *testing.T) { } } +func TestPropertyValueAggregateWithDisassociatedStream(t *testing.T) { + tc := test{ + // an disassociated stream will return nil in DescribeTimeSeriesWithContext for assetId and propertyId + name: "query by property alias of an disassociated stream", + query: `{ + "region":"us-west-2", + "propertyAlias":"/amazon/renton/1/rpm", + "aggregates":["SUM"], + "resolution":"1m" + }`, + expectedDescribeTimeSeriesWithContextArgs: &iotsitewise.DescribeTimeSeriesInput{Alias: Pointer("/amazon/renton/1/rpm")}, + expectedMaxPages: 1, + expectedMaxResults: 0, + } + + t.Run(tc.name, func(t *testing.T) { + mockSw := &mocks.SitewiseClient{} + + if tc.expectedDescribeTimeSeriesWithContextArgs != nil { + alias := Pointer("/amazon/renton/1/rpm") + var assetId *string + var propertyId *string + + mockSw.On("DescribeTimeSeriesWithContext", mock.Anything, mock.Anything).Return(&iotsitewise.DescribeTimeSeriesOutput{ + Alias: alias, + AssetId: assetId, + PropertyId: propertyId, + }, nil) + } + mockSw.On( + "BatchGetAssetPropertyAggregatesPageAggregation", + mock.Anything, + mock.MatchedBy(func(input *iotsitewise.BatchGetAssetPropertyAggregatesInput) bool { + entries := *input.Entries[0] + return *entries.EntryId == "_amazon_renton_1_rpm" && + *entries.PropertyAlias == "/amazon/renton/1/rpm" && + *entries.AggregateTypes[0] == "SUM" + + }), + tc.expectedMaxPages, + tc.expectedMaxResults, + ).Return(&iotsitewise.BatchGetAssetPropertyAggregatesOutput{ + NextToken: Pointer("some-next-token"), + SuccessEntries: []*iotsitewise.BatchGetAssetPropertyAggregatesSuccessEntry{{ + AggregatedValues: []*iotsitewise.AggregatedValue{{ + Timestamp: Pointer(time.Date(2021, 2, 1, 16, 27, 0, 0, time.UTC)), + Value: &iotsitewise.Aggregates{Sum: Pointer(1688.6)}, + }}, + EntryId: aws.String("_amazon_renton_1_rpm"), + }}, + }, nil) + + srvr := &server.Server{Datasource: mockedDatasource(mockSw).(*sitewise.Datasource)} + + sitewise.GetCache = func() *cache.Cache { + return cache.New(cache.DefaultExpiration, cache.NoExpiration) + } + + query := &backend.QueryDataRequest{ + PluginContext: backend.PluginContext{}, + Queries: []backend.DataQuery{ + { + RefID: "A", + QueryType: models.QueryTypePropertyAggregate, + TimeRange: timeRange, + JSON: []byte(tc.query), + }, + }, + } + + if tc.isExpression { + query.Headers = map[string]string{"http_X-Grafana-From-Expr": "true"} + } + + qdr, err := srvr.HandlePropertyAggregate(context.Background(), query) + require.Nil(t, err) + _, ok := qdr.Responses["A"] + require.True(t, ok) + require.NotNil(t, qdr.Responses["A"].Frames[0]) + + expectedFrame := data.NewFrame("/amazon/renton/1/rpm", + data.NewField("time", nil, []time.Time{time.Date(2021, 2, 1, 16, 27, 0, 0, time.UTC)}), + data.NewField("sum", nil, []float64{1688.6}), + ).SetMeta(&data.FrameMeta{ + Custom: models.SitewiseCustomMeta{ + NextToken: "some-next-token", + Resolution: "1m", + Aggregates: []string{models.AggregateSum}, + }, + }) + if diff := cmp.Diff(expectedFrame, qdr.Responses["A"].Frames[0], data.FrameTestCompareOptions()...); diff != "" { + t.Errorf("Result mismatch (-want +got):\n%s", diff) + } + + mockSw.AssertExpectations(t) + if tc.expectedDescribeTimeSeriesWithContextArgs != nil { + mockSw.AssertCalled(t, + "DescribeTimeSeriesWithContext", + mock.Anything, + tc.expectedDescribeTimeSeriesWithContextArgs, + ) + } + mockSw.AssertNotCalled(t, "DescribeAssetPropertyWithContext", mock.Anything, mock.Anything) + + }) + +} + func Pointer[T any](v T) *T { return &v } diff --git a/pkg/server/test/property_value_history_test.go b/pkg/server/test/property_value_history_test.go index c8c32617..92d88625 100644 --- a/pkg/server/test/property_value_history_test.go +++ b/pkg/server/test/property_value_history_test.go @@ -297,6 +297,87 @@ func Test_getPropertyValueHistoryFromAliasCaseTable(t *testing.T) { } } +func Test_getPropertyValueHistoryFromAliasCaseTable_disassociated_stream(t *testing.T) { + propVals := testdata.GetIoTSitewisePropHistoryVals(t, testDataRelativePath("property-history-values-from-alias-disassociated.json")) + propTimeSeries := testdata.GetIoTSitewiseTimeSeries(t, testDataRelativePath("describe-time-series-without-property.json")) + mockSw := &mocks.SitewiseClient{} + mockSw.On("BatchGetAssetPropertyValueHistoryPageAggregation", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&propVals, nil) + mockSw.On("DescribeTimeSeriesWithContext", mock.Anything, mock.Anything).Return(&propTimeSeries, nil) + + srvr := &server.Server{ + Datasource: mockedDatasource(mockSw).(*sitewise.Datasource), + } + + sitewise.GetCache = func() *cache.Cache { + return cache.New(cache.DefaultExpiration, cache.NoExpiration) + } + + qdr, err := srvr.HandlePropertyValueHistory(context.Background(), &backend.QueryDataRequest{ + PluginContext: backend.PluginContext{}, + Queries: []backend.DataQuery{ + { + QueryType: models.QueryTypePropertyValueHistory, + RefID: "A", + MaxDataPoints: 100, + Interval: 1000, + TimeRange: timeRange, + JSON: testdata.SerializeStruct(t, models.AssetPropertyValueQuery{ + BaseQuery: models.BaseQuery{ + AwsRegion: testdata.AwsRegion, + PropertyAlias: testdata.TurbinePropWindSpeedAlias, + }, + }), + }, + }, + }) + require.Nil(t, err) + + for i, dr := range qdr.Responses { + fname := fmt.Sprintf("%s-%s.golden", "property-history-values-from-alias-table-disassociated", i) + experimental.CheckGoldenJSONResponse(t, "../../testdata", fname, &dr, true) + } +} +func Test_getPropertyValueHistoryFromAliasCaseTable_disassociated_stream_empty_response(t *testing.T) { + propVals := testdata.GetIoTSitewisePropHistoryVals(t, testDataRelativePath("property-history-values-from-alias-disassociated-empty-response.json")) + propTimeSeries := testdata.GetIoTSitewiseTimeSeries(t, testDataRelativePath("describe-time-series-without-property.json")) + mockSw := &mocks.SitewiseClient{} + mockSw.On("BatchGetAssetPropertyValueHistoryPageAggregation", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&propVals, nil) + mockSw.On("DescribeTimeSeriesWithContext", mock.Anything, mock.Anything).Return(&propTimeSeries, nil) + + srvr := &server.Server{ + Datasource: mockedDatasource(mockSw).(*sitewise.Datasource), + } + + sitewise.GetCache = func() *cache.Cache { + return cache.New(cache.DefaultExpiration, cache.NoExpiration) + } + + qdr, err := srvr.HandlePropertyValueHistory(context.Background(), &backend.QueryDataRequest{ + PluginContext: backend.PluginContext{}, + Queries: []backend.DataQuery{ + { + QueryType: models.QueryTypePropertyValueHistory, + RefID: "A", + MaxDataPoints: 100, + Interval: 1000, + TimeRange: timeRange, + JSON: testdata.SerializeStruct(t, models.AssetPropertyValueQuery{ + BaseQuery: models.BaseQuery{ + AwsRegion: testdata.AwsRegion, + PropertyAlias: testdata.TurbinePropWindSpeedAlias, + }, + }), + }, + }, + }) + require.Nil(t, err) + + for i, dr := range qdr.Responses { + fname := fmt.Sprintf("%s-%s.golden", "property-history-values-from-alias-table-disassociated-empty-response", i) + experimental.CheckGoldenJSONResponse(t, "../../testdata", fname, &dr, true) + } +} + func Test_getPropertyValueHistoryFromAliasCaseTimeSeries(t *testing.T) { propVals := testdata.GetIoTSitewisePropHistoryVals(t, testDataRelativePath("property-history-values.json")) propDesc := testdata.GetIotSitewiseAssetProp(t, testDataRelativePath("describe-asset-property-avg-wind.json")) @@ -340,7 +421,88 @@ func Test_getPropertyValueHistoryFromAliasCaseTimeSeries(t *testing.T) { experimental.CheckGoldenJSONResponse(t, "../../testdata", fname, &dr, true) } } +func Test_getPropertyValueHistoryFromAliasCaseTimeSeries_disassociated_stream(t *testing.T) { + propVals := testdata.GetIoTSitewisePropHistoryVals(t, testDataRelativePath("property-history-values-from-alias-disassociated.json")) + propTimeSeries := testdata.GetIoTSitewiseTimeSeries(t, testDataRelativePath("describe-time-series-without-property.json")) + mockSw := &mocks.SitewiseClient{} + mockSw.On("BatchGetAssetPropertyValueHistoryPageAggregation", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&propVals, nil) + mockSw.On("DescribeTimeSeriesWithContext", mock.Anything, mock.Anything).Return(&propTimeSeries, nil) + + srvr := &server.Server{ + Datasource: mockedDatasource(mockSw).(*sitewise.Datasource), + } + + sitewise.GetCache = func() *cache.Cache { + return cache.New(cache.DefaultExpiration, cache.NoExpiration) + } + + qdr, err := srvr.HandlePropertyValueHistory(context.Background(), &backend.QueryDataRequest{ + PluginContext: backend.PluginContext{}, + Queries: []backend.DataQuery{ + { + QueryType: models.QueryTypePropertyValueHistory, + RefID: "A", + MaxDataPoints: 100, + Interval: 1000, + TimeRange: timeRange, + JSON: testdata.SerializeStruct(t, models.AssetPropertyValueQuery{ + BaseQuery: models.BaseQuery{ + ResponseFormat: "timeseries", + AwsRegion: testdata.AwsRegion, + PropertyAlias: testdata.TurbinePropWindSpeedAlias, + }, + }), + }, + }, + }) + require.Nil(t, err) + + for i, dr := range qdr.Responses { + fname := fmt.Sprintf("%s-%s.golden", "property-history-values-from-alias-timeseries-disassociated", i) + experimental.CheckGoldenJSONResponse(t, "../../testdata", fname, &dr, true) + } +} +func Test_getPropertyValueHistoryFromAliasCaseTimeSeries_disassociated_stream_with_empty_response(t *testing.T) { + propVals := testdata.GetIoTSitewisePropHistoryVals(t, testDataRelativePath("property-history-values-from-alias-disassociated-empty-response.json")) + propTimeSeries := testdata.GetIoTSitewiseTimeSeries(t, testDataRelativePath("describe-time-series-without-property.json")) + mockSw := &mocks.SitewiseClient{} + mockSw.On("BatchGetAssetPropertyValueHistoryPageAggregation", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&propVals, nil) + mockSw.On("DescribeTimeSeriesWithContext", mock.Anything, mock.Anything).Return(&propTimeSeries, nil) + + srvr := &server.Server{ + Datasource: mockedDatasource(mockSw).(*sitewise.Datasource), + } + sitewise.GetCache = func() *cache.Cache { + return cache.New(cache.DefaultExpiration, cache.NoExpiration) + } + + qdr, err := srvr.HandlePropertyValueHistory(context.Background(), &backend.QueryDataRequest{ + PluginContext: backend.PluginContext{}, + Queries: []backend.DataQuery{ + { + QueryType: models.QueryTypePropertyValueHistory, + RefID: "A", + MaxDataPoints: 100, + Interval: 1000, + TimeRange: timeRange, + JSON: testdata.SerializeStruct(t, models.AssetPropertyValueQuery{ + BaseQuery: models.BaseQuery{ + ResponseFormat: "timeseries", + AwsRegion: testdata.AwsRegion, + PropertyAlias: testdata.TurbinePropWindSpeedAlias, + }, + }), + }, + }, + }) + require.Nil(t, err) + + for i, dr := range qdr.Responses { + fname := fmt.Sprintf("%s-%s.golden", "property-history-values-from-alias-timeseries-disassociated-empty-response", i) + experimental.CheckGoldenJSONResponse(t, "../../testdata", fname, &dr, true) + } +} func Test_getPropertyValueBooleanFromAlias(t *testing.T) { propVals := testdata.GetIoTSitewisePropHistoryVals(t, testDataRelativePath("property-history-values-boolean.json")) propDesc := testdata.GetIotSitewiseAssetProp(t, testDataRelativePath("describe-asset-property-is-windy.json")) @@ -379,7 +541,89 @@ func Test_getPropertyValueBooleanFromAlias(t *testing.T) { require.Nil(t, err) for i, dr := range qdr.Responses { - fname := fmt.Sprintf("%s-%s.golden", "property-history-values-from-alias-boolean", i) + fname := fmt.Sprintf("%s-%s.golden", "property-history-values-from-alias-boolean-associated-stream", i) + experimental.CheckGoldenJSONResponse(t, "../../testdata", fname, &dr, true) + } +} + +func Test_getPropertyValueBooleanFromAliasWithDisassociatedStream(t *testing.T) { + propVals := testdata.GetIoTSitewisePropHistoryVals(t, testDataRelativePath("property-history-values-boolean-disassociated.json")) + propTimeSeriesWithoutPropertyId := testdata.GetIoTSitewiseTimeSeries(t, testDataRelativePath("describe-time-series-without-property.json")) + mockSw := &mocks.SitewiseClient{} + mockSw.On("BatchGetAssetPropertyValueHistoryPageAggregation", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&propVals, nil) + mockSw.On("DescribeTimeSeriesWithContext", mock.Anything, mock.Anything).Return(&propTimeSeriesWithoutPropertyId, nil) + + srvr := &server.Server{ + Datasource: mockedDatasource(mockSw).(*sitewise.Datasource), + } + + sitewise.GetCache = func() *cache.Cache { + return cache.New(cache.DefaultExpiration, cache.NoExpiration) + } + + qdr, err := srvr.HandlePropertyValueHistory(context.Background(), &backend.QueryDataRequest{ + PluginContext: backend.PluginContext{}, + Queries: []backend.DataQuery{ + { + QueryType: models.QueryTypePropertyValueHistory, + RefID: "A", + MaxDataPoints: 100, + Interval: 1000, + TimeRange: timeRange, + JSON: testdata.SerializeStruct(t, models.AssetPropertyValueQuery{ + BaseQuery: models.BaseQuery{ + AwsRegion: testdata.AwsRegion, + PropertyAlias: testdata.TurbinePropWindSpeedAlias, + }, + }), + }, + }, + }) + require.Nil(t, err) + + for i, dr := range qdr.Responses { + fname := fmt.Sprintf("%s-%s.golden", "property-history-values-from-alias-boolean-with-disassociated-stream", i) + experimental.CheckGoldenJSONResponse(t, "../../testdata", fname, &dr, true) + } +} + +func Test_getPropertyValueBooleanFromAlias_disassociated_stream_with_empty_response(t *testing.T) { + propVals := testdata.GetIoTSitewisePropHistoryVals(t, testDataRelativePath("property-history-values-boolean-disassociated-empty-response.json")) + propTimeSeriesWithoutPropertyId := testdata.GetIoTSitewiseTimeSeries(t, testDataRelativePath("describe-time-series-without-property.json")) + mockSw := &mocks.SitewiseClient{} + mockSw.On("BatchGetAssetPropertyValueHistoryPageAggregation", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&propVals, nil) + mockSw.On("DescribeTimeSeriesWithContext", mock.Anything, mock.Anything).Return(&propTimeSeriesWithoutPropertyId, nil) + + srvr := &server.Server{ + Datasource: mockedDatasource(mockSw).(*sitewise.Datasource), + } + + sitewise.GetCache = func() *cache.Cache { + return cache.New(cache.DefaultExpiration, cache.NoExpiration) + } + + qdr, err := srvr.HandlePropertyValueHistory(context.Background(), &backend.QueryDataRequest{ + PluginContext: backend.PluginContext{}, + Queries: []backend.DataQuery{ + { + QueryType: models.QueryTypePropertyValueHistory, + RefID: "A", + MaxDataPoints: 100, + Interval: 1000, + TimeRange: timeRange, + JSON: testdata.SerializeStruct(t, models.AssetPropertyValueQuery{ + BaseQuery: models.BaseQuery{ + AwsRegion: testdata.AwsRegion, + PropertyAlias: testdata.TurbinePropWindSpeedAlias, + }, + }), + }, + }, + }) + require.Nil(t, err) + + for i, dr := range qdr.Responses { + fname := fmt.Sprintf("%s-%s.golden", "property-history-values-from-alias-boolean-with-disassociated-stream-empty-response", i) experimental.CheckGoldenJSONResponse(t, "../../testdata", fname, &dr, true) } } diff --git a/pkg/server/test/property_value_test.go b/pkg/server/test/property_value_test.go index 5bcb16b0..28a30add 100644 --- a/pkg/server/test/property_value_test.go +++ b/pkg/server/test/property_value_test.go @@ -104,7 +104,7 @@ func Test_property_value_query_by_asset_id_and_property_id(t *testing.T) { ) } -func Test_property_value_query_by_alias(t *testing.T) { +func Test_property_value_query_by_alias_associated_stream(t *testing.T) { mockSw := &mocks.SitewiseClient{} mockSw.On("DescribeTimeSeriesWithContext", mock.Anything, mock.Anything).Return(&iotsitewise.DescribeTimeSeriesOutput{ Alias: Pointer("/amazon/renton/1/rpm"), @@ -194,7 +194,83 @@ func Test_property_value_query_by_alias(t *testing.T) { }, ) } +func Test_property_value_query_by_alias_disassociated_stream(t *testing.T) { + mockSw := &mocks.SitewiseClient{} + mockSw.On("DescribeTimeSeriesWithContext", mock.Anything, mock.Anything).Return(&iotsitewise.DescribeTimeSeriesOutput{ + Alias: Pointer("/amazon/renton/1/rpm"), + }, nil) + mockSw.On("BatchGetAssetPropertyValueWithContext", mock.Anything, mock.Anything).Return(&iotsitewise.BatchGetAssetPropertyValueOutput{ + SuccessEntries: []*iotsitewise.BatchGetAssetPropertyValueSuccessEntry{{ + AssetPropertyValue: &iotsitewise.AssetPropertyValue{ + Quality: Pointer("GOOD"), + Timestamp: &iotsitewise.TimeInNanos{ + OffsetInNanos: Pointer(int64(0)), + TimeInSeconds: Pointer(int64(1612207200)), + }, + Value: &iotsitewise.Variant{ + DoubleValue: Pointer(float64(23.8)), + }, + }, + EntryId: Pointer("_amazon_renton_1_rpm"), + }}}, nil) + + srvr := &server.Server{Datasource: mockedDatasource(mockSw).(*sitewise.Datasource)} + sitewise.GetCache = func() *cache.Cache { + return cache.New(cache.DefaultExpiration, cache.NoExpiration) + } + + qdr, err := srvr.HandlePropertyValue(context.Background(), &backend.QueryDataRequest{ + PluginContext: backend.PluginContext{}, + Queries: []backend.DataQuery{ + { + RefID: "A", + QueryType: models.QueryTypePropertyValue, + TimeRange: timeRange, + JSON: []byte( + `{ + "region":"us-west-2", + "propertyAlias":"/amazon/renton/1/rpm" + }`), + }, + }, + }) + require.Nil(t, err) + _, ok := qdr.Responses["A"] + require.True(t, ok) + require.NotNil(t, qdr.Responses["A"].Frames[0]) + + expectedFrame := data.NewFrame("", + data.NewField("time", nil, []time.Time{time.Date(2021, 2, 1, 19, 20, 0, 0, time.UTC)}), + data.NewField("/amazon/renton/1/rpm", nil, []float64{23.8}).SetConfig(&data.FieldConfig{Unit: ""}), + data.NewField("quality", nil, []string{"GOOD"}), + ) + if diff := cmp.Diff(expectedFrame, qdr.Responses["A"].Frames[0], data.FrameTestCompareOptions()...); diff != "" { + t.Errorf("Result mismatch (-want +got):\n%s", diff) + } + + mockSw.AssertExpectations(t) + mockSw.AssertCalled(t, + "DescribeTimeSeriesWithContext", + mock.Anything, + &iotsitewise.DescribeTimeSeriesInput{Alias: Pointer("/amazon/renton/1/rpm")}, + ) + mockSw.AssertCalled(t, + "BatchGetAssetPropertyValueWithContext", + mock.Anything, + &iotsitewise.BatchGetAssetPropertyValueInput{ + Entries: []*iotsitewise.BatchGetAssetPropertyValueEntry{{ + EntryId: Pointer("_amazon_renton_1_rpm"), + PropertyAlias: Pointer("/amazon/renton/1/rpm"), + }}, + }, + ) + mockSw.AssertNotCalled(t, + "DescribeAssetPropertyWithContext", + mock.Anything, + mock.Anything, + ) +} func Test_property_value_query_with_empty_property_value_results(t *testing.T) { mockSw := &mocks.SitewiseClient{} mockSw.On("BatchGetAssetPropertyValueWithContext", mock.Anything, mock.Anything).Return(&iotsitewise.BatchGetAssetPropertyValueOutput{ diff --git a/pkg/sitewise/api/describe_asset.go b/pkg/sitewise/api/describe_asset.go index d8050347..446537f3 100644 --- a/pkg/sitewise/api/describe_asset.go +++ b/pkg/sitewise/api/describe_asset.go @@ -4,6 +4,7 @@ import ( "context" "github.com/grafana/iot-sitewise-datasource/pkg/framer" + "github.com/grafana/iot-sitewise-datasource/pkg/util" "github.com/grafana/iot-sitewise-datasource/pkg/sitewise/client" @@ -12,7 +13,7 @@ import ( ) func DescribeAsset(ctx context.Context, client client.SitewiseClient, query models.DescribeAssetQuery) (*framer.AssetDescription, error) { - awsReq := &iotsitewise.DescribeAssetInput{AssetId: getAssetId(query.BaseQuery)} + awsReq := &iotsitewise.DescribeAssetInput{AssetId: util.GetAssetId(query.BaseQuery)} resp, err := client.DescribeAssetWithContext(ctx, awsReq) diff --git a/pkg/sitewise/api/describe_asset_property.go b/pkg/sitewise/api/describe_asset_property.go index 60b15b6f..a9303ff3 100644 --- a/pkg/sitewise/api/describe_asset_property.go +++ b/pkg/sitewise/api/describe_asset_property.go @@ -4,6 +4,7 @@ import ( "context" "github.com/grafana/iot-sitewise-datasource/pkg/framer" + "github.com/grafana/iot-sitewise-datasource/pkg/util" "github.com/aws/aws-sdk-go/service/iotsitewise" "github.com/grafana/iot-sitewise-datasource/pkg/models" @@ -13,8 +14,8 @@ import ( func GetAssetPropertyDescription(ctx context.Context, client client.SitewiseClient, query models.DescribeAssetPropertyQuery) (*framer.AssetProperty, error) { awsReq := &iotsitewise.DescribeAssetPropertyInput{ - AssetId: getAssetId(query.BaseQuery), - PropertyId: getPropertyId(query.BaseQuery), + AssetId: util.GetAssetId(query.BaseQuery), + PropertyId: util.GetPropertyId(query.BaseQuery), } resp, err := client.DescribeAssetPropertyWithContext(ctx, awsReq) diff --git a/pkg/sitewise/api/list_associated_assets.go b/pkg/sitewise/api/list_associated_assets.go index 0ceaf3b6..3791e669 100644 --- a/pkg/sitewise/api/list_associated_assets.go +++ b/pkg/sitewise/api/list_associated_assets.go @@ -9,6 +9,7 @@ import ( "github.com/grafana/iot-sitewise-datasource/pkg/framer" "github.com/grafana/iot-sitewise-datasource/pkg/models" "github.com/grafana/iot-sitewise-datasource/pkg/sitewise/client" + "github.com/grafana/iot-sitewise-datasource/pkg/util" ) func ListAssociatedAssets(ctx context.Context, client client.SitewiseClient, query models.ListAssociatedAssetsQuery) (*framer.AssociatedAssets, error) { @@ -26,7 +27,7 @@ func ListAssociatedAssets(ctx context.Context, client client.SitewiseClient, que } resp, err := client.ListAssociatedAssetsWithContext(ctx, &iotsitewise.ListAssociatedAssetsInput{ - AssetId: getAssetId(query.BaseQuery), + AssetId: util.GetAssetId(query.BaseQuery), HierarchyId: hierarchyId, MaxResults: MaxSitewiseResults, NextToken: getNextToken(query.BaseQuery), diff --git a/pkg/sitewise/api/property_aggregate.go b/pkg/sitewise/api/property_aggregate.go index 4433af4c..e6aadb72 100644 --- a/pkg/sitewise/api/property_aggregate.go +++ b/pkg/sitewise/api/property_aggregate.go @@ -48,12 +48,11 @@ func aggregateQueryToInput(query models.AssetPropertyValueQuery) *iotsitewise.Ba switch { case query.PropertyAlias != "": - id := getAssetId(query.BaseQuery) entries = append(entries, &iotsitewise.BatchGetAssetPropertyAggregatesEntry{ AggregateTypes: aggregateTypes, EndDate: to, - EntryId: id, - PropertyAlias: getPropertyAlias(query.BaseQuery), + EntryId: util.GetEntryId(query.BaseQuery), + PropertyAlias: util.GetPropertyAlias(query.BaseQuery), Qualities: qualities, Resolution: aws.String(resolution), StartDate: from, diff --git a/pkg/sitewise/api/property_history.go b/pkg/sitewise/api/property_history.go index 5309352c..879e7bfb 100644 --- a/pkg/sitewise/api/property_history.go +++ b/pkg/sitewise/api/property_history.go @@ -38,8 +38,8 @@ func historyQueryToInput(query models.AssetPropertyValueQuery) *iotsitewise.Batc entries = append(entries, &iotsitewise.BatchGetAssetPropertyValueHistoryEntry{ StartDate: from, EndDate: to, - EntryId: getAssetId(query.BaseQuery), - PropertyAlias: getPropertyAlias(query.BaseQuery), + EntryId: util.GetEntryId(query.BaseQuery), + PropertyAlias: util.GetPropertyAlias(query.BaseQuery), TimeOrdering: aws.String(query.TimeOrdering), Qualities: qualities, }) diff --git a/pkg/sitewise/api/property_interpolated.go b/pkg/sitewise/api/property_interpolated.go index b045c4b3..f47d7a35 100644 --- a/pkg/sitewise/api/property_interpolated.go +++ b/pkg/sitewise/api/property_interpolated.go @@ -56,9 +56,9 @@ func interpolatedQueryToInput(query models.AssetPropertyValueQuery) *iotsitewise IntervalInSeconds: aws.Int64(intervalInSeconds), MaxResults: aws.Int64(10), NextToken: getNextToken(query.BaseQuery), - AssetId: getAssetId(query.BaseQuery), - PropertyId: getPropertyId(query.BaseQuery), - PropertyAlias: getPropertyAlias(query.BaseQuery), + AssetId: util.GetAssetId(query.BaseQuery), + PropertyId: util.GetPropertyId(query.BaseQuery), + PropertyAlias: util.GetPropertyAlias(query.BaseQuery), Quality: &quality, Type: &interpolationType, } diff --git a/pkg/sitewise/api/property_value.go b/pkg/sitewise/api/property_value.go index a512c449..fe1702b2 100644 --- a/pkg/sitewise/api/property_value.go +++ b/pkg/sitewise/api/property_value.go @@ -4,6 +4,7 @@ import ( "context" "github.com/grafana/iot-sitewise-datasource/pkg/framer" + "github.com/grafana/iot-sitewise-datasource/pkg/util" "github.com/grafana/iot-sitewise-datasource/pkg/sitewise/client" @@ -18,8 +19,8 @@ func valueQueryToInput(query models.AssetPropertyValueQuery) *iotsitewise.BatchG switch { case query.PropertyAlias != "": entries = append(entries, &iotsitewise.BatchGetAssetPropertyValueEntry{ - EntryId: getAssetId(query.BaseQuery), - PropertyAlias: getPropertyAlias(query.BaseQuery), + EntryId: util.GetEntryId(query.BaseQuery), + PropertyAlias: util.GetPropertyAlias(query.BaseQuery), }) default: for _, assetId := range query.AssetIds { diff --git a/pkg/sitewise/api/util.go b/pkg/sitewise/api/util.go index 5f06c223..7952e5ea 100644 --- a/pkg/sitewise/api/util.go +++ b/pkg/sitewise/api/util.go @@ -7,6 +7,7 @@ import ( "github.com/aws/aws-sdk-go/service/iotsitewise" "github.com/grafana/iot-sitewise-datasource/pkg/models" "github.com/grafana/iot-sitewise-datasource/pkg/sitewise/client" + "github.com/grafana/iot-sitewise-datasource/pkg/util" ) var ( @@ -20,38 +21,27 @@ func getNextToken(query models.BaseQuery) *string { return aws.String(query.NextToken) } -func getAssetId(query models.BaseQuery) *string { - if len(query.AssetIds) == 0 { - return nil - } - return aws.String(query.AssetIds[0]) -} - -func getPropertyId(query models.BaseQuery) *string { - if query.PropertyId == "" { - return nil - } - return aws.String(query.PropertyId) -} - -func getPropertyAlias(query models.BaseQuery) *string { - if query.PropertyAlias == "" { - return nil - } - return aws.String(query.PropertyAlias) -} - func getAssetIdAndPropertyId(query models.AssetPropertyValueQuery, client client.SitewiseClient, ctx context.Context) (models.AssetPropertyValueQuery, error) { result := query if query.PropertyAlias != "" { resp, err := client.DescribeTimeSeriesWithContext(ctx, &iotsitewise.DescribeTimeSeriesInput{ - Alias: getPropertyAlias(query.BaseQuery), + Alias: util.GetPropertyAlias(query.BaseQuery), }) if err != nil { return models.AssetPropertyValueQuery{}, err } - result.AssetIds = []string{*resp.AssetId} - result.PropertyId = *resp.PropertyId + if resp.AssetId != nil { + result.AssetIds = []string{*resp.AssetId} + } else { + // For disassociated streams with a propertyAlias + result.AssetIds = []string{} + } + if resp.PropertyId != nil { + result.PropertyId = *resp.PropertyId + } else { + // For disassociated streams without a propertyAlias + result.PropertyId = "" + } } return result, nil } diff --git a/pkg/testdata/describe-time-series-without-property.json b/pkg/testdata/describe-time-series-without-property.json new file mode 100644 index 00000000..4c8c2095 --- /dev/null +++ b/pkg/testdata/describe-time-series-without-property.json @@ -0,0 +1,9 @@ +{ + "alias": "/amazon/renton/1/rpm", + "timeSeriesId": "32c483a3-6091-42fd-a2e2-dbf6caef45be", + "dataType": "DOUBLE", + "timeSeriesCreationDate": "2023-02-09T07:37:50-08:00", + "timeSeriesLastUpdateDate": "2023-03-09T11:42:16-08:00", + "timeSeriesArn": "arn:aws:iotsitewise:us-east-2:569069006612:time-series/32c483a3-6091-42fd-a2e2-dbf6caef45be" + } + \ No newline at end of file diff --git a/pkg/testdata/property-history-values-boolean-disassociated-empty-response.json b/pkg/testdata/property-history-values-boolean-disassociated-empty-response.json new file mode 100644 index 00000000..c6389169 --- /dev/null +++ b/pkg/testdata/property-history-values-boolean-disassociated-empty-response.json @@ -0,0 +1,9 @@ +{ + "SuccessEntries": [ + { + "AssetPropertyValueHistory": [], + "EntryId": "_amazon_renton_1_rpm" + } + ], + "NextToken": null +} diff --git a/pkg/testdata/property-history-values-boolean-disassociated.json b/pkg/testdata/property-history-values-boolean-disassociated.json new file mode 100644 index 00000000..832975de --- /dev/null +++ b/pkg/testdata/property-history-values-boolean-disassociated.json @@ -0,0 +1,465 @@ +{ + "SuccessEntries": [ + { + "AssetPropertyValueHistory": [ + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1612197000 + }, + "Value": { + "BooleanValue": true, + "DoubleValue": null, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1612197300 + }, + "Value": { + "BooleanValue": true, + "DoubleValue": null, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1612197600 + }, + "Value": { + "BooleanValue": false, + "DoubleValue": null, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1612197900 + }, + "Value": { + "BooleanValue": false, + "DoubleValue": null, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1612198200 + }, + "Value": { + "BooleanValue": true, + "DoubleValue": null, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1612198500 + }, + "Value": { + "BooleanValue": true, + "DoubleValue": null, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1612198800 + }, + "Value": { + "BooleanValue": false, + "DoubleValue": null, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1612199100 + }, + "Value": { + "BooleanValue": false, + "DoubleValue": null, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1612199400 + }, + "Value": { + "BooleanValue": true, + "DoubleValue": null, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1612199700 + }, + "Value": { + "BooleanValue": true, + "DoubleValue": null, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1612200000 + }, + "Value": { + "BooleanValue": false, + "DoubleValue": null, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1612200300 + }, + "Value": { + "BooleanValue": false, + "DoubleValue": null, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1612200600 + }, + "Value": { + "BooleanValue": true, + "DoubleValue": null, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1612200900 + }, + "Value": { + "BooleanValue": true, + "DoubleValue": null, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1612201200 + }, + "Value": { + "BooleanValue": false, + "DoubleValue": null, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1612201500 + }, + "Value": { + "BooleanValue": false, + "DoubleValue": null, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1612201800 + }, + "Value": { + "BooleanValue": true, + "DoubleValue": null, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1612202100 + }, + "Value": { + "BooleanValue": true, + "DoubleValue": null, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1612202400 + }, + "Value": { + "BooleanValue": false, + "DoubleValue": null, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1612202700 + }, + "Value": { + "BooleanValue": false, + "DoubleValue": null, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1612203000 + }, + "Value": { + "BooleanValue": true, + "DoubleValue": null, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1612203300 + }, + "Value": { + "BooleanValue": true, + "DoubleValue": null, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1612203600 + }, + "Value": { + "BooleanValue": false, + "DoubleValue": null, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1612203900 + }, + "Value": { + "BooleanValue": false, + "DoubleValue": null, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1612204200 + }, + "Value": { + "BooleanValue": true, + "DoubleValue": null, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1612204500 + }, + "Value": { + "BooleanValue": true, + "DoubleValue": null, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1612204800 + }, + "Value": { + "BooleanValue": false, + "DoubleValue": null, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1612205100 + }, + "Value": { + "BooleanValue": false, + "DoubleValue": null, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1612205400 + }, + "Value": { + "BooleanValue": true, + "DoubleValue": null, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1612205700 + }, + "Value": { + "BooleanValue": true, + "DoubleValue": null, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1612206000 + }, + "Value": { + "BooleanValue": false, + "DoubleValue": null, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1612206300 + }, + "Value": { + "BooleanValue": false, + "DoubleValue": null, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1612206600 + }, + "Value": { + "BooleanValue": true, + "DoubleValue": null, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1612206900 + }, + "Value": { + "BooleanValue": true, + "DoubleValue": null, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1612207200 + }, + "Value": { + "BooleanValue": false, + "DoubleValue": null, + "IntegerValue": null, + "StringValue": null + } + } + ], + "EntryId": "_amazon_renton_1_rpm" + } + ], + "NextToken": null +} diff --git a/pkg/testdata/property-history-values-from-alias-boolean-associated-stream-A.golden.jsonc b/pkg/testdata/property-history-values-from-alias-boolean-associated-stream-A.golden.jsonc new file mode 100644 index 00000000..bdffe223 --- /dev/null +++ b/pkg/testdata/property-history-values-from-alias-boolean-associated-stream-A.golden.jsonc @@ -0,0 +1,192 @@ +// 🌟 This was machine generated. Do not edit. 🌟 +// +// Frame[0] { +// "typeVersion": [ +// 0, +// 0 +// ], +// "custom": { +// "resolution": "RAW" +// } +// } +// Name: Demo Turbine Asset 1 +// Dimensions: 3 Fields by 35 Rows +// +-------------------------------+----------------+----------------+ +// | Name: time | Name: Is Windy | Name: quality | +// | Labels: | Labels: | Labels: | +// | Type: []time.Time | Type: []bool | Type: []string | +// +-------------------------------+----------------+----------------+ +// | 2021-02-01 17:30:00 +0100 CET | true | GOOD | +// | 2021-02-01 17:35:00 +0100 CET | true | GOOD | +// | 2021-02-01 17:40:00 +0100 CET | false | GOOD | +// | 2021-02-01 17:45:00 +0100 CET | false | GOOD | +// | 2021-02-01 17:50:00 +0100 CET | true | GOOD | +// | 2021-02-01 17:55:00 +0100 CET | true | GOOD | +// | 2021-02-01 18:00:00 +0100 CET | false | GOOD | +// | 2021-02-01 18:05:00 +0100 CET | false | GOOD | +// | 2021-02-01 18:10:00 +0100 CET | true | GOOD | +// | ... | ... | ... | +// +-------------------------------+----------------+----------------+ +// +// +// 🌟 This was machine generated. Do not edit. 🌟 +{ + "status": 200, + "frames": [ + { + "schema": { + "name": "Demo Turbine Asset 1", + "meta": { + "typeVersion": [ + 0, + 0 + ], + "custom": { + "resolution": "RAW" + } + }, + "fields": [ + { + "name": "time", + "type": "time", + "typeInfo": { + "frame": "time.Time" + } + }, + { + "name": "Is Windy", + "type": "boolean", + "typeInfo": { + "frame": "bool" + }, + "config": { + "unit": "none" + } + }, + { + "name": "quality", + "type": "string", + "typeInfo": { + "frame": "string" + } + } + ] + }, + "data": { + "values": [ + [ + 1612197000000, + 1612197300000, + 1612197600000, + 1612197900000, + 1612198200000, + 1612198500000, + 1612198800000, + 1612199100000, + 1612199400000, + 1612199700000, + 1612200000000, + 1612200300000, + 1612200600000, + 1612200900000, + 1612201200000, + 1612201500000, + 1612201800000, + 1612202100000, + 1612202400000, + 1612202700000, + 1612203000000, + 1612203300000, + 1612203600000, + 1612203900000, + 1612204200000, + 1612204500000, + 1612204800000, + 1612205100000, + 1612205400000, + 1612205700000, + 1612206000000, + 1612206300000, + 1612206600000, + 1612206900000, + 1612207200000 + ], + [ + true, + true, + false, + false, + true, + true, + false, + false, + true, + true, + false, + false, + true, + true, + false, + false, + true, + true, + false, + false, + true, + true, + false, + false, + true, + true, + false, + false, + true, + true, + false, + false, + true, + true, + false + ], + [ + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD" + ] + ] + } + } + ] +} \ No newline at end of file diff --git a/pkg/testdata/property-history-values-from-alias-boolean-with-disassociated-stream-A.golden.jsonc b/pkg/testdata/property-history-values-from-alias-boolean-with-disassociated-stream-A.golden.jsonc new file mode 100644 index 00000000..98a42f318 --- /dev/null +++ b/pkg/testdata/property-history-values-from-alias-boolean-with-disassociated-stream-A.golden.jsonc @@ -0,0 +1,189 @@ +// 🌟 This was machine generated. Do not edit. 🌟 +// +// Frame[0] { +// "typeVersion": [ +// 0, +// 0 +// ], +// "custom": { +// "resolution": "RAW" +// } +// } +// Name: +// Dimensions: 3 Fields by 35 Rows +// +-------------------------------+----------------------------+----------------+ +// | Name: time | Name: /amazon/renton/1/rpm | Name: quality | +// | Labels: | Labels: | Labels: | +// | Type: []time.Time | Type: []bool | Type: []string | +// +-------------------------------+----------------------------+----------------+ +// | 2021-02-01 17:30:00 +0100 CET | true | GOOD | +// | 2021-02-01 17:35:00 +0100 CET | true | GOOD | +// | 2021-02-01 17:40:00 +0100 CET | false | GOOD | +// | 2021-02-01 17:45:00 +0100 CET | false | GOOD | +// | 2021-02-01 17:50:00 +0100 CET | true | GOOD | +// | 2021-02-01 17:55:00 +0100 CET | true | GOOD | +// | 2021-02-01 18:00:00 +0100 CET | false | GOOD | +// | 2021-02-01 18:05:00 +0100 CET | false | GOOD | +// | 2021-02-01 18:10:00 +0100 CET | true | GOOD | +// | ... | ... | ... | +// +-------------------------------+----------------------------+----------------+ +// +// +// 🌟 This was machine generated. Do not edit. 🌟 +{ + "status": 200, + "frames": [ + { + "schema": { + "meta": { + "typeVersion": [ + 0, + 0 + ], + "custom": { + "resolution": "RAW" + } + }, + "fields": [ + { + "name": "time", + "type": "time", + "typeInfo": { + "frame": "time.Time" + } + }, + { + "name": "/amazon/renton/1/rpm", + "type": "boolean", + "typeInfo": { + "frame": "bool" + }, + "config": {} + }, + { + "name": "quality", + "type": "string", + "typeInfo": { + "frame": "string" + } + } + ] + }, + "data": { + "values": [ + [ + 1612197000000, + 1612197300000, + 1612197600000, + 1612197900000, + 1612198200000, + 1612198500000, + 1612198800000, + 1612199100000, + 1612199400000, + 1612199700000, + 1612200000000, + 1612200300000, + 1612200600000, + 1612200900000, + 1612201200000, + 1612201500000, + 1612201800000, + 1612202100000, + 1612202400000, + 1612202700000, + 1612203000000, + 1612203300000, + 1612203600000, + 1612203900000, + 1612204200000, + 1612204500000, + 1612204800000, + 1612205100000, + 1612205400000, + 1612205700000, + 1612206000000, + 1612206300000, + 1612206600000, + 1612206900000, + 1612207200000 + ], + [ + true, + true, + false, + false, + true, + true, + false, + false, + true, + true, + false, + false, + true, + true, + false, + false, + true, + true, + false, + false, + true, + true, + false, + false, + true, + true, + false, + false, + true, + true, + false, + false, + true, + true, + false + ], + [ + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD", + "GOOD" + ] + ] + } + } + ] +} \ No newline at end of file diff --git a/pkg/testdata/property-history-values-from-alias-boolean-with-disassociated-stream-empty-response-A.golden.jsonc b/pkg/testdata/property-history-values-from-alias-boolean-with-disassociated-stream-empty-response-A.golden.jsonc new file mode 100644 index 00000000..32d200ba --- /dev/null +++ b/pkg/testdata/property-history-values-from-alias-boolean-with-disassociated-stream-empty-response-A.golden.jsonc @@ -0,0 +1,71 @@ +// 🌟 This was machine generated. Do not edit. 🌟 +// +// Frame[0] { +// "typeVersion": [ +// 0, +// 0 +// ], +// "custom": { +// "resolution": "RAW" +// } +// } +// Name: +// Dimensions: 3 Fields by 0 Rows +// +-------------------+----------------------------+----------------+ +// | Name: time | Name: /amazon/renton/1/rpm | Name: quality | +// | Labels: | Labels: | Labels: | +// | Type: []time.Time | Type: []float64 | Type: []string | +// +-------------------+----------------------------+----------------+ +// +-------------------+----------------------------+----------------+ +// +// +// 🌟 This was machine generated. Do not edit. 🌟 +{ + "status": 200, + "frames": [ + { + "schema": { + "meta": { + "typeVersion": [ + 0, + 0 + ], + "custom": { + "resolution": "RAW" + } + }, + "fields": [ + { + "name": "time", + "type": "time", + "typeInfo": { + "frame": "time.Time" + } + }, + { + "name": "/amazon/renton/1/rpm", + "type": "number", + "typeInfo": { + "frame": "float64" + }, + "config": {} + }, + { + "name": "quality", + "type": "string", + "typeInfo": { + "frame": "string" + } + } + ] + }, + "data": { + "values": [ + [], + [], + [] + ] + } + } + ] +} \ No newline at end of file diff --git a/pkg/testdata/property-history-values-from-alias-disassociated-empty-response.json b/pkg/testdata/property-history-values-from-alias-disassociated-empty-response.json new file mode 100644 index 00000000..36fbee58 --- /dev/null +++ b/pkg/testdata/property-history-values-from-alias-disassociated-empty-response.json @@ -0,0 +1,8 @@ +{ + "AssetPropertyValueHistory": [], + "NextToken": "Pac27e1b8b7004c9e9e3e0178f3100cd4=AYADeB7wD96YfxEDz5ApsX6rKE8AXwABABVhd3MtY3J5cHRvLXB1YmxpYy1rZXkAREFrR0JGZWdjZkx1ajdiQ0h0Z3M0K3JFMW5FSngwNjJnTFozNTdmY3cwR1FLRTdad2VONEdHZVRLaDNFRSsvVXBsUT09AAEAA0FTTQA0YWMyN2UxYjhiNzAwNGM5ZTllM2UwMTc4ZjMxMDBjZDQAAACAAAAADLek1jU+goh+Y96/ZgAwQ/mhxOY2dchugmvz6ktDbfOcHAj8vvea3UzYtWahiM2BMRgYMRhPAHBm99rUlEqtAgAAAAAMAAAQAAAAAAAAAAAAAAAAAJUmtM2zXxkajPPvDCSTBdj/////AAAAAQAAAAAAAAAAAAAAAQAAAjEwyVkE50YAR0TPbv7ew+W62V/tElf7/tctiqb+DIsl7JjSanWIspl22qc1eTke3P5eSeXS1iUX+JKtKlqn/rWMcFS7mKsTDjeclQDoWD2c9BZrgNeei0F1d6LXGyrFM6o9blf+0qTWnSWVHFAWECAu84GMTW650Z0QRxtmKDxFDToskXFQqf6ZAbwe6DcxVd1Msvnu2iPs3C7ZJ5wOOO+W3A5o6YiWdHpVfUp3bhFput5HA/O5ffLcqYZTARqqYEckVSFE8FLaU9aainIt8NKuOYd4944OD4jOS/BOENLvsN3veGm+qHG/RIkcPKkWkS4nJXvShqSLBJF3SuhCgYqxhV5qN8WlJ+jcE1gAc72BIrBpgqbPa66iaQnnDDyuVyFmLFgpxL81WuiCakLjc4CsJU74A4WankPjrorZZQVXsK388YZAfzlsetuQicQt/PwUmO4DNSSjLwjGnfawhH+zaLyqZfjUSJwbv4uxxbFaswi+NEOOSbLOsXPIdhN5W9dfu6i3al0ZyY6xMe7ruAoNz8InnE0UXJHZ+aGbhO/CdzX/g04N0SiI9y+yQhXQixe8cJA6d3VqDILhTNGw4R5i5M69dGVOjR/Y6iO8LT0k8ZBKRRx8qv/rOgFuNEvk3MuwSyr5wO6fRVqKeM9QOZhagc0q6OW3kHPD7Y8Y/9EpG3TZTd5J9Q6SdH+rz8StNOBt+HrxjnqnC42mIGWsABtgsEutJhroir81/3Bc8ReDyEhFWkicgpYJDM4ULW2h8K2KAGcwZQIxAKrXUH5h3Zf/vq2BhK0f/4BV1oEwROf2ppp53Gt69poRfqotIQmvrnbV3g+KtS5OEAIwXA79NeK4xrpMCe1322SZ+ybR4Tmlbsnd6+68V9n5Y9ADC/7bQ6TPtDABfG7qkhOS", + "Query": { + "propertyAlias": "/amazon/renton/1/rpm", + "maxPageAggregations": 1 + } +} diff --git a/pkg/testdata/property-history-values-from-alias-disassociated.json b/pkg/testdata/property-history-values-from-alias-disassociated.json new file mode 100644 index 00000000..70c643e8 --- /dev/null +++ b/pkg/testdata/property-history-values-from-alias-disassociated.json @@ -0,0 +1,3259 @@ +{ + "AssetPropertyValueHistory": [ + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368494 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 33.051673012498036, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368495 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 33.13975223107515, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368496 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 33.117145236844, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368497 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 33.005076048062705, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368498 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 33.08812139072301, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368499 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 33.11194134756939, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368500 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 33.03951942228485, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368501 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 33.13729721356579, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368503 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.989202334386036, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368504 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.934583022747425, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368505 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 33.00178805800636, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368506 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.97804116296796, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368507 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.99447623542969, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368508 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.987375088122356, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368509 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.93836056283982, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368510 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.95189606857263, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368511 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 33.002302094857285, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368512 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.96146561243608, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368513 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.96791313771837, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368514 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.967816813627195, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368515 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.95522735064316, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368516 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.99521081936715, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368517 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.93141043445317, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368518 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.93731022274138, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368519 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.98924091856808, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368520 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.988936336734, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368521 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.965658665295734, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368522 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.98590216709441, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368523 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.98303132081303, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368524 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.95930831017469, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368525 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.94607215153201, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368526 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 33.00316941264218, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368527 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.95307030588052, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368528 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.936381216665445, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368529 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.94028557816653, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368530 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.97406090243209, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368531 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.99590742540219, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368532 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.94795260963136, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368533 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.97156017766616, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368534 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.986755216113416, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368535 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.999166917032596, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368536 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.96569617522532, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368537 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.957117969906555, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368538 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.95569247497845, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368539 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.99380574467904, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368540 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.981680729750344, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368541 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.975589015107985, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368542 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.96753026445135, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368543 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.992867659182146, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368544 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.99769899498714, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368545 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.9913484213298, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368546 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.981242272559136, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368547 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.979816777770544, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368548 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 33.002122832952224, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368549 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.938060070830225, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368550 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.98914802952298, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368551 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.93111954294142, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368552 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.979902316912096, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368553 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.9819944331639, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368554 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 33.0045591905524, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368555 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.96569652241702, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368556 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.94499142104827, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368557 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.95455410860575, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368558 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.94088281887162, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368559 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.96910431408667, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368560 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.96331360621206, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368561 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.95738650159099, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368562 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.68199192230752, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368563 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.36003522671322, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368564 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.74438349964775, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368565 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.65386678712134, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368566 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.784589522692144, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368567 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.36008274626955, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368568 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.817446335803155, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368569 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.50738607882386, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368570 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.885654533056815, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368571 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.37617298444556, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368572 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.39693268893535, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368573 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.637499820233025, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368574 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.35303042289689, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368575 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.64900698945831, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368576 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.46847622449745, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368577 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.87289303152726, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368578 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.73858255112008, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368579 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.47491867222704, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368580 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.384315342335945, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368581 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.86537715836431, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368582 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.76572973841917, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368583 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.91261354484485, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368584 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.770192499694495, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368585 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.81828969884913, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368586 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.46128888293288, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368587 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.76251477664546, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368588 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.704955561896135, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368589 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.51926146548139, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368590 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.634094059783216, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368591 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.66546153083306, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368592 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.86716517545729, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368593 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.65044629233098, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368594 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.49789125936552, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368595 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.71845409120877, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368596 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.58082102155535, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368597 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.62415465946752, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368598 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.665008712764525, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368599 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.35215943669837, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368600 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.75751960810145, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368601 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.8923343654765, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368602 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.61046524040131, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368603 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.479305032306904, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368604 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.61692063518682, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368605 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.36887787616485, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368606 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.77200424814639, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368607 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.75274475351076, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368608 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.8398778646626, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368609 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.4651132769262, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368610 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.89605740746869, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368611 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.909398233008694, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368612 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.682521856883056, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368613 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.74396777334688, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368614 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.54647764609465, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368615 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.79087082869232, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368616 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.688739610062214, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368617 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.467925864586526, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368618 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.40650804077812, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368619 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.679634913239624, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368620 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.85793246076542, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368621 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.651431537300724, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368622 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.76600453823212, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368623 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.39039042686536, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368624 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.63664497411701, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368625 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.88109073577085, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368626 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.719971692881145, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368627 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.54778436852072, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368628 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.69643611637554, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368629 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.34435148570677, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368630 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.39187034448192, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368631 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.587993100977286, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368632 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.57080827503957, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368633 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.87699762613215, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368634 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.832613835559314, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368635 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.831651046393375, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368636 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.55276769104299, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368637 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.623710110515724, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368638 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.36217323331328, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368639 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.77734332466742, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368640 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.60790422411928, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368641 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.8234872882669, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368642 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.8052352184766, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368643 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.596246431253185, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368644 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.47145748961048, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368645 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.65988221716882, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368646 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.70585006009133, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368647 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.489794380912436, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368648 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.37246306878219, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368649 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.591549081184894, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368650 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.620272540321174, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368651 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.783358417491144, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368652 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.4647057944717, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368653 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.68343630290723, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368654 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.46653963246343, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368655 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.78327944999353, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368656 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.74318926992981, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368657 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.732856799810214, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368658 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.87572586812359, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368659 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.402209662397055, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368660 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.41428725395299, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368661 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.39174970829819, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368662 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.827541871956186, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368663 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.38750275935463, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368664 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.369622315052005, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368665 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.48897996486204, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368666 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.409089131080194, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368667 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.596607991555686, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368668 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.5056392380832, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368669 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.62722171354342, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368670 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.5941104074963, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368671 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.87773958464462, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368672 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.627884938343364, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368673 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.711216821797414, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368674 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.67179384173786, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368675 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.70013581152619, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368676 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.89093895468822, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368677 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.77872662975507, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368678 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.73133246057074, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368679 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.67458742687953, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368680 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.57092977345809, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368681 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.41336854315389, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368682 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.38892586213455, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368683 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.5584072599331, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368684 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.47029646306458, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368685 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.495854771578735, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368686 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.5037124144032, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368687 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.58913350009725, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368688 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.54908911137108, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368689 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.36233495268232, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368690 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.51262974071021, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368691 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.532768700936344, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368692 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.344025034087544, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368693 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.49687270662588, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368694 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.50842910189536, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368695 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.48214163956658, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368696 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.351482485719245, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368697 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.38474845448547, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368698 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.43158608371481, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368699 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.447725983670715, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368700 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.48717762547366, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368701 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.49122739450515, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368702 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.410916203395935, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368703 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.47267355916452, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368704 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.4991142060543, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368705 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.36836884789964, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368706 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.42608252413705, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368707 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.37154929635479, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368708 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.40128972625851, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368709 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.53288646453798, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368710 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.44662723235496, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368711 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.46025368010737, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368712 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.38037394318173, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368713 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.46318222439887, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368714 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.556678966230756, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368715 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.37356718575815, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368716 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.565304190080205, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368717 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.3761197704734, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368718 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.50948660777987, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368719 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.550647750534296, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368720 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.606576778827446, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368721 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.459764661720115, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368722 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.38990857961259, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368723 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.47644509098468, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368724 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.35547310094432, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368725 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.52902677870059, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368726 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.45701449947238, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368727 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.46518553739097, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368728 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.488414193245404, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368729 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.40203921535132, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368730 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.57838936203865, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368731 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.40561300882473, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368732 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.46472939980301, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368733 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.6074820813432, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368734 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.5482539004254, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368735 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.355929674901446, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368736 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.506561301374816, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368737 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.34753627146235, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368738 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.53642407880251, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368739 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.543695135783814, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368740 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.420431103352634, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368741 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.42402014090615, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368743 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.71173146467559, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368744 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.704134383384414, + "IntegerValue": null, + "StringValue": null + } + }, + { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1626368745 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 32.67438841801078, + "IntegerValue": null, + "StringValue": null + } + } + ], + "NextToken": "Pac27e1b8b7004c9e9e3e0178f3100cd4=AYADeB7wD96YfxEDz5ApsX6rKE8AXwABABVhd3MtY3J5cHRvLXB1YmxpYy1rZXkAREFrR0JGZWdjZkx1ajdiQ0h0Z3M0K3JFMW5FSngwNjJnTFozNTdmY3cwR1FLRTdad2VONEdHZVRLaDNFRSsvVXBsUT09AAEAA0FTTQA0YWMyN2UxYjhiNzAwNGM5ZTllM2UwMTc4ZjMxMDBjZDQAAACAAAAADLek1jU+goh+Y96/ZgAwQ/mhxOY2dchugmvz6ktDbfOcHAj8vvea3UzYtWahiM2BMRgYMRhPAHBm99rUlEqtAgAAAAAMAAAQAAAAAAAAAAAAAAAAAJUmtM2zXxkajPPvDCSTBdj/////AAAAAQAAAAAAAAAAAAAAAQAAAjEwyVkE50YAR0TPbv7ew+W62V/tElf7/tctiqb+DIsl7JjSanWIspl22qc1eTke3P5eSeXS1iUX+JKtKlqn/rWMcFS7mKsTDjeclQDoWD2c9BZrgNeei0F1d6LXGyrFM6o9blf+0qTWnSWVHFAWECAu84GMTW650Z0QRxtmKDxFDToskXFQqf6ZAbwe6DcxVd1Msvnu2iPs3C7ZJ5wOOO+W3A5o6YiWdHpVfUp3bhFput5HA/O5ffLcqYZTARqqYEckVSFE8FLaU9aainIt8NKuOYd4944OD4jOS/BOENLvsN3veGm+qHG/RIkcPKkWkS4nJXvShqSLBJF3SuhCgYqxhV5qN8WlJ+jcE1gAc72BIrBpgqbPa66iaQnnDDyuVyFmLFgpxL81WuiCakLjc4CsJU74A4WankPjrorZZQVXsK388YZAfzlsetuQicQt/PwUmO4DNSSjLwjGnfawhH+zaLyqZfjUSJwbv4uxxbFaswi+NEOOSbLOsXPIdhN5W9dfu6i3al0ZyY6xMe7ruAoNz8InnE0UXJHZ+aGbhO/CdzX/g04N0SiI9y+yQhXQixe8cJA6d3VqDILhTNGw4R5i5M69dGVOjR/Y6iO8LT0k8ZBKRRx8qv/rOgFuNEvk3MuwSyr5wO6fRVqKeM9QOZhagc0q6OW3kHPD7Y8Y/9EpG3TZTd5J9Q6SdH+rz8StNOBt+HrxjnqnC42mIGWsABtgsEutJhroir81/3Bc8ReDyEhFWkicgpYJDM4ULW2h8K2KAGcwZQIxAKrXUH5h3Zf/vq2BhK0f/4BV1oEwROf2ppp53Gt69poRfqotIQmvrnbV3g+KtS5OEAIwXA79NeK4xrpMCe1322SZ+ybR4Tmlbsnd6+68V9n5Y9ADC/7bQ6TPtDABfG7qkhOS", + "Query": { + "propertyAlias": "/amazon/renton/1/rpm", + "maxPageAggregations": 1 + } +} \ No newline at end of file diff --git a/pkg/testdata/property-history-values-from-alias-table-disassociated-A.golden.jsonc b/pkg/testdata/property-history-values-from-alias-table-disassociated-A.golden.jsonc new file mode 100644 index 00000000..38ec4550 --- /dev/null +++ b/pkg/testdata/property-history-values-from-alias-table-disassociated-A.golden.jsonc @@ -0,0 +1,6 @@ +// 🌟 This was machine generated. Do not edit. 🌟 +// 🌟 This was machine generated. Do not edit. 🌟 +{ + "status": 200, + "frames": [] +} \ No newline at end of file diff --git a/pkg/testdata/property-history-values-from-alias-table-disassociated-empty-response-A.golden.jsonc b/pkg/testdata/property-history-values-from-alias-table-disassociated-empty-response-A.golden.jsonc new file mode 100644 index 00000000..38ec4550 --- /dev/null +++ b/pkg/testdata/property-history-values-from-alias-table-disassociated-empty-response-A.golden.jsonc @@ -0,0 +1,6 @@ +// 🌟 This was machine generated. Do not edit. 🌟 +// 🌟 This was machine generated. Do not edit. 🌟 +{ + "status": 200, + "frames": [] +} \ No newline at end of file diff --git a/pkg/testdata/property-history-values-from-alias-timeseries-disassociated-A.golden.jsonc b/pkg/testdata/property-history-values-from-alias-timeseries-disassociated-A.golden.jsonc new file mode 100644 index 00000000..38ec4550 --- /dev/null +++ b/pkg/testdata/property-history-values-from-alias-timeseries-disassociated-A.golden.jsonc @@ -0,0 +1,6 @@ +// 🌟 This was machine generated. Do not edit. 🌟 +// 🌟 This was machine generated. Do not edit. 🌟 +{ + "status": 200, + "frames": [] +} \ No newline at end of file diff --git a/pkg/testdata/property-history-values-from-alias-timeseries-disassociated-empty-response-A.golden.jsonc b/pkg/testdata/property-history-values-from-alias-timeseries-disassociated-empty-response-A.golden.jsonc new file mode 100644 index 00000000..38ec4550 --- /dev/null +++ b/pkg/testdata/property-history-values-from-alias-timeseries-disassociated-empty-response-A.golden.jsonc @@ -0,0 +1,6 @@ +// 🌟 This was machine generated. Do not edit. 🌟 +// 🌟 This was machine generated. Do not edit. 🌟 +{ + "status": 200, + "frames": [] +} \ No newline at end of file diff --git a/pkg/testdata/property-value-disassociated.json b/pkg/testdata/property-value-disassociated.json new file mode 100644 index 00000000..f94171f3 --- /dev/null +++ b/pkg/testdata/property-value-disassociated.json @@ -0,0 +1,21 @@ +{ + "SuccessEntries": [ + { + "AssetPropertyValue": { + "Quality": "GOOD", + "Timestamp": { + "OffsetInNanos": 0, + "TimeInSeconds": 1612207200 + }, + "Value": { + "BooleanValue": null, + "DoubleValue": 23.81007059955162, + "IntegerValue": null, + "StringValue": null + } + }, + "EntryId": "_amazon_renton_1_rpm" + } + ], + "NextToken": null +} diff --git a/pkg/util/ids.go b/pkg/util/ids.go new file mode 100644 index 00000000..714452cc --- /dev/null +++ b/pkg/util/ids.go @@ -0,0 +1,37 @@ +package util + +import ( + "strings" + + "github.com/aws/aws-sdk-go/aws" + "github.com/grafana/iot-sitewise-datasource/pkg/models" +) + +func GetAssetId(query models.BaseQuery) *string { + if len(query.AssetIds) == 0 { + return nil + } + return aws.String(query.AssetIds[0]) +} + +func GetPropertyId(query models.BaseQuery) *string { + if query.PropertyId == "" { + return nil + } + return aws.String(query.PropertyId) +} + +func GetPropertyAlias(query models.BaseQuery) *string { + if query.PropertyAlias == "" { + return nil + } + return aws.String(query.PropertyAlias) +} + +func GetEntryId(query models.BaseQuery) *string { + if query.PropertyAlias != "" && len(query.AssetIds) == 0 && query.PropertyId == "" { + // API constraint: EntryId cannot have a slash in it, so replace with underscore + return aws.String(strings.ReplaceAll(query.PropertyAlias, "/", "_")) + } + return GetAssetId(query) +} diff --git a/src/DataSource.ts b/src/DataSource.ts index 4c332a05..3e647582 100644 --- a/src/DataSource.ts +++ b/src/DataSource.ts @@ -94,7 +94,7 @@ export class DataSource extends DataSourceWithBackend