Skip to content

Commit d9e6711

Browse files
committed
Fix subscription removal for multiple remotes
- When a service has multiple similar remote devices (EVSEs with attached EVs), then removing an EV did remove the subscriptions for all remote EVs and therefor these wallboxes switched into fallback mode. This change fixes this - Add more tests for NodeManagementDetailedDiscovery entity removal
1 parent f94715c commit d9e6711

5 files changed

+132
-8
lines changed

spine/helper_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@ import (
1818
)
1919

2020
const (
21-
wallbox_detaileddiscoverydata_recv_reply_file_path = "./testdata/wallbox_detaileddiscoverydata_recv_reply.json"
22-
wallbox_detaileddiscoverydata_recv_notify_file_path = "./testdata/wallbox_detaileddiscoverydata_recv_notify.json"
21+
wallbox_detaileddiscoverydata_recv_reply_file_path = "./testdata/wallbox_detaileddiscoverydata_recv_reply.json"
22+
wallbox_detaileddiscoverydata_recv_notify_file_path = "./testdata/wallbox_detaileddiscoverydata_recv_notify.json"
23+
wallbox_detaileddiscoverydata_recv_notify_remove_file_path = "./testdata/wallbox_detaileddiscoverydata_recv_notify_remove.json"
2324
)
2425

2526
type WriteMessageHandler struct {

spine/nodemanagement_detaileddiscovery_test.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,27 @@ func (s *NodeManagementSuite) TestDetailedDiscovery_RecvNotifyAdded() {
153153
assert.Equal(s.T(), 10, len(ev.Features()))
154154
}
155155
}
156+
157+
// Act
158+
msgCounter, _ = s.remoteDevice.HandleSpineMesssage(loadFileData(s.T(), wallbox_detaileddiscoverydata_recv_notify_remove_file_path))
159+
waitForAck(s.T(), msgCounter, s.writeHandler)
160+
161+
// Assert
162+
rEntities = remoteDevice.Entities()
163+
if assert.Equal(s.T(), 2, len(rEntities)) {
164+
{
165+
di := rEntities[DeviceInformationEntityId]
166+
assert.NotNil(s.T(), di)
167+
assert.Equal(s.T(), model.EntityTypeTypeDeviceInformation, di.EntityType())
168+
assert.Equal(s.T(), 2, len(di.Features()))
169+
}
170+
{
171+
evse := rEntities[1]
172+
assert.NotNil(s.T(), evse)
173+
assert.Equal(s.T(), model.EntityTypeTypeEVSE, evse.EntityType())
174+
assert.Equal(s.T(), 3, len(evse.Features()))
175+
}
176+
}
156177
}
157178

