Skip to content

Software Architecture

Introduction

Document Purpose

The purpose of this document is to document the architecture of the tic4eebus application.

Application Scope

The tic4eebus application allows limiting an electric vehicle (EV) charging station based on the available energy provided by a Linky meter.

The software implements the OPEV use case of the EEBUS standard by acting as an energy management system (Energy Guard) to control the EV charging station (CEM) based on data read from the Linky meter (Smart Meter).

Overview diagram

Architecture Overview

General Description

Use Case

The tic4eebus application interacts with five actors:

  • The Clock triggering energy management system functionalities
  • The File System storing application data
  • The Database providing access to application data
  • The TIC2WebSocket API providing metrological data from the Linky meter
  • The EEBUS Stack managing access to the charging station and electric vehicle

The Clock actor allows:

  • Triggering the available energy adjustment

The File System actor allows:

  • Storing application business data

The Database actor allows:

  • Accessing application business data (visualization, processing, etc.)

The TIC2WebSocket API actor allows:

  • Receiving Linky meter data

The EEBUS Stack actor allows:

  • Limiting electric vehicle charging
General descriptionGeneral descriptiontic4eebusReceive Linky meter dataLimit electric vehicle chargingAdjust available energySave business dataClockFile SystemDatabaseTIC2WebSocket APIEEBUS Stackincludeincludeinclude
General descriptionGeneral descriptiontic4eebusReceive Linky meter dataLimit electric vehicle chargingAdjust available energySave business dataClockFile SystemDatabaseTIC2WebSocket APIEEBUS Stackincludeincludeinclude

Main Components

The tic4eebus application contains:

  • The main component hnadling program startup and shutdown
  • The config component loading all application configurations
  • The ems component containing the application's energy management system
  • The ems.data component managing the application's data model
  • The linkymeter component receiving Linky meter data
  • The evse component providing access to the charging station and electric vehicle

It uses two main external dependencies:

  • The TIC2WebSocket component receiving frames from the meter customer interface (TIC)
  • The eebus-go component enabling EEBUS communication with equipment (charging station and vehicle)
Main componentsMain componentstic4eebusemsmainconfiglinkymeterevseCSVInfluxDbdataTIC2WebSocketeebus-gouseuseusesavesaveuseuseuseuseuse
Main componentsMain componentstic4eebusemsmainconfiglinkymeterevseCSVInfluxDbdataTIC2WebSocketeebus-gouseuseusesavesaveuseuseuseuseuse

Detailed Architecture View

main component

Description

The main component is responsible for launching and stopping the program.

At startup, it manages:

  • Command line interpretation (function main.parseCommandLine)
  • Configuration loading (function config.LoadConfig)
  • Logger initialization (function main.initLogger)
  • Energy management system startup (method Start of class ems.EnergyGuard)

At shutdown, it manages:

  • Energy management system shutdown (method Stop of class ems.EnergyGuard)

Dependencies

Internal Dependencies

The main module uses 2 internal dependencies:

  1. The config module
  2. The ems module
External Dependencies

The main module uses 2 external dependencies:

  1. The file-rotatelogs package for log rotation
  2. The logrus package for log management

Class Diagram

The following class diagram describes the main component and its internal dependencies:

main component classesmain component classesmainconfigemsInputsconfigFilePath stringshowVersion boolmaininit()parseCommandLine() (inputs Inputs)initLogger(logConfig config.LogConfig)start()stop()LogConfigConfigLog LogConfigconfigLoadConfig(configFilePath string) (Config, error)energyguardNewEnergyGuard(config Config) *EnergyGuardEnergyGuardStart()Stop()
main component classesmain component classesmainconfigemsInputsconfigFilePath stringshowVersion boolmaininit()parseCommandLine() (inputs Inputs)initLogger(logConfig config.LogConfig)start()stop()LogConfigConfigLog LogConfigconfigLoadConfig(configFilePath string) (Config, error)energyguardNewEnergyGuard(config Config) *EnergyGuardEnergyGuardStart()Stop()

config component

Description

The config component is responsible for loading all application configurations.

It uses:

  • The configuration for the overload protection algorithm implementing the OPEV use case of the EEBUS standard (class config.OverloadProtectionConfig)
  • The electric vehicle data access configuration (class config.VehicleConfig)
  • The charging station data access configuration (class config.WallboxConfig)
  • The application logging configuration (class config.LogConfig)
  • The application data model persistence configuration (class config.DataModelConfig)
  • The Linky meter TIC access configuration (class config.TeleInformationClientConfig)
  • The EEBUS communication configuration (class config.EEBUSConfig)

Dependencies

Internal Dependencies

The config module has no internal dependencies.

External Dependencies

The config module uses 2 external dependencies:

  1. The logrus package to use the desired logging level
  2. The yaml package to decode YAML configuration file

Class Diagram

The following class diagram describes the config component and its internal dependencies:

