Hello!
In DLMS.c file server.c function svr_handle Single Action Schedule().
If script has few actions function srv_invoke() called for every one. But, in srv_invoke() compare current time with time of last execution and sets time of last execution to current time after first run. Therefore, for other actions in script comparing time and last execution time failed.
The single action schedule will call only one script action. It's not possible to call both captureScriptActions from the one script.
executedScriptSelector is the script index of the script table that is invoked. If you want to invoke both script indexes (#1 and #2) you need to create own action schedule for both.
So you need to create a new addCaptureAction2 method what will invoke index #2. Something like:
int addCaptureAction2()
{
int ret;
const unsigned char ln[6] = { 0, 0, 15, 0, 6, 255 };
Hello!
Is this a limitation in GuruxDLMS or in the Blue Book?
How i understand, Single Action Schedule run ONE script from array of scripts and this script can have array of actions.
The error code is returned at the moment. But my question is more generic. If there are multiple actions in one schedules what to do for them. If an error code is returned immediately following actions are not run. What to do if there are multiple actions that fail.
You have wrote:
"Therefore, for other actions in script comparing time and last execution time failed.".
But actions don't compare the time. They are executed when the script is invoked.
Can you make a code that causes this issue for you? Maybe it will help me to understand the problem better.
Hello!
If script have many actions and one of them finished with error, then do not run next actions.
In function srv_handle Single Action Shedule() of file server.c called function srv_invoke() in cycle for each action of script.
In beginning of srv_invoke() have code:
if (!exec)
{
//Execute in exact time if end time is not given.
if (end == NULL)
{
//Ignore deviation and status for single action script.
exec = *executed < time&& time_compare With Diff(start, time, 0) == 0;
}
else if (*executed < time)
{
exec = time_compare 2(start, time) != 1 && time_compare 2(end, time) != -1;
}
}
For first action (*executed < time) == true, action run and change executed: *executed = time;
For next action (*executed < time) != true and next action do not run.
Yes, the error will interrupt the action executing. That is good to remember if you have multiple actions in one schedule.
Your solution is simple and it will solve the problem if you want to execute multiple scheduled actions.
The problem is that the execution time is not updated after all items actions are run.
I prose that the execution time is saved at the beginning of the function.
uint32_t tmpTime = object->executedTime;
It's restored before invoke in called like this:
//Execution time is returned in case there are multiple actions in one schedule.
object->executedTime = tmpTime;
if ((ret = svr_invoke...
Now the execution time is correct after the actions are executed. Testing will take a couple of days, but I'm hoping that if this will work, it's released during this week.
Hi fon Luck,
Hi fon Luck,
Can you share what kind of single action schedules you have added, so this can be tested. I haven't heard that there are any problems with this.
BR,
Mikko
Hello!
Hello!
gxActionSchedule captureActionShedule;
const BYTE captureTimeQuantity = 1;
gxtime captureTime[captureTimeQuantity];
gxScriptTable captureScriptsTable;
const BYTE captureScriptsQuantity = 1;
gxScript captureScript[captureScriptsQuantity];
const BYTE captureActionQuantity = 2;
gxScriptAction captureScriptAction[captureActionQuantity];
int addCaptureScriptsTable()
{
int ret;
const unsigned char ln[6] = { 0, 0, 10, 0, 5, 255 };
if ((ret = INIT_OBJECT(captureScriptsTable, DLMS_OBJECT_TYPE_SCRIPT_TABLE, ln)) == 0)
{
ARR_ATTACH(captureScriptsTable.scripts, captureScript, captureScriptsQuantity);
captureScript[0].id = 1;
arr_init(&captureScript[0].actions);
captureScriptAction[0].type = DLMS_SCRIPT_ACTION_TYPE_EXECUTE;
captureScriptAction[0].target = BASE(Profile1);
captureScriptAction[0].index = 2;
var_init(&captureScriptAction[0].parameter);
GX_INT8(captureScriptAction[0].parameter) = 0;
captureScriptAction[1].type = DLMS_SCRIPT_ACTION_TYPE_EXECUTE;
captureScriptAction[1].target = BASE(Profile2);
captureScriptAction[1].index = 2;
var_init(&captureScriptAction[1].parameter);
GX_INT8(captureScriptAction[1].parameter) = 0;
ARR_ATTACH(captureScript[0].actions, captureScriptAction, captureActionQuantity);
}
return ret;
}
int addCaptureAction()
{
int ret;
const unsigned char ln[6] = { 0, 0, 15, 0, 5, 255 };
if ((ret = INIT_OBJECT(captureActionShedule, DLMS_OBJECT_TYPE_ACTION_SCHEDULE, ln)) == 0)
{
captureActionShedule.executedScript = &captureScriptsTable;
captureActionShedule.executedScriptSelector = 1;
captureActionShedule.type = DLMS_SINGLE_ACTION_SCHEDULE_TYPE1;
ARR_ATTACH(captureActionShedule.executionTime, captureTime, captureTimeQuantity);
time_init(&captureTime[0], -1, -1, -1, -1, -1, 0, 0, 0);
}
return ret;
}
Hi,
Hi,
The single action schedule will call only one script action. It's not possible to call both captureScriptActions from the one script.
executedScriptSelector is the script index of the script table that is invoked. If you want to invoke both script indexes (#1 and #2) you need to create own action schedule for both.
So you need to create a new addCaptureAction2 method what will invoke index #2. Something like:
int addCaptureAction2()
{
int ret;
const unsigned char ln[6] = { 0, 0, 15, 0, 6, 255 };
if ((ret = INIT_OBJECT(captureActionShedule2, DLMS_OBJECT_TYPE_ACTION_SCHEDULE, ln)) == 0)
{
captureActionShedule2.executedScript = &captureScriptsTable;
captureActionShedule2.executedScriptSelector = 2;
captureActionShedule2.type = DLMS_SINGLE_ACTION_SCHEDULE_TYPE1;
ARR_ATTACH(captureActionShedule2.executionTime, captureTime, captureTimeQuantity);
time_init(&captureTime[0], -1, -1, -1, -1, -1, 0, 0, 0);
}
return ret;
}
BR,
Mikko
Hello!
Hello!
Is this a limitation in GuruxDLMS or in the Blue Book?
How i understand, Single Action Schedule run ONE script from array of scripts and this script can have array of actions.
With best regards.
Hi,
Hi,
Forget what I said. I did try to find a reason for your problem and search for it from the wrong place. :-(
It's possible to call multiple actions, but in general, meters have only one action per script.
The main reason for this that what to do if one script fails. Should you continue executing the next scripts or return the error code.
We have tried to solve your problem, but need more info.
How often do you run svr_run-method?
BR,
Mikko
Hello!
Hello!
Each second.
I think, the best choice is to return error code.
With best regards.
Hi,
Hi,
The error code is returned at the moment. But my question is more generic. If there are multiple actions in one schedules what to do for them. If an error code is returned immediately following actions are not run. What to do if there are multiple actions that fail.
You have wrote:
"Therefore, for other actions in script comparing time and last execution time failed.".
But actions don't compare the time. They are executed when the script is invoked.
Can you make a code that causes this issue for you? Maybe it will help me to understand the problem better.
BR,
Mikko
Hello!
Hello!
If script have many actions and one of them finished with error, then do not run next actions.
In function srv_handle Single Action Shedule() of file server.c called function srv_invoke() in cycle for each action of script.
In beginning of srv_invoke() have code:
if (!exec)
{
//Execute in exact time if end time is not given.
if (end == NULL)
{
//Ignore deviation and status for single action script.
exec = *executed < time&& time_compare With Diff(start, time, 0) == 0;
}
else if (*executed < time)
{
exec = time_compare 2(start, time) != 1 && time_compare 2(end, time) != -1;
}
}
For first action (*executed < time) == true, action run and change executed: *executed = time;
For next action (*executed < time) != true and next action do not run.
With best regards.
Hello!
Hello!
My suggestion:
uint32_t tmpTime; // add
int posA;
for (posA = 0; posA != it->actions.size; ++posA)
{
#ifdef DLMS_IGNORE_MALLOC
if ((ret = arr_getByIndex(&it->actions, posA, (void**)&a, sizeof(gxScriptAction))) != 0)
{
break;
}
#else
if ((ret = arr_getByIndex(&it->actions, posA, (void**)&a)) != 0)
{
break;
}
#endif //DLMS_IGNORE_MALLOC
tmpTime = object->executedTime;
if ((ret = svr_invoke(
settings,
(gxObject*)a->target,
a->index,
time,
s,
NULL,
&tmpTime, // change
next)) != 0)
{
break;
}
}
object->executedTime = tmpTime; // add
With best regards.
Hi,
Hi,
Yes, the error will interrupt the action executing. That is good to remember if you have multiple actions in one schedule.
Your solution is simple and it will solve the problem if you want to execute multiple scheduled actions.
The problem is that the execution time is not updated after all items actions are run.
I prose that the execution time is saved at the beginning of the function.
uint32_t tmpTime = object->executedTime;
It's restored before invoke in called like this:
//Execution time is returned in case there are multiple actions in one schedule.
object->executedTime = tmpTime;
if ((ret = svr_invoke...
Now the execution time is correct after the actions are executed. Testing will take a couple of days, but I'm hoping that if this will work, it's released during this week.
Thank you for your thoughts.
BR,
Mikko