158179
func (s *NodeManagementSuite) TestDetailedDiscovery_SendReplyWithAcknowledge() {

spine/subscription_manager.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,9 @@ func (c *SubscriptionManager) RemoveSubscription(data model.SubscriptionManageme
114114
for _, item := range c.subscriptionEntries {
115115
itemAddress := item.ClientFeature.Address()
116116

117-
if !reflect.DeepEqual(*itemAddress, clientAddress) &&
117+
if !reflect.DeepEqual(itemAddress.Device, clientAddress.Device) ||
118+
!reflect.DeepEqual(itemAddress.Entity, clientAddress.Entity) ||
119+
!reflect.DeepEqual(itemAddress.Feature, clientAddress.Feature) ||
118120
!reflect.DeepEqual(item.ServerFeature, serverFeature) {
119121
newSubscriptionEntries = append(newSubscriptionEntries, item)
120122
}
@@ -163,7 +165,8 @@ func (c *SubscriptionManager) RemoveSubscriptionsForEntity(remoteEntity api.Enti
163165

164166
var newSubscriptionEntries []*api.SubscriptionEntry
165167
for _, item := range c.subscriptionEntries {
166-
if !reflect.DeepEqual(item.ClientFeature.Address().Entity, remoteEntity.Address().Entity) {
168+
if !reflect.DeepEqual(item.ClientFeature.Address().Device, remoteEntity.Address().Device) ||
169+
!reflect.DeepEqual(item.ClientFeature.Address().Entity, remoteEntity.Address().Entity) {
167170
newSubscriptionEntries = append(newSubscriptionEntries, item)
168171
continue
169172
}

spine/subscription_manager_test.go

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@ func TestSubscriptionManagerSuite(t *testing.T) {
1818
type SubscriptionManagerSuite struct {
1919
suite.Suite
2020

21-
localDevice api.DeviceLocalInterface
22-
remoteDevice api.DeviceRemoteInterface
23-
sut api.SubscriptionManagerInterface
21+
localDevice api.DeviceLocalInterface
22+
remoteDevice,
23+
remoteDevice2 api.DeviceRemoteInterface
24+
sut api.SubscriptionManagerInterface
2425
}
2526

2627
func (suite *SubscriptionManagerSuite) WriteShipMessageWithPayload([]byte) {}
@@ -31,9 +32,12 @@ func (suite *SubscriptionManagerSuite) SetupSuite() {
3132
ski := "test"
3233
sender := NewSender(suite)
3334
suite.remoteDevice = NewDeviceRemote(suite.localDevice, ski, sender)
34-
3535
_ = suite.localDevice.SetupRemoteDevice(ski, suite)
3636

37+
ski2 := "test2"
38+
suite.remoteDevice2 = NewDeviceRemote(suite.localDevice, ski2, sender)
39+
_ = suite.localDevice.SetupRemoteDevice(ski2, suite)
40+
3741
suite.sut = NewSubscriptionManager(suite.localDevice)
3842
}
3943

@@ -49,13 +53,28 @@ func (suite *SubscriptionManagerSuite) Test_Subscriptions() {
4953
remoteFeature := NewFeatureRemote(remoteEntity.NextFeatureId(), remoteEntity, model.FeatureTypeTypeDeviceDiagnosis, model.RoleTypeClient)
5054
remoteFeature.Address().Device = util.Ptr(model.AddressDeviceType("remoteDevice"))
5155
remoteEntity.AddFeature(remoteFeature)
56+
remoteEntity.Address().Device = util.Ptr(model.AddressDeviceType("remoteDevice"))
5257

5358
subscrRequest := model.SubscriptionManagementRequestCallType{
5459
ClientAddress: remoteFeature.Address(),
5560
ServerAddress: localFeature.Address(),
5661
ServerFeatureType: util.Ptr(model.FeatureTypeTypeDeviceDiagnosis),
5762
}
5863

64+
remoteEntity2 := NewEntityRemote(suite.remoteDevice2, model.EntityTypeTypeEVSE, []model.AddressEntityType{1})
65+
suite.remoteDevice2.AddEntity(remoteEntity2)
66+
67+
remoteFeature2 := NewFeatureRemote(remoteEntity2.NextFeatureId(), remoteEntity2, model.FeatureTypeTypeDeviceDiagnosis, model.RoleTypeClient)
68+
remoteFeature2.Address().Device = util.Ptr(model.AddressDeviceType("remoteDevice2"))
69+
remoteEntity2.AddFeature(remoteFeature2)
70+
remoteEntity2.Address().Device = util.Ptr(model.AddressDeviceType("remoteDevice2"))
71+
72+
subscrRequest2 := model.SubscriptionManagementRequestCallType{
73+
ClientAddress: remoteFeature2.Address(),
74+
ServerAddress: localFeature.Address(),
75+
ServerFeatureType: util.Ptr(model.FeatureTypeTypeDeviceDiagnosis),
76+
}
77+
5978
subMgr := suite.localDevice.SubscriptionManager()
6079
err := subMgr.AddSubscription(suite.remoteDevice, subscrRequest)
6180
assert.Nil(suite.T(), err)
@@ -69,6 +88,12 @@ func (suite *SubscriptionManagerSuite) Test_Subscriptions() {
6988
subs = subMgr.Subscriptions(suite.remoteDevice)
7089
assert.Equal(suite.T(), 1, len(subs))
7190

91+
err = subMgr.AddSubscription(suite.remoteDevice2, subscrRequest2)
92+
assert.Nil(suite.T(), err)
93+
94+
subs = subMgr.Subscriptions(suite.remoteDevice2)
95+
assert.Equal(suite.T(), 1, len(subs))
96+
7297
subscrDelete := model.SubscriptionManagementDeleteCallType{
7398
ClientAddress: remoteFeature.Address(),
7499
ServerAddress: localFeature.Address(),
@@ -90,8 +115,21 @@ func (suite *SubscriptionManagerSuite) Test_Subscriptions() {
90115
subs = subMgr.Subscriptions(suite.remoteDevice)
91116
assert.Equal(suite.T(), 1, len(subs))
92117

118+
subMgr.RemoveSubscriptionsForEntity(nil)
119+
120+
subs = subMgr.Subscriptions(suite.remoteDevice)
121+
assert.Equal(suite.T(), 1, len(subs))
122+
123+
subMgr.RemoveSubscriptionsForDevice(nil)
124+
125+
subs = subMgr.Subscriptions(suite.remoteDevice)
126+
assert.Equal(suite.T(), 1, len(subs))
127+
93128
subMgr.RemoveSubscriptionsForDevice(suite.remoteDevice)
94129

95130
subs = subMgr.Subscriptions(suite.remoteDevice)
96131
assert.Equal(suite.T(), 0, len(subs))
132+
133+
subs = subMgr.Subscriptions(suite.remoteDevice2)
134+
assert.Equal(suite.T(), 1, len(subs))
97135
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
{
2+
"datagram": {
3+
"header": {
4+
"specificationVersion": "1.3.0",
5+
"addressSource": {
6+
"device": "Wallbox",
7+
"entity": [
8+
0
9+
],
10+
"feature": 0
11+
},
12+
"addressDestination": {
13+
"device": "HEMS",
14+
"entity": [
15+
0
16+
],
17+
"feature": 0
18+
},
19+
"msgCounter": 4,
20+
"cmdClassifier": "notify",
21+
"ackRequest":true
22+
},
23+
"payload": {
24+
"cmd": [
25+
{
26+
"function": "nodeManagementDetailedDiscoveryData",
27+
"filter": [
28+
{
29+
"cmdControl": {
30+
"partial": {}
31+
}
32+
}
33+
],
34+
"nodeManagementDetailedDiscoveryData": {
35+
"deviceInformation": {
36+
"description": {
37+
"deviceAddress": {
38+
"device": "Wallbox"
39+
}
40+
}
41+
},
42+
"entityInformation": [
43+
{
44+
"description": {
45+
"entityAddress": {
46+
"entity": [
47+
1,
48+
1
49+
]
50+
},
51+
"entityType": "EV",
52+
"lastStateChange": "removed"
53+
}
54+
}
55+
]
56+
}
57+
}
58+
]
59+
}
60+
}
61+
}

0 commit comments

Comments
 (0)