config component classesconfig component classesconfigCurrentLimitConfigValueInAmps float64LockDelayInSeconds float64FileRotationConfigPeriodInHours intPeriodCount intPeriodPattern stringCsvConfigFilePath stringRotation FileRotationConfigInfluxDbConfigBucket stringOrg stringToken stringIpAddress stringTcpPort intTic2WebsocketConfigIpAddress stringTcpPort intTicIdentifierConfigSerialNumber stringOverloadProtectionConfigEnable boolRunningPeriodInSeconds intCurrentLimit CurrentLimitConfigVehicleConfigUpdateDataPeriodInSeconds intDataPersistent boolWallboxConfigUpdateDataPeriodInSeconds intDataPersistent boolLogConfigLevel log.LevelFilePath stringRotation FileRotationConfigDataModelConfigCsv *CsvConfigInfluxDb *InfluxDbConfigTeleInformationClientConfigTic2Websocket Tic2WebsocketConfigTicIdentifier TicIdentifierConfigEebusConfigServerPort intRemoteSki stringCertificateFilePath stringPrivateKeyFilePath stringVendorCode stringDeviceBrand stringDeviceModel stringSerialNumber stringHeartbeatTimeoutInSeconds intConfigOverloadProtection OverloadProtectionConfigVehicle VehicleConfigWallbox WallboxConfigLog LogConfigDataModel DataModelConfigTeleInformationClient TeleInformationClientConfigEebus EebusConfigconfigLoadConfig(configFilePath string) (Config, error)
config component classesconfig component classesconfigCurrentLimitConfigValueInAmps float64LockDelayInSeconds float64FileRotationConfigPeriodInHours intPeriodCount intPeriodPattern stringCsvConfigFilePath stringRotation FileRotationConfigInfluxDbConfigBucket stringOrg stringToken stringIpAddress stringTcpPort intTic2WebsocketConfigIpAddress stringTcpPort intTicIdentifierConfigSerialNumber stringOverloadProtectionConfigEnable boolRunningPeriodInSeconds intCurrentLimit CurrentLimitConfigVehicleConfigUpdateDataPeriodInSeconds intDataPersistent boolWallboxConfigUpdateDataPeriodInSeconds intDataPersistent boolLogConfigLevel log.LevelFilePath stringRotation FileRotationConfigDataModelConfigCsv *CsvConfigInfluxDb *InfluxDbConfigTeleInformationClientConfigTic2Websocket Tic2WebsocketConfigTicIdentifier TicIdentifierConfigEebusConfigServerPort intRemoteSki stringCertificateFilePath stringPrivateKeyFilePath stringVendorCode stringDeviceBrand stringDeviceModel stringSerialNumber stringHeartbeatTimeoutInSeconds intConfigOverloadProtection OverloadProtectionConfigVehicle VehicleConfigWallbox WallboxConfigLog LogConfigDataModel DataModelConfigTeleInformationClient TeleInformationClientConfigEebus EebusConfigconfigLoadConfig(configFilePath string) (Config, error)

linkymeter component

Description

The linkymeter component is responsible for accessing Linky meter data.

It manages:

  • Access to the interface (websocket server) provided by the TIC2WebSocket application (class linkymeter.TIC2WebSocketClient)
  • Retrieving meter data from messages sent by TIC2WebSocket (function linkymeter.ComputeMeterData)

Dependencies

Internal Dependencies

The linkymeter module uses no internal dependencies.

External Dependencies

The linkymeter module uses 4 external dependencies:

  1. The uuid package for generating unique identifiers used for meter subscription with the TIC2WebSocket application
  2. The websocket package for managing the websocket client accessing the TIC2WebSocket application
  3. The mapstructure package for converting dictionaries to data structures
  4. The logrus package for application logging

Class Diagram

The following class diagram describes the linkymeter component and its internal dependencies:

linkymeter component classeslinkymeter component classeslinkymeterOnTicDataOnTicData(ticData TicData)OnTicErrorOnTicError(ticError TicError)OnTicAbnormalClosureOnTicAbnormalClosure()TicDataMode stringCaptureDateTime stringIdentifier TicIdentifierContent map[string]stringTicErrorErrorCode intErrorMessage stringIdentifier TicIdentifierTicIdentifierSerialNumber stringPortName stringPortId stringTic2WebsocketClientConnect(host string) errorGetAvailableTics() ([]TicIdentifier,error)SubscribeTic(onData OnTicData,onError OnTicError,onAbnormalClosure OnTicAbnormalClosure,identifier TicIdentifier) (string, error)UnsubscribeTic(subscriptionId string) errorClose() errorticNewTic2WebsocketClient() *Tic2WebsocketClientMeterDataSerialNumber stringDateTime stringBreakerOpened boolPhaseCount intOverloadPowerLimit intOverloadPowerLimitPerPhase []float64RmsVoltagePerPhase []intRmsCurrentPerPhase []float64ApparentImportPower intApparentImportPowerPerPhase []intAvailableCurrentPerPhase []float64dataComputeMeterData(ticContent map[string]string) MeterData
linkymeter component classeslinkymeter component classeslinkymeterOnTicDataOnTicData(ticData TicData)OnTicErrorOnTicError(ticError TicError)OnTicAbnormalClosureOnTicAbnormalClosure()TicDataMode stringCaptureDateTime stringIdentifier TicIdentifierContent map[string]stringTicErrorErrorCode intErrorMessage stringIdentifier TicIdentifierTicIdentifierSerialNumber stringPortName stringPortId stringTic2WebsocketClientConnect(host string) errorGetAvailableTics() ([]TicIdentifier,error)SubscribeTic(onData OnTicData,onError OnTicError,onAbnormalClosure OnTicAbnormalClosure,identifier TicIdentifier) (string, error)UnsubscribeTic(subscriptionId string) errorClose() errorticNewTic2WebsocketClient() *Tic2WebsocketClientMeterDataSerialNumber stringDateTime stringBreakerOpened boolPhaseCount intOverloadPowerLimit intOverloadPowerLimitPerPhase []float64RmsVoltagePerPhase []intRmsCurrentPerPhase []float64ApparentImportPower intApparentImportPowerPerPhase []intAvailableCurrentPerPhase []float64dataComputeMeterData(ticContent map[string]string) MeterData

