diff --git a/agents/httpagent_it_test.go b/agents/httpagent_it_test.go
index c004e166a..76708478e 100644
--- a/agents/httpagent_it_test.go
+++ b/agents/httpagent_it_test.go
@@ -57,14 +57,10 @@ func TestHAitInitCfg(t *testing.T) {
}
// Remove data in both rating and accounting db
-func TestHAitResetDataDb(t *testing.T) {
+func TestHAitResetDB(t *testing.T) {
if err := engine.InitDataDb(haCfg); err != nil {
t.Fatal(err)
}
-}
-
-// Wipe out the cdr database
-func TestHAitResetStorDb(t *testing.T) {
if err := engine.InitStorDb(haCfg); err != nil {
t.Fatal(err)
}
diff --git a/config/chargerscfg.go b/config/chargerscfg.go
new file mode 100644
index 000000000..074332a59
--- /dev/null
+++ b/config/chargerscfg.go
@@ -0,0 +1,58 @@
+/*
+Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
+Copyright (C) ITsysCOM GmbH
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see
+*/
+
+package config
+
+// SupplierSCfg is the configuration of supplier service
+type ChargerSCfg struct {
+ Enabled bool
+ AttributeSConns []*HaPoolConfig
+ StringIndexedFields *[]string
+ PrefixIndexedFields *[]string
+}
+
+func (cS *ChargerSCfg) loadFromJsonCfg(jsnCfg *ChargerSJsonCfg) (err error) {
+ if jsnCfg == nil {
+ return
+ }
+ if jsnCfg.Enabled != nil {
+ cS.Enabled = *jsnCfg.Enabled
+ }
+ if jsnCfg.Attributes_conns != nil {
+ cS.AttributeSConns = make([]*HaPoolConfig, len(*jsnCfg.Attributes_conns))
+ for idx, jsnHaCfg := range *jsnCfg.Attributes_conns {
+ cS.AttributeSConns[idx] = NewDfltHaPoolConfig()
+ cS.AttributeSConns[idx].loadFromJsonCfg(jsnHaCfg)
+ }
+ }
+ if jsnCfg.String_indexed_fields != nil {
+ sif := make([]string, len(*jsnCfg.String_indexed_fields))
+ for i, fID := range *jsnCfg.String_indexed_fields {
+ sif[i] = fID
+ }
+ cS.StringIndexedFields = &sif
+ }
+ if jsnCfg.Prefix_indexed_fields != nil {
+ pif := make([]string, len(*jsnCfg.Prefix_indexed_fields))
+ for i, fID := range *jsnCfg.Prefix_indexed_fields {
+ pif[i] = fID
+ }
+ cS.PrefixIndexedFields = &pif
+ }
+ return
+}
diff --git a/config/config.go b/config/config.go
index c36219a51..f9f1b6083 100755
--- a/config/config.go
+++ b/config/config.go
@@ -341,19 +341,20 @@ type CGRConfig struct {
CdreProfiles map[string]*CdreConfig
CdrcProfiles map[string][]*CdrcConfig // Number of CDRC instances running imports, format map[dirPath][]{Configs}
sessionSCfg *SessionSCfg
- fsAgentCfg *FsAgentConfig // FreeSWITCHAgent configuration
- kamAgentCfg *KamAgentCfg // KamailioAgent Configuration
- SmOsipsConfig *SmOsipsConfig // SMOpenSIPS Configuration
- asteriskAgentCfg *AsteriskAgentCfg // SMAsterisk Configuration
- diameterAgentCfg *DiameterAgentCfg // DiameterAgent configuration
- radiusAgentCfg *RadiusAgentCfg // RadiusAgent configuration
- httpAgentCfg []*HttpAgentCfg // HttpAgent configuration
- filterSCfg *FilterSCfg // FilterS configuration
- PubSubServerEnabled bool // Starts PubSub as server: .
- AliasesServerEnabled bool // Starts PubSub as server: .
- UserServerEnabled bool // Starts User as server:
- UserServerIndexes []string // List of user profile field indexes
- attributeSCfg *AttributeSCfg // Attribute service configuration
+ fsAgentCfg *FsAgentConfig // FreeSWITCHAgent configuration
+ kamAgentCfg *KamAgentCfg // KamailioAgent Configuration
+ SmOsipsConfig *SmOsipsConfig // SMOpenSIPS Configuration
+ asteriskAgentCfg *AsteriskAgentCfg // SMAsterisk Configuration
+ diameterAgentCfg *DiameterAgentCfg // DiameterAgent configuration
+ radiusAgentCfg *RadiusAgentCfg // RadiusAgent configuration
+ httpAgentCfg []*HttpAgentCfg // HttpAgent configuration
+ filterSCfg *FilterSCfg // FilterS configuration
+ PubSubServerEnabled bool // Starts PubSub as server: .
+ AliasesServerEnabled bool // Starts PubSub as server: .
+ UserServerEnabled bool // Starts User as server:
+ UserServerIndexes []string // List of user profile field indexes
+ attributeSCfg *AttributeSCfg // Attribute service configuration
+ chargerSCfg *ChargerSCfg
resourceSCfg *ResourceSConfig // Configuration for resource limiter
statsCfg *StatSCfg // Configuration for StatS
thresholdSCfg *ThresholdSCfg // configuration for ThresholdS
@@ -646,6 +647,14 @@ func (self *CGRConfig) checkConfigSanity() error {
}
}
}
+ if self.chargerSCfg != nil && self.chargerSCfg.Enabled {
+ for _, connCfg := range self.chargerSCfg.AttributeSConns {
+ if connCfg.Address == utils.MetaInternal &&
+ (self.attributeSCfg == nil || !self.attributeSCfg.Enabled) {
+ return errors.New("AttributeS not enabled but requested by ChargerS component.")
+ }
+ }
+ }
// ResourceLimiter checks
if self.resourceSCfg != nil && self.resourceSCfg.Enabled {
for _, connCfg := range self.resourceSCfg.ThresholdSConns {
@@ -818,6 +827,11 @@ func (self *CGRConfig) loadFromJsonCfg(jsnCfg *CgrJsonCfg) (err error) {
return err
}
+ jsnChargerSCfg, err := jsnCfg.ChargerServJsonCfg()
+ if err != nil {
+ return err
+ }
+
jsnRLSCfg, err := jsnCfg.ResourceSJsonCfg()
if err != nil {
return err
@@ -1376,6 +1390,15 @@ func (self *CGRConfig) loadFromJsonCfg(jsnCfg *CgrJsonCfg) (err error) {
}
}
+ if jsnChargerSCfg != nil {
+ if self.chargerSCfg == nil {
+ self.chargerSCfg = new(ChargerSCfg)
+ }
+ if self.chargerSCfg.loadFromJsonCfg(jsnChargerSCfg); err != nil {
+ return err
+ }
+ }
+
if jsnRLSCfg != nil {
if self.resourceSCfg == nil {
self.resourceSCfg = new(ResourceSConfig)
@@ -1496,6 +1519,10 @@ func (cfg *CGRConfig) AttributeSCfg() *AttributeSCfg {
return cfg.attributeSCfg
}
+func (cfg *CGRConfig) ChargerSCfg() *ChargerSCfg {
+ return cfg.chargerSCfg
+}
+
// ToDo: fix locking here
func (self *CGRConfig) ResourceSCfg() *ResourceSConfig {
return self.resourceSCfg
diff --git a/config/config_defaults.go b/config/config_defaults.go
index 5c6dc034a..031314365 100755
--- a/config/config_defaults.go
+++ b/config/config_defaults.go
@@ -429,6 +429,14 @@ const CGRATES_CFG_JSON = `
},
+"chargers": { // Charger service
+ "enabled": false, // starts charger service: .
+ "attributes_conns": [], // address where to reach the AttributeS <""|127.0.0.1:2013>
+ //"string_indexed_fields": [], // query indexes based on these fields for faster processing
+ "prefix_indexed_fields": [], // query indexes based on these fields for faster processing
+},
+
+
"resources": { // Resource service (*new)
"enabled": false, // starts ResourceLimiter service: .
"store_interval": "", // dump cache regularly to dataDB, 0 - dump at start/shutdown: <""|$dur>
diff --git a/config/config_json.go b/config/config_json.go
index 70b56e7af..52cb0dada 100644
--- a/config/config_json.go
+++ b/config/config_json.go
@@ -67,6 +67,7 @@ const (
DispatcherSJson = "dispatcher"
CgrLoaderCfgJson = "loader"
CgrMigratorCfgJson = "migrator"
+ ChargerSCfgJson = "chargers"
)
// Loads the json config out of io.Reader, eg other sources than file, maybe over http
@@ -368,6 +369,18 @@ func (cgrJsn CgrJsonCfg) AttributeServJsonCfg() (*AttributeSJsonCfg, error) {
return cfg, nil
}
+func (cgrJsn CgrJsonCfg) ChargerServJsonCfg() (*ChargerSJsonCfg, error) {
+ rawCfg, hasKey := cgrJsn[ChargerSCfgJson]
+ if !hasKey {
+ return nil, nil
+ }
+ cfg := new(ChargerSJsonCfg)
+ if err := json.Unmarshal(*rawCfg, cfg); err != nil {
+ return nil, err
+ }
+ return cfg, nil
+}
+
func (self CgrJsonCfg) ResourceSJsonCfg() (*ResourceSJsonCfg, error) {
rawCfg, hasKey := self[RESOURCES_JSON]
if !hasKey {
diff --git a/config/config_json_test.go b/config/config_json_test.go
index e0751d0b9..9906559ba 100755
--- a/config/config_json_test.go
+++ b/config/config_json_test.go
@@ -705,6 +705,20 @@ func TestDfAttributeServJsonCfg(t *testing.T) {
}
}
+func TestDfChargerServJsonCfg(t *testing.T) {
+ eCfg := &ChargerSJsonCfg{
+ Enabled: utils.BoolPointer(false),
+ Attributes_conns: &[]*HaPoolJsonCfg{},
+ String_indexed_fields: nil,
+ Prefix_indexed_fields: &[]string{},
+ }
+ if cfg, err := dfCgrJsonCfg.ChargerServJsonCfg(); err != nil {
+ t.Error(err)
+ } else if !reflect.DeepEqual(eCfg, cfg) {
+ t.Error("Received: ", cfg)
+ }
+}
+
func TestDfFilterSJsonCfg(t *testing.T) {
eCfg := &FilterSJsonCfg{
Stats_conns: &[]*HaPoolJsonCfg{},
diff --git a/config/config_test.go b/config/config_test.go
index 90628520d..3bfc82409 100755
--- a/config/config_test.go
+++ b/config/config_test.go
@@ -801,6 +801,18 @@ func TestCgrCfgJSONDefaultSAttributeSCfg(t *testing.T) {
}
}
+func TestCgrCfgJSONDefaultSChargerSCfg(t *testing.T) {
+ eChargerSCfg := &ChargerSCfg{
+ Enabled: false,
+ AttributeSConns: []*HaPoolConfig{},
+ StringIndexedFields: nil,
+ PrefixIndexedFields: &[]string{},
+ }
+ if !reflect.DeepEqual(eChargerSCfg, cgrCfg.chargerSCfg) {
+ t.Errorf("received: %+v, expecting: %+v", eChargerSCfg, cgrCfg.chargerSCfg)
+ }
+}
+
func TestCgrCfgJSONDefaultsResLimCfg(t *testing.T) {
eResLiCfg := &ResourceSConfig{
Enabled: false,
diff --git a/config/libconfig_json.go b/config/libconfig_json.go
index d3bcd1096..66136dbf0 100755
--- a/config/libconfig_json.go
+++ b/config/libconfig_json.go
@@ -429,6 +429,14 @@ type AttributeSJsonCfg struct {
Prefix_indexed_fields *[]string
}
+// ChargerSJsonCfg service config section
+type ChargerSJsonCfg struct {
+ Enabled *bool
+ Attributes_conns *[]*HaPoolJsonCfg
+ String_indexed_fields *[]string
+ Prefix_indexed_fields *[]string
+}
+
// ResourceLimiter service config section
type ResourceSJsonCfg struct {
Enabled *bool
diff --git a/data/tariffplans/tutorial/Chargers.csv b/data/tariffplans/tutorial/Chargers.csv
new file mode 100644
index 000000000..d9f4caed0
--- /dev/null
+++ b/data/tariffplans/tutorial/Chargers.csv
@@ -0,0 +1 @@
+#Tenant,ID,FilterIDs,ActivationInterval,RunID,AttributeIDs,Weight
\ No newline at end of file
diff --git a/engine/chargers.go b/engine/chargers.go
new file mode 100644
index 000000000..95c5fb7a3
--- /dev/null
+++ b/engine/chargers.go
@@ -0,0 +1,54 @@
+/*
+Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
+Copyright (C) ITsysCOM GmbH
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see
+*/
+
+package engine
+
+import (
+ "fmt"
+
+ "github.com/cgrates/cgrates/utils"
+)
+
+func NewChargerService(dm *DataManager, filterS *FilterS,
+ strgIdxFlds, prfxIdxFlds *[]string) (*ChargerService, error) {
+ return &ChargerService{dm: dm, filterS: filterS,
+ strgIdxFlds: strgIdxFlds,
+ prfxIdxFlds: prfxIdxFlds}, nil
+}
+
+type ChargerService struct {
+ dm *DataManager
+ filterS *FilterS
+ strgIdxFlds *[]string
+ prfxIdxFlds *[]string
+}
+
+// ListenAndServe will initialize the service
+func (cS *ChargerService) ListenAndServe(exitChan chan bool) (err error) {
+ utils.Logger.Info(fmt.Sprintf("Starting %s", utils.ChargerS))
+ e := <-exitChan
+ exitChan <- e
+ return
+}
+
+// Shutdown is called to shutdown the service
+func (cS *ChargerService) Shutdown() (err error) {
+ utils.Logger.Info(fmt.Sprintf("<%s> shutdown initialized", utils.ChargerS))
+ utils.Logger.Info(fmt.Sprintf("<%s> shutdown complete", utils.ChargerS))
+ return
+}
diff --git a/engine/models.go b/engine/models.go
index 8c5e8f9d1..11e7e5114 100644
--- a/engine/models.go
+++ b/engine/models.go
@@ -558,3 +558,16 @@ type TPAttribute struct {
Weight float64 `index:"9" re:"\d+\.?\d*"`
CreatedAt time.Time
}
+
+type TPCharger struct {
+ PK uint `gorm:"primary_key"`
+ Tpid string
+ Tenant string `index:"0" re:""`
+ ID string `index:"1" re:""`
+ FilterIDs string `index:"2" re:""`
+ ActivationInterval string `index:"3" re:""`
+ RunID string `index:"4" re:""`
+ AttributeIDs string `index:"5" re:""`
+ Weight float64 `index:"6" re:"\d+\.?\d*"`
+ CreatedAt time.Time
+}
diff --git a/utils/consts.go b/utils/consts.go
index 53f03e03d..fad828173 100755
--- a/utils/consts.go
+++ b/utils/consts.go
@@ -655,6 +655,7 @@ const (
APIKey = "APIKey"
APIMethods = "APIMethods"
NestingSep = "."
+ ChargerS = "ChargerS"
)
// MetaFilterIndexesAPIs