Skip to content

Commit

Permalink
Merge pull request #80 from destroyedlolo/Dev
Browse files Browse the repository at this point in the history
Add NamedMinMax
  • Loading branch information
destroyedlolo authored Oct 28, 2024
2 parents 4650c52 + a925af4 commit b882a14
Show file tree
Hide file tree
Showing 24 changed files with 636 additions and 21 deletions.
43 changes: 43 additions & 0 deletions Documentations/NamedMinMax.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# .namedminmax
NamedMinMax generates some statistics from several named dataset (instead of only one as [MinMax](MinMax.md) is doing).

## Syntax

NamedMinMax are basically **[Lua tasks](Task(lua).md)** and are following the same syntax.

In the header of the script (comment block at the very beginning of the script), each line starting with `-->>` are Majordome's commands.<br>
Consequently, `--->>` are commented out commands (notice the 3 dashes).

## Directives

### Generals

#### -->> name=
Unique name to identify the NamedMinMax. If not set, uses the filename.
`-->> name=toto`
#### -->> quiet
Remove some trace. This option is useful to avoid logging of very noisy topics.

#### -->> disabled
This NamedMinMax starts as disabled : stats change and incoming messages are ignored.

### NamedMinMax owns
None

### Exposed variables
- **MAJORDOME_Myself** is automatically created and correspond to the current NamedMinMax
- **MAJORDOME_NAMEDMINMAX** - NamedMinMax's name

## at Lua side
### Exposed objects
Statistics sequencing and retrieving are done through the **MajordomeNamedMinMax**'s API :
- `getContainer()` returns the container (directory) in which this NamedMinMax has been defined
- `getName()` returns NamedMinMax's name
- `isEnabled()` returns a boolean reflecting if this NamedMinMax is enabled or not
- `Enable()` to enable this NamedMinMax
- `Disable()` to disable this NamedMinMax
- `Clear(name)` or `Reset(name)` to reset data statistics : a new collection is starting (only impacting the one the name is provided)
- `getMin(name)`, `getMax(name)`, `getAverage(name)` : some statistics
- `getSum(name)` : sum of all incoming data since last `Reset()`
- `getSamplesNumber(name)` : number of samples received since last `Reset()`
- `FiguresNames()` : return all figures name's
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Timer to launch tasks every 10 secondes

# name of the timer
# if not set, takes the filename
#name=toto

# repeating delay (in seconds)
# ignored if null
every=10

# This timer is set to an absolute time,
# format HHMM
#at=2256

# NOTEZ-BIEN : every has precedence on at.
# If both are present, only every is took in account

# Launch tasks at startup
#immediate

# Launch tasks if Majordome is starting after at= time (for the same day)
#runifover

# disable this timer
#disabled
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
-- This task with collect minmax data every 1 minute.
--
-- In the header of the script (comment block at the very beginning of
-- the script), each line starting with -->> are Majordome's commands.
-- Consequently, '--->>' are commented out commands.
--
-- Name of this script
-- if not set, takes the filename
-- Notez-bien : if used, this directive MUST be defined before any
-- listen directive.
--->> name=Toto
--
-- Indicate the Timer(s) to wait for
-- (more than one "when" can be present)
-->> when=10s
--
-- Create this rendez-vous object
-->> need_namedminmax=TestNamedMinMax
--
-- remove some trace
-- This option is useful to avoid logging of very noisy topics
--->> quiet
--
-- Disable this script
--->> disabled
--

print ""

-- Iterate against stored values
for _,v in ipairs( table.pack(TestNamedMinMax:FiguresNames()) ) do

print(v)
print "---------"

print( "Number of samples :", TestNamedMinMax:getSamplesNumber(v) )
print( "Min value :", TestNamedMinMax:getMin(v) )
print( "Max value :", TestNamedMinMax:getMax(v) )
print( "Max Average :", TestNamedMinMax:getAverage(v) )

-- Clear storage : restart a new series
TestNamedMinMax:Clear(v)
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Retrieve electricity consumed for my home

topic=TeleInfo/Consommation/values/PAPP
#store
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Retrieve power consumed

topic=TeleInfo/LinkyProduction/values/SINSTI
#store
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
-- This is an example of Tracker script
-- In the header of the script (comment bloc at the very beginning of
-- the script), each line starting with -->> are Majordome's commands.
-- Consequently, '--->>' are commented out commands.
--
-- Name of this script
-- if not set, takes the filename
-- Notez-bien : if used, this directive MUST be defined before any
-- listen directive.
--->> name=Toto
--
-- remove some trace
-- This option is useful to avoid logging of very noisy topics
-->> quiet
--
-- Disable this trigger
--->> disabled
--
-- Indicate MQTT topic(s) to listen to
-- More than one "listen" can be present
-- In such case, it's wise for this function to return different name.
-->> listen=ConsPower
-->> listen=ProdPower
--
-->> need_topic=ConsPower
-->> need_topic=ProdPower

