Skip to content

Commit

Permalink
feat: stub notify report
Browse files Browse the repository at this point in the history
  • Loading branch information
subnova committed Mar 18, 2024
1 parent 94c32d2 commit 305060e
Show file tree
Hide file tree
Showing 7 changed files with 268 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .talismanrc
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@ fileignoreconfig:
checksum: 59847ff1e1e7e69859e48cbb64b1bfaacd304e66854a9b18bfccbb6bc2280537
- filename: manager/ocpp/ocpp201/id_token_enum_type.go
checksum: 12cb2bc8ca2fe84231986857696a463e3dff4d5f9cdde9b265899b09bb1f95b0
- filename: manager/ocpp/ocpp201/notify_report_request.go
checksum: 56f5032378467e28dfc09b1c76d8eb7d96d13be2f14408532d9fdb284059178a
- filename: manager/ocpp/ocpp201/set_variables_request.go
checksum: d89e126fff18c8e6ecdc170a86bceb01fd2f46a676cae7178c17d1fa3e642613
- filename: manager/ocpp/ocpp201/transactionevent_request.go
Expand Down
27 changes: 27 additions & 0 deletions manager/handlers/ocpp201/notify_report.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// SPDX-License-Identifier: Apache-2.0

package ocpp201

import (
"context"
"github.com/thoughtworks/maeve-csms/manager/ocpp"
"github.com/thoughtworks/maeve-csms/manager/ocpp/ocpp201"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
)

type NotifyReportHandler struct{}

func (h NotifyReportHandler) HandleCall(ctx context.Context, chargeStationId string, request ocpp.Request) (response ocpp.Response, err error) {
req := request.(*ocpp201.NotifyReportRequestJson)

span := trace.SpanFromContext(ctx)

span.SetAttributes(
attribute.String("notify_report.generated_at", req.GeneratedAt),
attribute.Int("notify_report.request_id", req.RequestId),
attribute.Int("notify_report.seq_no", req.SeqNo),
attribute.Bool("notify_report.tbc", req.Tbc))

return &ocpp201.NotifyReportResponseJson{}, nil
}
65 changes: 65 additions & 0 deletions manager/handlers/ocpp201/notify_report_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// SPDX-License-Identifier: Apache-2.0

package ocpp201_test

import (
"context"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/thoughtworks/maeve-csms/manager/handlers/ocpp201"
types "github.com/thoughtworks/maeve-csms/manager/ocpp/ocpp201"
"github.com/thoughtworks/maeve-csms/manager/testutil"
"testing"
)