evse component

Description

The evse component is responsible for reading charging station and electric vehicle data.

It uses:

  • The charging station configuration (class config.WallboxConfig)
  • The electric vehicle configuration (class config.VehicleConfig)
  • The charging station component handling EEBUS messages related to the station (class evse.Wallbox)
  • The electric vehicle component handling EEBUS messages related to the vehicle (class evse.Vehicle)

Dependencies

Internal Dependencies

The evse module uses 1 internal dependency:

  • The config module
External Dependencies

The evse module uses 5 external dependencies:

  1. The eebus-go package for the EEBUS service and EEBUS use cases (EVSECC, EVCC, EVCEM, OPEV)
  2. The spine-go package for accessing EEBUS equipment and entities for information retrieval (station operational state, EV communication standard, EV limitation result)
  3. The gocron package for launching periodic tasks to read EV and charging station information
  4. The uuid package for unique subscription identifier to EV and charging station information
  5. The logrus package for application logging concerning the EV and charging station

Class Diagram

The following class diagram describes the synchronizer component and its internal dependencies:

evse component classesevse component classesconfigevseWallboxConfigUpdateDataPeriodInSeconds intDataPersistent boolVehicleConfigUpdateDataPeriodInSeconds intDataPersistent boolonWallboxDataonWallboxData(wallboxData map[string]interface{})onWallboxConnectedonWallboxConnected()onWallboxDisconnectedonWallboxDisconnected()onWallboxSupportedonWallboxSupported()onVehicleDataonVehicleData(vehicleData map[string]interface{})onVehicleConnectedonVehicleConnected()onVehicleDisconnectedonVehicleDisconnected()onVehicleOpevSupportedonVehicleOpevSupported()WallboxEnableRemoteConnection()DisableRemoteConnection()SubscribeData(onData onWallboxData,onConnected onWallboxConnected,onDisconnected onWallboxDisconnected,onSupported onWallboxSupported) (id string)UnsubscribeData(id string) errorVehicleEnableRemoteConnection()DisableRemoteConnection()SubscribeData(onData onVehicleData,onConnected onVehicleConnected,onDisconnected onVehicleDisconnected,onOPEVSupported onVehicleOpevSupported) (id string)UnsubscribeData(id string) errorwallboxNewWallbox(service api.ServiceInterface,localEntity spineapi.EntityLocalInterface,config config.WallboxConfig) *WallboxvehicleNewVehicle(service api.ServiceInterface,localEntity spineapi.EntityLocalInterface,config config.VehicleConfig) *Vehicle
evse component classesevse component classesconfigevseWallboxConfigUpdateDataPeriodInSeconds intDataPersistent boolVehicleConfigUpdateDataPeriodInSeconds intDataPersistent boolonWallboxDataonWallboxData(wallboxData map[string]interface{})onWallboxConnectedonWallboxConnected()onWallboxDisconnectedonWallboxDisconnected()onWallboxSupportedonWallboxSupported()onVehicleDataonVehicleData(vehicleData map[string]interface{})onVehicleConnectedonVehicleConnected()onVehicleDisconnectedonVehicleDisconnected()onVehicleOpevSupportedonVehicleOpevSupported()WallboxEnableRemoteConnection()DisableRemoteConnection()SubscribeData(onData onWallboxData,onConnected onWallboxConnected,onDisconnected onWallboxDisconnected,onSupported onWallboxSupported) (id string)UnsubscribeData(id string) errorVehicleEnableRemoteConnection()DisableRemoteConnection()SubscribeData(onData onVehicleData,onConnected onVehicleConnected,onDisconnected onVehicleDisconnected,onOPEVSupported onVehicleOpevSupported) (id string)UnsubscribeData(id string) errorwallboxNewWallbox(service api.ServiceInterface,localEntity spineapi.EntityLocalInterface,config config.WallboxConfig) *WallboxvehicleNewVehicle(service api.ServiceInterface,localEntity spineapi.EntityLocalInterface,config config.VehicleConfig) *Vehicle

ems component

Description

The ems component implements the energy management system called Energy Guard in the EEBUS standard.

It uses:

  • The global application configuration (class config.Config)
  • The TIC2WebSocket client to receive Linky meter data (class linkymeter.Tic2WebSocketClient)
  • The conversion of raw Linky meter data to business data (function linkymeter.ComputeMeterData)
  • Application data persistence (class ems.data.DataSynchronizer)
  • Electric vehicle data retrieval (class evse.Vehicle)
  • Charging station data retrieval (class evse.Wallbox)

Dependencies

Internal Dependencies

The ems component uses 4 internal dependencies:

  1. The config package
  2. The linkymeter package
  3. The evse package
  4. The ems.data package
External Dependencies

The ems component uses 7 external dependencies:

  1. The eebus-go package for EEBUS service management and energy management system diagnostics
  2. The ship-go package for remote EEBUS service definition and remote connection state
  3. The spine-go package for local EEBUS entity interface and EV current limit setpoint write result information
  4. The gocron package for launching the periodic EV charge limitation regulation task
  5. The cmp package to detect changes in EV and charging station information
  6. The uuid package for unique subscription identifier to energy management system information
  7. The logrus package for application logging concerning the energy management system

