enbility / eebus-go Goto Github PK
View Code? Open in Web Editor NEWEEBUS protocol implementation in go
Home Page: https://enbility.net
License: MIT License
EEBUS protocol implementation in go
Home Page: https://enbility.net
License: MIT License
The Elli wallbox implements the Heartbeat Diagnosis client Feature on a Generic
featuretype
, see https://github.com/enbility/devices/blob/main/elli/charger-connect-pro/discovery-data.json#L716-L741
The Overload Protection by EV Charging Current Curtailment spec V1.0.1 defines in 3.2.2.1 the feature to be implemented in featureType
DeviceDiagnosis
for the role server
. In 3.2.1.1 it is defined for featureType
any
for the role client
.
Why is that different? Why should this be allowed to be implemented in a non DeviceDiagnosis
featureType
?
Currently the update implementation requires that all fields defined as an identifier key are required to be provided, otherwise the data is updated in all list elements.
What should be done instead?
Currently the project does not directly support creating a UI to guide through the trust and pairing process. This should be added.
When using the demo services (hems, evse) do the following:
SHIP handshake error: Timeout waiting for message
This should work on the first start
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x14 pc=0x1bbfab4]
goroutine 1 [running]:
github.com/evcc-io/evcc/core.(*Loadpoint).Prepare(0x4c35900, 0x57879c0, 0x5787a00, 0x4ce4380)
/home/runner/work/evcc/evcc/core/loadpoint.go:609 +0x93c
github.com/evcc-io/evcc/core.(*Site).Prepare(0x571fd40, 0x4c6d900, 0x4f14200)
/home/runner/work/evcc/evcc/core/site.go:766 +0xd8
github.com/evcc-io/evcc/cmd.runRoot(0x3ae9398, {0x3b222b8, 0x0, 0x0})
/home/runner/work/evcc/evcc/cmd/root.go:260 +0x179c
github.com/spf13/cobra.(*Command).execute(0x3ae9398, {0x4c0e148, 0x0, 0x0})
/home/runner/go/pkg/mod/github.com/spf13/[email protected]/command.go:944 +0x714
github.com/spf13/cobra.(*Command).ExecuteC(0x3ae9398)
/home/runner/go/pkg/mod/github.com/spf13/[email protected]/command.go:1068 +0x418
github.com/spf13/cobra.(*Command).Execute(...)
/home/runner/go/pkg/mod/github.com/spf13/[email protected]/command.go:992
github.com/evcc-io/evcc/cmd.Execute()
/home/runner/work/evcc/evcc/cmd/root.go:109 +0x20
main.main()
/home/runner/work/evcc/evcc/main.go:44 +0x3c
config:
- type: template
template: rct-power
usage: grid
host: 192.168.178.10
name: grid1
- type: template
template: rct-power
usage: pv
host: 192.168.178.10
name: pv2
- type: template
template: rct-power
usage: battery
host: 192.168.178.10
name: battery3
chargers:
- type: template
template: hardybarth-salia
host: 192.168.178.11
name: wallbox4
loadpoints:
- title: Garage
charger: wallbox4
mode: pv
phases: 3
mincurrent: 6
maxcurrent: 16
resetOnDisconnect: false
site:
title: Zuhause
meters:
grid: grid1
pv:
- pv2
battery:
- battery3
Pairing is technically only a process for the two devices to be allowed to talk to each other. The UX for any user without this technical understanding has no idea about this, its implications and results in a bad experience.
An Elli wallbox can be paired with another Elli wallbox. Then nothing happens afterwards. There is no warning that nothing will happen or can happen.
A lot of users tried to pair the Elli wallbox with an SMA Home Manager 2.0 as both say they support EEBUS. Pairing worked and some people thought now charging is controlled by available PV surplus energy. Even though technically this can not work. The Elli wallbox limited the charging speed to 6A per phase and never changed it. The Elli wallbox doesn't even show an information or error message that the other device doesn't support required features and falls back to this charging mode. It only shows an yellow LED instead of a green LED.
Even electrical engineers setting up the devices do not have such an understanding and will not have sufficient understanding. It is just too complex and the varieties will only increase with more devices supporting EEBUS in the future.
Solutions:
NodeManagementDetailedDiscoveryData
and NodeManagementUseCaseData
responses and presenting this in an end-user friendly waygo run cmd/hems/main.go 4715 <> keys/evse.crt keys/evse.key
2023-07-14 11:28:07 INFO Local SKI: 41c98b1bbe5fc7657ce311981951f12d304ab419
2023-07-14 11:28:07 DEBUG restarting mdns search
2023-07-14 11:28:07 DEBUG mdns: start search
2023-07-14 11:28:07 DEBUG starting websocket server on :4715
2023-07-14 11:28:07 DEBUG mdns: announce
2023-07-14 11:28:07 DEBUG mdns: using avahi
2023-07-14 11:28:07 DEBUG ski: <> name: Viessmann-7377953305981209 brand: model: typ: identifier: Viessmann-73779533
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x10 pc=0xa4613d]
goroutine 19 [running]:
github.com/enbility/eebus-go/service.(*mdns).resolveEntries(0xc0000b6660)
/root/eebus/eebus-go-dev/service/mdns.go:338 +0x31d
created by github.com/enbility/eebus-go/service.(*mdns).RegisterMdnsSearch
/root/eebus/eebus-go-dev/service/mdns.go:277 +0x265
exit status 2
Some devices, like the Elli Wallbox, come with a certificate that was signed by some random companies CA.
These CAs don't need to be generally trusted. In this way it would be great to externalize the TLSConfig of the server and client, so that people can handle these connections.
The current implementations requires lots of code duplications with minor adjustments which is error prone. Also it requires one hash key and does not allow different selectors, e.g. for electricalConnectionParameterDescriptionListData
, to be used.
We should find a way to implement this in a generic way and define selectors e.g. using tags and correlations between filter selectors and datatypes e.g. using mapping constructs as done with functions and data types.
SHIP Spec 13.4.4.1.3 defined for the state SME_HELLO_STATE_PENDING
the substates SME_HELLO_STATE_PENDING_INIT
, SME_HELLO_STATE_PENDING_LISTEN
, SME_HELLO_STATE_PENDING_TIMEOUT
.
The documentation says:
General information on the basic state "PENDING":
In this case, the use of Send-Prolongation-Request-Timer is required as soon as the "waiting" sub-
element from the communication partner is available, independent from the communication
partner's phase (except for "aborted").
As described above, an SME User with state "PENDING" requires the communication partner to also
announce its basic state "READY" in time. Thus, the Wait-For-Ready-Timer is required as long as this
information has not been received.
It is unclear to me on how this are actually used and thus should be exposed. The implementation right now doesn't actively use them, but can can react to them if the remote service uses them.
Any hints would be appreciated.
Instead of having an Interface with multiple methods required to be implemented to handle everything SHIP related, a specific message should be provided to a callback functions that hints e.g. on the data change. A set of public methods will be provided that can be called from the device implementation to trigger actions or grab data depending on the received message.
These two methods do not work as expected. Needs to be analyzed and then fixed or removed. Not sure if they are needed/useful anyway.
Especially the generic
feature is used for pretty much anything, even if there is a specific feature assigned to a function in a spec. E.g. the Elli EVSE uses the Generic
feature for FunctionTypeDeviceDiagnosisHeartbeatData
, even though the spec defines them in the context of the feature DeviceDiagnosis
.
Right now the FunctionTypeDeviceDiagnosisHeartbeatData
is added to Generic
, but this may be endless and would require adding more and updating this library just because some usages come up with more fancy ideas like this.
That's why it is probably better to be able to use any function with any feature. sigh
Checking if avahi is available can take about a second. If the setup process is run in a go-routine, this could cause device registrations and searches to come in before mDNS setup is finished and thus cause panics.
Instead incoming device registrations should be saved and search started once setup is done.
Instead of combining Zeroconf and avahi into one mDNS implementation, split them up in two and detect which one to use
Hey Andi,
thank you for the excellent work on making EEBUS available to the people :-)
I am succeeding already in using it for a HVAC Use case with my Heat Pump (and have already added a couple of features on my local branch to make this possible).
I am struggling to understand a part of the code base: How do I subscribe (as a client) to a remote data point?
I could only find the subscription implementation for when we are acting as a server... Could you point me to the right places, please?
Thanks again
Lukas
The ship handshake code is quite cumbersome and error prone, e.g. due to the need for locking. It seems that using a state machine with defined state changes should make the code easier to read, debug and also more failure proof.
These similar panics sometimes occur all the time, sometimes never:
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x4 pc=0xb89ac4]
goroutine 1 [running]:
github.com/enbility/eebus-go/features.(*DeviceDiagnosis).GetState(0x3896458)
/Users/andreaslinde/go/pkg/mod/github.com/enbility/[email protected]/features/devicediagnosis.go:57 +0x90
github.com/enbility/cemd/emobility.(*EMobilityImpl).EVCurrentChargeState(0x3160080)
/Users/andreaslinde/go/pkg/mod/github.com/enbility/[email protected]/emobility/public.go:21 +0x34
or
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x4 pc=0xb8d8cc]
goroutine 178 [running]:
github.com/enbility/eebus-go/features.(*Measurement).GetValuesPerPhaseForScope(0x574a300, {0x19b7bec, 0x9}, 0x574a2f8)
/Users/andreaslinde/go/pkg/mod/github.com/enbility/[email protected]/features/measurement.go:137 +0xbc
github.com/enbility/cemd/emobility.(*EMobilityImpl).EVCurrentsPerPhase(0x4844ec0)
/Users/andreaslinde/go/pkg/mod/github.com/enbility/[email protected]/emobility/public.go:133 +0x4c
The SHIP spec defines in 7.3.2 the optional type
field for the TXT record in the mDNS entry as String with device type
. Without further definition this field is not helpful by any means. Different EVSE vendors already use different values. E.g. Porsche uses EVSE
and Elli uses Wallbox
.
This way the field can not be used in a UI to show only potentially compatible devices for pairing.
As a suggestion, the SHIP model DeviceType
should be used. The example references such a value Dishwasher
, but the specification does not reference the data model.
The current non avahi mDNS library does not merge mDNS data packets and therefor EEBUS devices using the latest avahi version can not be used without avahi in this library, as the IP address does not get merged into the mDNS record.
Find a way to implement this in the used golang specific mDNS implementation or find another library that already provides this.
Source: evcc-io/evcc#6496
Stacktrace:
2023-02-27T15:10:54.854609155Z | stdout | /go/pkg/mod/github.com/enbility/[email protected]/spine/events.go:78 +0xa5
2023-02-27T15:10:54.854559764Z | stdout | created by github.com/enbility/eebus-go/spine.(*events).Publish
2023-02-27T15:10:54.854499288Z | stdout | /go/pkg/mod/github.com/enbility/[email protected]/emobility/events.go:39 +0x16a
2023-02-27T15:10:54.854416743Z | stdout | github.com/enbility/cemd/emobility.(*EMobilityImpl).HandleEvent(0xc000a6e100, {{0xc0006e67b0, 0x28}, 0x1, 0x2, 0xc001131bc0, 0x0, 0x0, {0x1ad6dc0, 0xc001430400}})
2023-02-27T15:10:54.854281886Z | stdout | goroutine 112049 [running]:
2023-02-27T15:10:54.854207103Z | stdout |
2023-02-27T15:10:54.854066831Z | stdout | [signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0xf7374a]
2023-02-27T15:10:54.853794559Z | stdout | panic: runtime error: invalid memory address or nil pointer dereference
2023-02-27T15:10:54.846665204Z | stdout | /go/pkg/mod/github.com/enbility/[email protected]/ship/websocket.go:66 +0xca
2023-02-27T15:10:54.846618665Z | stdout | created by github.com/enbility/eebus-go/ship.(*websocketConnection).run
2023-02-27T15:10:54.846570440Z | stdout | /go/pkg/mod/github.com/enbility/[email protected]/ship/websocket.go:140 +0x102
2023-02-27T15:10:54.846521349Z | stdout | github.com/enbility/eebus-go/ship.(*websocketConnection).readShipPump(0xc001131740)
2023-02-27T15:10:54.846471682Z | stdout | /go/pkg/mod/github.com/enbility/[email protected]/ship/connection.go:174 +0xa2
2023-02-27T15:10:54.846420826Z | stdout | github.com/enbility/eebus-go/ship.(*ShipConnection).HandleIncomingShipMessage(0xc0009ec680, {0xc0004ba380, 0x2f1, 0x380})
2023-02-27T15:10:54.846371406Z | stdout | /go/pkg/mod/github.com/enbility/[email protected]/spine/device_remote.go:75 +0xbd
2023-02-27T15:10:54.846318345Z | stdout | github.com/enbility/eebus-go/spine.(*DeviceRemoteImpl).HandleIncomingSpineMesssage(0xc001131bc0, {0xc000e50a00, 0x27d, 0x280})
2023-02-27T15:10:54.846257818Z | stdout | /go/pkg/mod/github.com/enbility/[email protected]/spine/device_local.go:216 +0x442
2023-02-27T15:10:54.846128692Z | stdout | github.com/enbility/eebus-go/spine.(*DeviceLocalImpl).ProcessCmd(0xc000e55080?, {{0xc0012b7d00, 0xc000b5eed0, 0xc000b5ef00, 0x0, 0xc0010cb4d8, 0x0, 0xc0012b7d30, 0x0, 0x0}, ...}, ...)
2023-02-27T15:10:54.846076681Z | stdout | /go/pkg/mod/github.com/enbility/[email protected]/spine/nodemanagement.go:62 +0x7ba
2023-02-27T15:10:54.846025120Z | stdout | github.com/enbility/eebus-go/spine.(*NodeManagementImpl).HandleMessage(0xc0009f63f0?, 0xc0012b7e00?)
2023-02-27T15:10:54.845913436Z | stdout | /go/pkg/mod/github.com/enbility/[email protected]/spine/nodemanagement_defaileddiscovery.go:247 +0x14a
2023-02-27T15:10:54.845865887Z | stdout | github.com/enbility/eebus-go/spine.(*NodeManagementImpl).handleMsgDetailedDiscoveryData(0x0?, 0x0?, 0x0?)
2023-02-27T15:10:54.845813752Z | stdout | /go/pkg/mod/github.com/enbility/[email protected]/spine/nodemanagement_defaileddiscovery.go:192 +0x2d0
2023-02-27T15:10:54.845761433Z | stdout | github.com/enbility/eebus-go/spine.(*NodeManagementImpl).processNotifyDetailedDiscoveryData(0xc000c68560, 0x0?, 0xc001430400)
2023-02-27T15:10:54.845694688Z | stdout | /go/pkg/mod/github.com/enbility/[email protected]/spine/subscription_manager.go:137 +0xba
2023-02-27T15:10:54.845613393Z | stdout | github.com/enbility/eebus-go/spine.(*SubscriptionManagerImpl).RemoveSubscriptionsForEntity(0xc000c4f420, 0x0)
2023-02-27T15:10:54.845404577Z | stdout | goroutine 110999 [running]:
2023-02-27T15:10:54.845365051Z | stdout |
2023-02-27T15:10:54.845267766Z | stdout | [signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0xdf891a]
2023-02-27T15:10:54.844686583Z | stdout | panic: runtime error: invalid memory address or nil pointer dereference
It looks like the remote device sent a DetailedDiscovery message to remove a device entity, which does not exist.
Split the code in this repository into 3 independent repositories:
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.