func TestNotifyReport(t *testing.T) {
handler := ocpp201.NotifyReportHandler{}

tracer, exporter := testutil.GetTracer()

ctx := context.Background()

func() {
ctx, span := tracer.Start(ctx, "test")
defer span.End()

req := &types.NotifyReportRequestJson{
GeneratedAt: "2024-03-18T17:10:00.000Z",
ReportData: []types.ReportDataType{
{
Component: types.ComponentType{
Name: "SomeCtrlr",
},
Variable: types.VariableType{
Name: "SomeVar",
},
VariableAttribute: []types.VariableAttributeType{
{
Constant: false,
Mutability: makePtr(types.MutabilityEnumTypeReadOnly),
Persistent: true,
Type: makePtr(types.AttributeEnumTypeActual),
Value: makePtr("19"),
},
},
VariableCharacteristics: nil,
},
},
RequestId: 42,
SeqNo: 1,
Tbc: false,
}

resp, err := handler.HandleCall(ctx, "cs001", req)
require.NoError(t, err)

assert.Equal(t, &types.NotifyReportResponseJson{}, resp)
}()

testutil.AssertSpan(t, &exporter.GetSpans()[0], "test", map[string]any{
"notify_report.generated_at": "2024-03-18T17:10:00.000Z",
"notify_report.request_id": 42,
"notify_report.seq_no": 1,
"notify_report.tbc": false,
})
}
6 changes: 6 additions & 0 deletions manager/handlers/ocpp201/routing.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,12 @@ func NewRouter(emitter transport.Emitter,
ResponseSchema: "ocpp201/MeterValuesResponse.json",
Handler: MeterValuesHandler{},
},
"NotifyReport": {
NewRequest: func() ocpp.Request { return new(ocpp201.NotifyReportRequestJson) },
RequestSchema: "ocpp201/NotifyReportRequest.json",
ResponseSchema: "ocpp201/NotifyReportResponse.json",
Handler: NotifyReportHandler{},
},
"StatusNotification": {
NewRequest: func() ocpp.Request { return new(ocpp201.StatusNotificationRequestJson) },
RequestSchema: "ocpp201/StatusNotificationRequest.json",
Expand Down
6 changes: 6 additions & 0 deletions manager/handlers/ocpp201/routing_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,12 @@ func TestRoutingCalls(t *testing.T) {
},
},
},
"NotifyReport": &types.NotifyReportRequestJson{
GeneratedAt: "2024-03-18T17:50:00.000Z",
RequestId: 33,
SeqNo: 1,
Tbc: false,
},
"SecurityEventNotification": &types.SecurityEventNotificationRequestJson{
Timestamp: "2023-06-15T15:05:00+01:00",
Type: "SettingSystemTime",
Expand Down
152 changes: 152 additions & 0 deletions manager/ocpp/ocpp201/notify_report_request.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
// SPDX-License-Identifier: Apache-2.0

package ocpp201

type DataEnumType string

const DataEnumTypeBoolean DataEnumType = "boolean"
const DataEnumTypeDateTime DataEnumType = "dateTime"
const DataEnumTypeDecimal DataEnumType = "decimal"
const DataEnumTypeInteger DataEnumType = "integer"
const DataEnumTypeMemberList DataEnumType = "MemberList"
const DataEnumTypeOptionList DataEnumType = "OptionList"
const DataEnumTypeSequenceList DataEnumType = "SequenceList"
const DataEnumTypeString DataEnumType = "string"

type MutabilityEnumType string

const MutabilityEnumTypeReadOnly MutabilityEnumType = "ReadOnly"
const MutabilityEnumTypeReadWrite MutabilityEnumType = "ReadWrite"
const MutabilityEnumTypeWriteOnly MutabilityEnumType = "WriteOnly"

// Attribute data of a variable.
type VariableAttributeType struct {
// If true, value that will never be changed by the Charging Station at runtime.
// Default when omitted is false.
//
Constant bool `json:"constant,omitempty" yaml:"constant,omitempty" mapstructure:"constant,omitempty"`

// CustomData corresponds to the JSON schema field "customData".
CustomData *CustomDataType `json:"customData,omitempty" yaml:"customData,omitempty" mapstructure:"customData,omitempty"`

// Mutability corresponds to the JSON schema field "mutability".
Mutability *MutabilityEnumType `json:"mutability,omitempty" yaml:"mutability,omitempty" mapstructure:"mutability,omitempty"`

// If true, value will be persistent across system reboots or power down. Default
// when omitted is false.
//
Persistent bool `json:"persistent,omitempty" yaml:"persistent,omitempty" mapstructure:"persistent,omitempty"`

// Type corresponds to the JSON schema field "type".
Type *AttributeEnumType `json:"type,omitempty" yaml:"type,omitempty" mapstructure:"type,omitempty"`

// Value of the attribute. May only be omitted when mutability is set to
// 'WriteOnly'.
//
// The Configuration Variable
// <<configkey-reporting-value-size,ReportingValueSize>> can be used
// to limit GetVariableResult.attributeValue, VariableAttribute.value and
// EventData.actualValue. The max size of these values will always remain equal.
//
Value *string `json:"value,omitempty" yaml:"value,omitempty" mapstructure:"value,omitempty"`
}

// Fixed read-only parameters of a variable.
type VariableCharacteristicsType struct {
// CustomData corresponds to the JSON schema field "customData".
CustomData *CustomDataType `json:"customData,omitempty" yaml:"customData,omitempty" mapstructure:"customData,omitempty"`

// DataType corresponds to the JSON schema field "dataType".
DataType DataEnumType `json:"dataType" yaml:"dataType" mapstructure:"dataType"`

// Maximum possible value of this variable. When the datatype of this Variable is
// String, OptionList, SequenceList or MemberList, this field defines the maximum
// length of the (CSV) string.
//
MaxLimit *float64 `json:"maxLimit,omitempty" yaml:"maxLimit,omitempty" mapstructure:"maxLimit,omitempty"`

// Minimum possible value of this variable.
//
MinLimit *float64 `json:"minLimit,omitempty" yaml:"minLimit,omitempty" mapstructure:"minLimit,omitempty"`

// Flag indicating if this variable supports monitoring.
//
SupportsMonitoring bool `json:"supportsMonitoring" yaml:"supportsMonitoring" mapstructure:"supportsMonitoring"`

// Unit of the variable. When the transmitted value has a unit, this field SHALL
// be included.
//
Unit *string `json:"unit,omitempty" yaml:"unit,omitempty" mapstructure:"unit,omitempty"`

// Allowed values when variable is Option/Member/SequenceList.
//
// * OptionList: The (Actual) Variable value must be a single value from the
// reported (CSV) enumeration list.
//
// * MemberList: The (Actual) Variable value may be an (unordered) (sub-)set of
// the reported (CSV) valid values list.
//
// * SequenceList: The (Actual) Variable value may be an ordered (priority, etc)
// (sub-)set of the reported (CSV) valid values.
//
// This is a comma separated list.
//
// The Configuration Variable
// <<configkey-configuration-value-size,ConfigurationValueSize>> can
// be used to limit SetVariableData.attributeValue and
// VariableCharacteristics.valueList. The max size of these values will always
// remain equal.
//
//
ValuesList *string `json:"valuesList,omitempty" yaml:"valuesList,omitempty" mapstructure:"valuesList,omitempty"`
}

// Class to report components, variables and variable attributes and
// characteristics.
type ReportDataType struct {
// Component corresponds to the JSON schema field "component".
Component ComponentType `json:"component" yaml:"component" mapstructure:"component"`

// CustomData corresponds to the JSON schema field "customData".
CustomData *CustomDataType `json:"customData,omitempty" yaml:"customData,omitempty" mapstructure:"customData,omitempty"`

// Variable corresponds to the JSON schema field "variable".
Variable VariableType `json:"variable" yaml:"variable" mapstructure:"variable"`

// VariableAttribute corresponds to the JSON schema field "variableAttribute".
VariableAttribute []VariableAttributeType `json:"variableAttribute" yaml:"variableAttribute" mapstructure:"variableAttribute"`

// VariableCharacteristics corresponds to the JSON schema field
// "variableCharacteristics".
VariableCharacteristics *VariableCharacteristicsType `json:"variableCharacteristics,omitempty" yaml:"variableCharacteristics,omitempty" mapstructure:"variableCharacteristics,omitempty"`
}

type NotifyReportRequestJson struct {
// CustomData corresponds to the JSON schema field "customData".
CustomData *CustomDataType `json:"customData,omitempty" yaml:"customData,omitempty" mapstructure:"customData,omitempty"`

// Timestamp of the moment this message was generated at the Charging Station.
//
GeneratedAt string `json:"generatedAt" yaml:"generatedAt" mapstructure:"generatedAt"`

// ReportData corresponds to the JSON schema field "reportData".
ReportData []ReportDataType `json:"reportData,omitempty" yaml:"reportData,omitempty" mapstructure:"reportData,omitempty"`

// The id of the GetReportRequest or GetBaseReportRequest that requested this
// report
//
RequestId int `json:"requestId" yaml:"requestId" mapstructure:"requestId"`

// Sequence number of this message. First message starts at 0.
//
SeqNo int `json:"seqNo" yaml:"seqNo" mapstructure:"seqNo"`

// “to be continued” indicator. Indicates whether another part of the report
// follows in an upcoming notifyReportRequest message. Default value when omitted
// is false.
//
//
Tbc bool `json:"tbc,omitempty" yaml:"tbc,omitempty" mapstructure:"tbc,omitempty"`
}

func (*NotifyReportRequestJson) IsRequest() {}
10 changes: 10 additions & 0 deletions manager/ocpp/ocpp201/notify_report_response.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// SPDX-License-Identifier: Apache-2.0

package ocpp201

type NotifyReportResponseJson struct {
// CustomData corresponds to the JSON schema field "customData".
CustomData *CustomDataType `json:"customData,omitempty" yaml:"customData,omitempty" mapstructure:"customData,omitempty"`
}

func (*NotifyReportResponseJson) IsResponse() {}

0 comments on commit 305060e

Please sign in to comment.