Class Diagram

The following class diagram describes the ems component and its internal dependencies:

Classes of ems componentClasses of ems componentemsdataconfigevselinkymeteronDataonData(data data.DataModel)EnergyGuard Start()Stop() Energy manager startup SubscribeData(onData onData) (id string)UnsubscribeData(id string) error Energy manager data subscription Trace(args ...interface{})Tracef(format string, args ...interface{})Debug(args ...interface{})Debugf(format string, args ...interface{})Info(args ...interface{})Infof(format string, args ...interface{})Error(args ...interface{})Errorf(format string, args ...interface{}) Logging interface RemoteSKIConnected(service api.ServiceInterface, ski string)RemoteSKIDisconnected(service api.ServiceInterface, ski string)VisibleRemoteServicesUpdated(service api.ServiceInterface, entries []shipapi.RemoteService)ServiceShipIDUpdate(ski string, shipdID string)ServicePairingDetailUpdate(ski string, detail *shipapi.ConnectionStateDetail)AllowWaitingForTrust(ski string) boolEEBUS service interfaceenergyguardNewEnergyGuard(config.Config) (*EnergyGuard)DataSynchronizerDataModelOverloadProtectionDataDiagnosisDataDataModelConfigConfigVehicleWallboxMeterDataTic2WebSocketClient
Classes of ems componentClasses of ems componentemsdataconfigevselinkymeteronDataonData(data data.DataModel)EnergyGuard Start()Stop() Energy manager startup SubscribeData(onData onData) (id string)UnsubscribeData(id string) error Energy manager data subscription Trace(args ...interface{})Tracef(format string, args ...interface{})Debug(args ...interface{})Debugf(format string, args ...interface{})Info(args ...interface{})Infof(format string, args ...interface{})Error(args ...interface{})Errorf(format string, args ...interface{}) Logging interface RemoteSKIConnected(service api.ServiceInterface, ski string)RemoteSKIDisconnected(service api.ServiceInterface, ski string)VisibleRemoteServicesUpdated(service api.ServiceInterface, entries []shipapi.RemoteService)ServiceShipIDUpdate(ski string, shipdID string)ServicePairingDetailUpdate(ski string, detail *shipapi.ConnectionStateDetail)AllowWaitingForTrust(ski string) boolEEBUS service interfaceenergyguardNewEnergyGuard(config.Config) (*EnergyGuard)DataSynchronizerDataModelOverloadProtectionDataDiagnosisDataDataModelConfigConfigVehicleWallboxMeterDataTic2WebSocketClient

ems.data component

Description

The ems.data component saves the application's data model.

It uses:

  • The application data model configuration (class config.DataModelConfig)
  • The application data model (class ems.data.DataModel)
  • The data model management interface (class ems.data.DataSynchronizer)
  • The data model CSV file persistence interface (class ems.data.CsvWriter)
  • The data model InfluxDb database persistence interface (class ems.data.InfluxDbWriter)

Dependencies

Internal Dependencies

The ems component uses 3 internal dependencies:

  1. The config package
  2. The linkymeter package
  3. The evse package
External Dependencies

The ems component uses 6 external dependencies:

  1. The eebus-go package for data types related to the electric vehicle and charging station
  2. The spine-go package for data types related to diagnostics, EV charge limitation, and charging station operational state
  3. The influxdb-client-go package for InfluxDb database access
  4. The cmp package to compare new EV and charging station data with current data
  5. The file-rotatelogs package for CSV file rotation
  6. The logrus package for application logging concerning the data model

Class Diagram

The following class diagram describes the ems.data component and its internal dependencies:

ems.data component classesems.data component classesemsdatalinkymeterconfigevseDataWriterSave(model DataModel)CsvWriterSave(model DataModel)InfluxDbWriterSave(model DataModel)synchronizerNewDataSynchronizer(dataModelConfig config.DataModelConfig) *DataSynchronizerDataSynchronizer  IsConnected() (isConnected bool)SetIsConnected(isConnected bool) (hasChanged bool)HasMeterData() (hasMeterData bool)SetHasMeterData(hasMeterData bool) (hasChanged bool)IsOpevSupported() (isOpevSupported bool)SetIsOpevSupported(isOpevSupported bool) (hasChanged bool) Connections GetVehicle() (vehicle map[string]interface{})SetVehicle(vehicle map[string]interface{}) (hasChanged bool)GetWallbox() (wallbox map[string]interface{})SetWallbox(wallbox map[string]interface{}) (hasChanged bool)GetMeter() (meter linkymeter.MeterData)SetMeter(meter linkymeter.MeterData) (hasChanged bool) Data GetMeterMinAvailableCurrent() (minAvailableCurrent float64)DisableOverloadProtectionActive()GetOverloadProtectionValue() (limitValue float64)SetOverloadProtectionValue(limitValue float64)SetOverloadProtectionResult(result model.ResultDataType) (hasChanged bool)SetOverloadProtectionLockStart(lockStart time.Time) (hasChanged bool)GetOverloadProtectionLockDuration() (lockDuration time.Duration)SetOverloadProtectionLockActive(lockActive bool) (hasChanged bool) Overload protection GetDiagnosisState() *model.DeviceDiagnosisStateDataTypeSetDiagnosis(operatingState model.DeviceDiagnosisOperatingStateType, lastErrorCode model.LastErrorCodeType) (hasChanged bool) Diagnostics GetModel() (model DataModel)Print() ModelOverloadProtectionDataActive boolValue float64Start time.TimeResultCode model.ErrorNumberTypeResultDescription model.DescriptionTypeLockActive boolLockStart time.TimeDiagnosisDataOperatingState model.DeviceDiagnosisOperatingStateTypeLastErrorCode model.LastErrorCodeTypeDataModelIsConnected boolHasMeterData boolIsOpevSupported boolVehicle map[string]interface{}Wallbox map[string]interface{}Meter linkymeter.MeterDataOverloadProtection OverloadProtectionDataDiagnosis DiagnosisDataMeterDataDataModelConfigvehiclewallbox
ems.data component classesems.data component classesemsdatalinkymeterconfigevseDataWriterSave(model DataModel)CsvWriterSave(model DataModel)InfluxDbWriterSave(model DataModel)synchronizerNewDataSynchronizer(dataModelConfig config.DataModelConfig) *DataSynchronizerDataSynchronizer  IsConnected() (isConnected bool)SetIsConnected(isConnected bool) (hasChanged bool)HasMeterData() (hasMeterData bool)SetHasMeterData(hasMeterData bool) (hasChanged bool)IsOpevSupported() (isOpevSupported bool)SetIsOpevSupported(isOpevSupported bool) (hasChanged bool) Connections GetVehicle() (vehicle map[string]interface{})SetVehicle(vehicle map[string]interface{}) (hasChanged bool)GetWallbox() (wallbox map[string]interface{})SetWallbox(wallbox map[string]interface{}) (hasChanged bool)GetMeter() (meter linkymeter.MeterData)SetMeter(meter linkymeter.MeterData) (hasChanged bool) Data GetMeterMinAvailableCurrent() (minAvailableCurrent float64)DisableOverloadProtectionActive()GetOverloadProtectionValue() (limitValue float64)SetOverloadProtectionValue(limitValue float64)SetOverloadProtectionResult(result model.ResultDataType) (hasChanged bool)SetOverloadProtectionLockStart(lockStart time.Time) (hasChanged bool)GetOverloadProtectionLockDuration() (lockDuration time.Duration)SetOverloadProtectionLockActive(lockActive bool) (hasChanged bool) Overload protection GetDiagnosisState() *model.DeviceDiagnosisStateDataTypeSetDiagnosis(operatingState model.DeviceDiagnosisOperatingStateType, lastErrorCode model.LastErrorCodeType) (hasChanged bool) Diagnostics GetModel() (model DataModel)Print() ModelOverloadProtectionDataActive boolValue float64Start time.TimeResultCode model.ErrorNumberTypeResultDescription model.DescriptionTypeLockActive boolLockStart time.TimeDiagnosisDataOperatingState model.DeviceDiagnosisOperatingStateTypeLastErrorCode model.LastErrorCodeTypeDataModelIsConnected boolHasMeterData boolIsOpevSupported boolVehicle map[string]interface{}Wallbox map[string]interface{}Meter linkymeter.MeterDataOverloadProtection OverloadProtectionDataDiagnosis DiagnosisDataMeterDataDataModelConfigvehiclewallbox

Interaction Models

Sequence Diagrams

The sequence diagrams illustrate interactions between components concerning:

  • Application startup
  • Application shutdown
  • Energy management system startup
  • Energy management system shutdown
  • Energy management system periodic regulation

Application Startup

Application startup is described by the following sequence diagram:

Application startupApplication startupmainmainmainmainmainconfigEnergyGuardSystemmainconfigInputsEnergyGuardSystemSystemmainmainconfigconfigInputsEnergyGuardmainmainmainmainmainconfigEnergyGuardmain()init()Command lineparseCommandLine()newInputsupdate input data with command lineinput dataConfigurationLoadConfig()configurationLogginginitLogger()logger initializedEnergy management systemnewEnergyGuardcreation with configuration parametersapplication initializestart()Start()energy management system startedapplication started
Application startupApplication startupmainmainmainmainmainconfigEnergyGuardSystemmainconfigInputsEnergyGuardSystemSystemmainmainconfigconfigInputsEnergyGuardmainmainmainmainmainconfigEnergyGuardmain()init()Command lineparseCommandLine()newInputsupdate input data with command lineinput dataConfigurationLoadConfig()configurationLogginginitLogger()logger initializedEnergy management systemnewEnergyGuardcreation with configuration parametersapplication initializestart()Start()energy management system startedapplication started

Application Shutdown

Application shutdown is described by the following sequence diagram :

Application shutdownApplication shutdownmainmainEnergyGuardSystemmainEnergyGuardSystemSystemmainmainEnergyGuardEnergyGuardmainmainEnergyGuardSIGSTOP [CTRL + C]stop()Energy management systemStop()energy management stoppedapplication stoppedexit()
Application shutdownApplication shutdownmainmainEnergyGuardSystemmainEnergyGuardSystemSystemmainmainEnergyGuardEnergyGuardmainmainEnergyGuardSIGSTOP [CTRL + C]stop()Energy management systemStop()energy management stoppedapplication stoppedexit()

Energy Management System Startup

Energy management system startup is described by the following sequence diagram :