-- The function bellow has to return the name of the figure
-- (or nothing if the data has to be rejected)

-- Determine which data is it
if MAJORDOME_TOPIC == ConsPower:getTopic() then
return "Consumer"
elseif MAJORDOME_TOPIC == ProdPower:getTopic() then
return "Producer"
end
27 changes: 27 additions & 0 deletions Documentations/SamplesCode/NamedMinMax/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
Demonstrates the usage of **MinMax** object : It will gather real-time consumed electricity and, every 10 seconds, will display some statistics about it :
```
Number of samples : 7.0
Min value : 530.0
Max value : 2640.0
Max Average : 1640.0
```

---

* `ConsPower.topic` : data source
* `ProdPower.topic` : data source
* `TestNamedMinMax.minmax` : statistic generator for this example
* `10s.timer` : Timeframe to generate statistics on
* `Collector.lua` : display MinMax's statistics

---

To test it, create a config file like this :

# URL to reach the broker
Broker_URL=tcp://torchwood.local:1883

# Application directory
ApplicationDirectory=Documentations/SamplesCode/Tracker_HowMany

And obviously you have to find out your own data source.
2 changes: 1 addition & 1 deletion Documentations/minmax.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ MinMax takes incoming data from a data source (a topic), and generates some stat

## Syntax

Trackers are basically **[Lua tasks](Task(lua).md)** and are following the same syntax.
MinMax are basically **[Lua tasks](Task(lua).md)** and are following the same syntax.

In the header of the script (comment block at the very beginning of the script), each line starting with `-->>` are Majordome's commands.<br>
Consequently, `--->>` are commented out commands (notice the 3 dashes).
Expand Down
9 changes: 9 additions & 0 deletions src/Config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,3 +179,12 @@ MinMax &Config::findMinMax( std::string &n ) {
else
return (*obj).second;
}

NamedMinMax &Config::findNamedMinMax( std::string &n ) {
Config::NamedMinMaxElements::iterator obj;

if( (obj = this->NamedMinMaxList.find( n )) == this->NamedMinMaxList.end() )
throw 1;
else
return (*obj).second;
}
5 changes: 5 additions & 0 deletions src/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "MQTTTopic.h"
#include "Tracker.h"
#include "MinMax.h"
#include "NamedMinMax.h"