Energy management system startupEnergy management system startupEnergyGuardTic2WebSocketClientTic2WebSocketClientTic2WebSocketClientEEBUS ServiceEEBUS ServiceSchedulerSchedulerSchedulerTICIdentifierTICIdentifiermainEnergyGuardTic2WebSocketClientEEBUS ServiceSchedulerTICIdentifiermainmainEnergyGuardEnergyGuardTic2WebSocketClientTic2WebSocketClientEEBUS ServiceEEBUS ServiceSchedulerSchedulerTICIdentifierEnergyGuardTic2WebSocketClientTic2WebSocketClientTic2WebSocketClientEEBUS ServiceEEBUS ServiceSchedulerSchedulerSchedulerTICIdentifierTICIdentifierStart()Start receiving data from Linky meterConnect(ticServiceHost)connected with Tic2WebSocketGetAvailableTics()available TIC streamsalt[Meter serial number exists in config]loop[available TIC streams]alt[TIC stream meter serial number matches config]newTICIdentifierupdate serial numberSerial number updated[Meter serial number empty in config]loop[available TIC streams]alt[TIC stream meter serial number exists]newTICIdentifierupdate serial numberSerial number updatedSubscribeTIC(onData,onError,ticIdentifier)meter data subscription successfulStart EEBUS communicationRegisterRemoteSKI(config.EEBUS.RemoteSKI)Charging station SKI identifier registeredStart()EEBUS service startedStart overload protectionEvery(config.OverloadProtection.RunningPeriodInSeconds)Overload protection execution period definedSeconds()Overload protection execution period converted to secondsDo(runOverloadProtection)Overload protection function configuredenergy management system started
Energy management system startupEnergy management system startupEnergyGuardTic2WebSocketClientTic2WebSocketClientTic2WebSocketClientEEBUS ServiceEEBUS ServiceSchedulerSchedulerSchedulerTICIdentifierTICIdentifiermainEnergyGuardTic2WebSocketClientEEBUS ServiceSchedulerTICIdentifiermainmainEnergyGuardEnergyGuardTic2WebSocketClientTic2WebSocketClientEEBUS ServiceEEBUS ServiceSchedulerSchedulerTICIdentifierEnergyGuardTic2WebSocketClientTic2WebSocketClientTic2WebSocketClientEEBUS ServiceEEBUS ServiceSchedulerSchedulerSchedulerTICIdentifierTICIdentifierStart()Start receiving data from Linky meterConnect(ticServiceHost)connected with Tic2WebSocketGetAvailableTics()available TIC streamsalt[Meter serial number exists in config]loop[available TIC streams]alt[TIC stream meter serial number matches config]newTICIdentifierupdate serial numberSerial number updated[Meter serial number empty in config]loop[available TIC streams]alt[TIC stream meter serial number exists]newTICIdentifierupdate serial numberSerial number updatedSubscribeTIC(onData,onError,ticIdentifier)meter data subscription successfulStart EEBUS communicationRegisterRemoteSKI(config.EEBUS.RemoteSKI)Charging station SKI identifier registeredStart()EEBUS service startedStart overload protectionEvery(config.OverloadProtection.RunningPeriodInSeconds)Overload protection execution period definedSeconds()Overload protection execution period converted to secondsDo(runOverloadProtection)Overload protection function configuredenergy management system started

Energy Management System Shutdown

Energy manager shutdown is described by the following sequence diagram :

Energy management system shutdownEnergy management system shutdownEnergyGuardTic2WebSocketClientTic2WebSocketClientEEBUS ServiceVehicleWallboxSchedulermainEnergyGuardTic2WebSocketClientEEBUS ServiceVehicleWallboxSchedulermainmainEnergyGuardEnergyGuardTic2WebSocketClientTic2WebSocketClientEEBUS ServiceEEBUS ServiceVehicleVehicleWallboxWallboxSchedulerSchedulerEnergyGuardTic2WebSocketClientTic2WebSocketClientEEBUS ServiceVehicleWallboxSchedulerStop()Stop overload protectionStop()Overload protection execution scheduler stoppedStop EEBUS communicationShutdown()EEBUS service stoppedDisableRemoteConnection()Vehicle data update disabledDisableRemoteConnection()Charging station data update disabledStop receiving data from Linky meterUnsubscribe(ticServiceSubcriptionId)Meter data subscription endedClose()Connection with Tic2WebSocket closedEnergy management system stopped
Energy management system shutdownEnergy management system shutdownEnergyGuardTic2WebSocketClientTic2WebSocketClientEEBUS ServiceVehicleWallboxSchedulermainEnergyGuardTic2WebSocketClientEEBUS ServiceVehicleWallboxSchedulermainmainEnergyGuardEnergyGuardTic2WebSocketClientTic2WebSocketClientEEBUS ServiceEEBUS ServiceVehicleVehicleWallboxWallboxSchedulerSchedulerEnergyGuardTic2WebSocketClientTic2WebSocketClientEEBUS ServiceVehicleWallboxSchedulerStop()Stop overload protectionStop()Overload protection execution scheduler stoppedStop EEBUS communicationShutdown()EEBUS service stoppedDisableRemoteConnection()Vehicle data update disabledDisableRemoteConnection()Charging station data update disabledStop receiving data from Linky meterUnsubscribe(ticServiceSubcriptionId)Meter data subscription endedClose()Connection with Tic2WebSocket closedEnergy management system stopped

Energy Managerment System Periodic Regulation

Energy management system periodic regulation is explained by the flowchart below :

Energy management system periodic regulation flowchartEnergy management system periodic regulation flowchartCalculate charge limitation lock durationLock duration elapsed?yesnoCalculate minimum available current across all phasesOverload protection necessary?yesnoDecrease vehicle maximum charging current valueIncrease vehicle maximum charging current valueUpdate lock parametersMaintain vehicle maximum charging current valueApply vehicle maximum charging current valueyesMeter data available?
Energy management system periodic regulation flowchartEnergy management system periodic regulation flowchartCalculate charge limitation lock durationLock duration elapsed?yesnoCalculate minimum available current across all phasesOverload protection necessary?yesnoDecrease vehicle maximum charging current valueIncrease vehicle maximum charging current valueUpdate lock parametersMaintain vehicle maximum charging current valueApply vehicle maximum charging current valueyesMeter data available?

Energy management system periodic regulation is described in detail by the following sequence diagram :

Energy management system periodic regulationEnergy management system periodic regulationEnergyGuardEnergyGuardEnergyGuardEnergyGuardEnergyGuardDataSynchronizerDataSynchronizerDataSynchronizerDataSynchronizerDataSynchronizerDataSynchronizerDataSynchronizerDataSynchronizerVehicleVehicleVehicleSchedulerEnergyGuardDataSynchronizerVehicleSchedulerSchedulerEnergyGuardEnergyGuardDataSynchronizerDataSynchronizerVehicleVehicleEnergyGuardEnergyGuardEnergyGuardEnergyGuardEnergyGuardDataSynchronizerDataSynchronizerDataSynchronizerDataSynchronizerDataSynchronizerDataSynchronizerDataSynchronizerDataSynchronizerVehicleVehicleVehiclerunOverloadProtection()IsConnected()EEBUS connection stateIsConnected()EV connection stateGetVehicleCurrentLimits()EV current limitations (min, max)HasMeterData()Connection state with Linky meteralt[Linky meter data NOT available]currentLimit = minCurrentLimitUpdate vehicle charge limitation to apply[Linky meter data available]GetOverloadProtectionValue()Vehicle maximum charging currentGetOverloadProtectionLockDuration()Charge limitation lock durationalt[Lock duration elapsed]SetOverloadProtectionActive(false)Update vehicle charge limitation activation stateGetMeterMinAvailableCurrent()Minimum available current across all phasesalt[Overload protection necessary]currentLimit = loadControlLimit - abs(minAvailableCurrent)Decrease vehicle maximum charging current value[Overload protection NOT necessary]currentLimit = loadControlLimit + abs(minAvailableCurrent)Increase vehicle maximum charging current valueSetOverloadProtectionLockStart(now)Update charge limitation lock start timestamp[Lock duration NOT elapsed]currentLimit = loadControlLimitMaintain vehicle maximum charging current valueWriteLoadControlLimits(currentLimit)Vehicle maximum charging current appliedSetOverloadProtectionValue(currentLimit)Update vehicle maximum charging current valueOverload protection executed
Energy management system periodic regulationEnergy management system periodic regulationEnergyGuardEnergyGuardEnergyGuardEnergyGuardEnergyGuardDataSynchronizerDataSynchronizerDataSynchronizerDataSynchronizerDataSynchronizerDataSynchronizerDataSynchronizerDataSynchronizerVehicleVehicleVehicleSchedulerEnergyGuardDataSynchronizerVehicleSchedulerSchedulerEnergyGuardEnergyGuardDataSynchronizerDataSynchronizerVehicleVehicleEnergyGuardEnergyGuardEnergyGuardEnergyGuardEnergyGuardDataSynchronizerDataSynchronizerDataSynchronizerDataSynchronizerDataSynchronizerDataSynchronizerDataSynchronizerDataSynchronizerVehicleVehicleVehiclerunOverloadProtection()IsConnected()EEBUS connection stateIsConnected()EV connection stateGetVehicleCurrentLimits()EV current limitations (min, max)HasMeterData()Connection state with Linky meteralt[Linky meter data NOT available]currentLimit = minCurrentLimitUpdate vehicle charge limitation to apply[Linky meter data available]GetOverloadProtectionValue()Vehicle maximum charging currentGetOverloadProtectionLockDuration()Charge limitation lock durationalt[Lock duration elapsed]SetOverloadProtectionActive(false)Update vehicle charge limitation activation stateGetMeterMinAvailableCurrent()Minimum available current across all phasesalt[Overload protection necessary]currentLimit = loadControlLimit - abs(minAvailableCurrent)Decrease vehicle maximum charging current value[Overload protection NOT necessary]currentLimit = loadControlLimit + abs(minAvailableCurrent)Increase vehicle maximum charging current valueSetOverloadProtectionLockStart(now)Update charge limitation lock start timestamp[Lock duration NOT elapsed]currentLimit = loadControlLimitMaintain vehicle maximum charging current valueWriteLoadControlLimits(currentLimit)Vehicle maximum charging current appliedSetOverloadProtectionValue(currentLimit)Update vehicle maximum charging current valueOverload protection executed

Technical Infrastructure

Programming Languages

The tic4eebus project is entirely developed in Go.

It is compatible with Go versions 1.23 and later.

Database

The database used to access the application's data model is an InfluxDb database.

Its structure consists of only one bucket (named demo-bucket) and one measurement (named EnergyGuard) belonging to the same organization "demo-org".

The data available in the table are :