class Config : virtual public SortDir {
std::string configDir;
Expand Down Expand Up @@ -47,6 +48,9 @@ protected :
typedef std::unordered_map<std::string, MinMax> MinMaxElements;
MinMaxElements MinMaxList;

typedef std::unordered_map<std::string, NamedMinMax> NamedMinMaxElements;
NamedMinMaxElements NamedMinMaxList;

/* Initialise this configuration against 'where' directory's content */
void init(std::string &where, lua_State *L);

Expand All @@ -73,6 +77,7 @@ protected :
LuaTask &findTask( std::string & );
Tracker &findTracker( std::string & );
MinMax &findMinMax( std::string & );
NamedMinMax &findNamedMinMax( std::string & );

std::string getConfigDir(){ return this->configDir; }
};
Expand Down
41 changes: 34 additions & 7 deletions src/LuaExec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ bool LuaExec::LoadFunc( lua_State *L, std::stringstream &buffer, const char *nam
* Slave threads
****/

void LuaExec::feedState( lua_State *L, const char *name, const char *topic, const char *payload, bool tracker, const char *trkstatus, bool minmax ){
void LuaExec::feedState( lua_State *L, const char *name, const char *topic, const char *payload, bool tracker, const char *trkstatus ){
lua_pushstring( L, config.getConfigDir().c_str() );
lua_setglobal( L, "MAJORDOME_CONFIGURATION_DIRECTORY" );

Expand All @@ -63,11 +63,6 @@ void LuaExec::feedState( lua_State *L, const char *name, const char *topic, cons
lua_setglobal( L, "MAJORDOME_PAYLOAD" );
}

if( minmax ){
lua_pushstring( L, name ); // Push the name of the tracker
lua_setglobal( L, "MAJORDOME_MINMAX" );
}

if( tracker ){ // Launched by a tracker
lua_pushstring( L, name ); // Push the name of the tracker
lua_setglobal( L, "MAJORDOME_TRACKER" );
Expand Down Expand Up @@ -206,6 +201,21 @@ bool LuaExec::feedbyNeeded( lua_State *L ){
}
}

for(auto &i : this->needed_namedminmax){
try {
class NamedMinMax &mm = config.NamedMinMaxList.at( i );
class NamedMinMax **minmax = (class NamedMinMax **)lua_newuserdata(L, sizeof(class NamedMinMax *));
assert(minmax);

*minmax = &mm;
luaL_getmetatable(L, "MajordomeNamedMinMax");
lua_setmetatable(L, -2);

lua_setglobal(L, i.c_str());
} catch( std::out_of_range &e ){ // Not found
return false;
}
}
return true;
}

Expand Down Expand Up @@ -297,6 +307,17 @@ bool LuaExec::readConfigDirective( std::string &l ){
SelLog->Log('F', "\t\tminmax '%s' is not (yet ?) defined", arg.c_str());
exit(EXIT_FAILURE);
}
} else if(!!(arg = striKWcmp( l, "-->> need_namedminmax=" ))){
Config::NamedMinMaxElements::iterator nminmax;
if( (nminmax = config.NamedMinMaxList.find(arg)) != config.NamedMinMaxList.end()){
if(verbose)
SelLog->Log('C', "\t\tAdded needed namedminmax '%s'", arg.c_str());
this->addNeededNamedMinMax( arg );
return true;
} else {
SelLog->Log('F', "\t\tnamedminmax '%s' is not (yet ?) defined", arg.c_str());
exit(EXIT_FAILURE);
}
}

return Object::readConfigDirective(l);
Expand Down Expand Up @@ -366,7 +387,7 @@ bool LuaExec::execAsync( const char *name, const char *topic, const char *payloa
return true;
}

bool LuaExec::execSync( const char *name, const char *topic, const char *payload, bool tracker, enum boolRetCode *rc ){
bool LuaExec::execSync( const char *name, const char *topic, const char *payload, bool tracker, enum boolRetCode *rc, std::string *rs ){
lua_State *L = luaL_newstate();
if( !L ){
SelLog->Log('E', "Unable to create a new Lua State for '%s' from '%s'", this->getNameC(), this->getWhereC() );
Expand Down Expand Up @@ -402,6 +423,12 @@ bool LuaExec::execSync( const char *name, const char *topic, const char *payload
*rc = lua_toboolean(L, -1) ? boolRetCode::RCtrue : boolRetCode::RCfalse;
}

if(rs){
*rs = "";
if(lua_isstring(L, -1))
*rs = lua_tostring(L, -1);
}

lua_close(L);

return true;
Expand Down
7 changes: 5 additions & 2 deletions src/LuaExec.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class LuaExec : virtual public Object {
StringVector required_topic;
StringVector needed_task;
StringVector needed_minmax;
StringVector needed_namedminmax;

protected:
void addNeededRendezVous( std::string t ){ this->needed_rendezvous.Add(t); }
Expand All @@ -34,6 +35,7 @@ class LuaExec : virtual public Object {
void addRequiredTopic( std::string t ){ this->required_topic.Add(t); }
void addNeededTask( std::string t ){ this->needed_task.Add(t); }
void addNeededMinMax( std::string t ){ this->needed_minmax.Add(t); }
void addNeededNamedMinMax( std::string t ){ this->needed_namedminmax.Add(t); }

bool readConfigDirective( std::string &l );

Expand All @@ -60,7 +62,7 @@ class LuaExec : virtual public Object {
*
* May be overloaded if some local objects have to be created
*/
virtual void feedState( lua_State *L, const char *name, const char *topic=NULL, const char *payload=NULL, bool tracker=false, const char *trkstatus=NULL, bool minmax=false );
virtual void feedState( lua_State *L, const char *name, const char *topic=NULL, const char *payload=NULL, bool tracker=false, const char *trkstatus=NULL );

/* Launch a task in a slave thread
* -> same as feedState()
Expand All @@ -71,9 +73,10 @@ class LuaExec : virtual public Object {
/* Execute a task in the same thread
* -> same as feedState()
* -> return code from the function (NULL = Ignored)
* -> return return string (NULL = Ignored)
* <- true if it has been executed, false otherwise
*/
bool execSync( const char *name, const char *topic=NULL, const char *payload=NULL, bool tracker=false, enum boolRetCode *rc=NULL );
bool execSync( const char *name, const char *topic=NULL, const char *payload=NULL, bool tracker=false, enum boolRetCode *rc=NULL, std::string *rs=NULL );

/* Tell when a task is finished
* (mostly for tasks with "once" parameter)
Expand Down
17 changes: 17 additions & 0 deletions src/MQTTTopic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,23 @@ void MQTTTopic::execMinMax( Config &cfg, const char *name, const char *topic, co
}
}

void MQTTTopic::execNamedMinMax( Config &cfg, const char *name, const char *topic, const char *payload ){
#ifdef DEBUG
if(debug && !this->isQuiet())
SelLog->Log('D', "execNamedMinMax() : %d to run", this->minmaxes.size() );
#endif

for( StringVector::iterator trk = this->namedminmaxes.begin(); trk != this->namedminmaxes.end(); trk++){
try {
NamedMinMax &namedminmax = cfg.findNamedMinMax( *trk );
namedminmax.exec( name, topic, payload );
} catch (...) {
SelLog->Log('F', "Internal error : can't find NamedMinMax \"%s\"", (*trk).c_str() );
exit(EXIT_FAILURE);
}
}
}

/*****
* Lua exposed functions
*****/
Expand Down
Loading

0 comments on commit b882a14

Please sign in to comment.