InfluxDB database structureInfluxDB database structureOrg: demo-orgBucket: demo-bucket«measurement»EnergyGuardtime : timestampEnergyGuard : string «tag»  IsConnected : bool «field»HasMeterData : bool «field»IsOpevSupported : bool «field»Diagnosis_LastErrorCode : string «field»OverloadProtection_Value : float «field» Energy manager Meter_DateTime : string «field»Meter_BreakerOpened : bool «field»Meter_OverLoadCurrentLimit1 : float «field»Meter_OverLoadCurrentLimit2 : float «field»Meter_OverLoadCurrentLimit3 : float «field»Meter_RmsCurrent1 : float «field»Meter_RmsCurrent2 : float «field»Meter_RmsCurrent3 : float «field» Linky meter EV_CurrentPerPhase1 : float «field»EV_CurrentPerPhase2 : float «field»EV_CurrentPerPhase3 : float «field»Electric vehicle
InfluxDB database structureInfluxDB database structureOrg: demo-orgBucket: demo-bucket«measurement»EnergyGuardtime : timestampEnergyGuard : string «tag»  IsConnected : bool «field»HasMeterData : bool «field»IsOpevSupported : bool «field»Diagnosis_LastErrorCode : string «field»OverloadProtection_Value : float «field» Energy manager Meter_DateTime : string «field»Meter_BreakerOpened : bool «field»Meter_OverLoadCurrentLimit1 : float «field»Meter_OverLoadCurrentLimit2 : float «field»Meter_OverLoadCurrentLimit3 : float «field»Meter_RmsCurrent1 : float «field»Meter_RmsCurrent2 : float «field»Meter_RmsCurrent3 : float «field» Linky meter EV_CurrentPerPhase1 : float «field»EV_CurrentPerPhase2 : float «field»EV_CurrentPerPhase3 : float «field»Electric vehicle

Servers and Hosting

The tic4eebus application can be installed on multiple platforms (Raspberry Pi, PLC, Windows PC, Mac)

Security

Security Measures

All communication with the charging station is secured (see EEBUS standard)

Access Management

The tic4eebus application accesses the charging station via its SKI which is in the configuration file loaded at application startup.

Error Handling and Monitoring

Error Handling

During periodic regulation there are 6 main possible errors:

  1. Loss of connection with TIC2WebSocket which provides Linky meter data
  2. Absence of TIC stream with the Linky meter in TIC2WebSocket
  3. Absence of message from the Linky meter in TIC2WebSocket
  4. Loss of EEBUS connection with the electric vehicle charging station
  5. Non-implementation of the OPEV use case of the EEBUS standard by the charging station
  6. Failure to apply the electric vehicle current limitation

All errors are logged in the application log.

Each of these errors modifies the energy management system diagnostic data.

When the energy manager operational state is in error (see failure in the table), the charging station limits the electric vehicle with the minimum charging current.

Loss of Connection with TIC2WebSocket

The Tic2WebSocketClient WebSocket client of the tic4eebus application connects to the WebSocket server of the TIC2WebSocket application to retrieve Linky meter business data.

If the connection with the server fails or is cut, then the tic4eebus application cannot receive Linky meter business data.

A periodic connection recovery attempt is made until the connection is established.

Absence of Meter TIC Stream in TIC2WebSocket

After the Tic2WebSocketClient WebSocket client of the tic4eebus application connects to the WebSocket server of the TIC2WebSocket application, a request is sent to retrieve the list of available TIC streams.

When no stream is available or when the specified meter is not present in the available TIC streams, retrieving Linky meter business data is not possible.

Periodic requests to list available TIC streams are executed until a meter or the specified meter is detected.

Absence of Message from Meter in TIC2WebSocket

After the Tic2WebSocketClient WebSocket client of the tic4eebus application subscribes to a meter with the WebSocket server of the TIC2WebSocket application, messages containing business data are retrieved periodically (with a period varying between 1 and 3 seconds).

When the Linky meter has not sent a message (TIC frame) for 10 seconds, the meter business data is obsolete and it is considered that there is no data from the meter.

When a message (TIC frame) is received again, the message absence stops and the energy manager periodic regulation resumes normally.

Loss of Connection with Charging Station

At tic4eebus application startup, the EEBUS service connects to the charging station.

When the connection with the charging station fails or is cut, then the tic4eebus application can no longer regulate the electric vehicle charge limitation.

A periodic connection recovery attempt with the charging station is made by the EEBUS service.

Non-implementation of OPEV EEBUS Use Case in Charging Station

At tic4eebus application startup, the EEBUS service connects to the charging station.

When the connection with the charging station is established, the EEBUS standard use cases implemented by the station can be retrieved (not on all stations).

When an electric vehicle connects, new notifications appear to provide information about the EEBUS use cases related to the electric vehicle.

The OPEV use case that interests us allows limiting electric vehicle charging.

If this use case is not implemented, then vehicle regulation is not possible.

Failure to Apply Electric Vehicle Charge Limitation

In the energy manager periodic regulation, the vehicle current limitation value is calculated then applied if it is different from the current limitation value.

During current limitation application, the request can be rejected and therefore the regulation non-operational.

Periodic regulation continues anyway hoping that the next current limitation application request is not rejected.

Monitoring Tools

In the current state, there is no tool to monitor the application state and performance.

Scalability

Scalability Strategies

Several evolution axes are possible:

  • Provide application state
  • Take into account the current drawn by the vehicle in periodic regulation

Conclusion

The tic4tic4eebus eebus application is a multi-platform implementation that allows implementing the OPEV use case with a Linky meter and an EEBUS-compatible charging station.