Closed sa-wo closed 4 years ago
Have you tried setting the interval to zero in the task settings? ^^
@Budman1758 thanks for your reply, but this device has changeable values in the task settings.
@sa-wo there is no such thing like interval in this plugin ... need to check if got something like this module or need logs from this module when rfid is in coil and far from coil
@uzi18 Hi this is the log, holding the token for 2 seconds on coil. No rules set.
83162: RFID : Tag: 3364040 83209: EVENT: rfid_tag_water#Tag=3364040 83227: RFID : Tag: 3364040 83291: RFID : Tag: 3364040 83335: EVENT: rfid_tag_water#Tag=3364040 83356: RFID : Tag: 3364040 83409: EVENT: rfid_tag_water#Tag=3364040 83421: RFID : Tag: 3364040 83485: RFID : Tag: 3364040 83510: EVENT: rfid_tag_water#Tag=3364040 83550: RFID : Tag: 3364040 83615: RFID : Tag: 3364040 83630: EVENT: rfid_tag_water#Tag=3364040 83679: RFID : Tag: 3364040 83756: EVENT: rfid_tag_water#Tag=3364040 83762: RFID : Tag: 3364040 83808: RFID : Tag: 3364040 83831: EVENT: rfid_tag_water#Tag=3364040 83878: RFID : Tag: 3364040 83916: EVENT: rfid_tag_water#Tag=3364040 83943: RFID : Tag: 3364040 84007: RFID : Tag: 3364040 84031: EVENT: rfid_tag_water#Tag=3364040 84072: RFID : Tag: 3364040 84137: RFID : Tag: 3364040 84180: EVENT: rfid_tag_water#Tag=3364040 84202: RFID : Tag: 3364040 84225: EVENT: rfid_tag_water#Tag=3364040 84266: RFID : Tag: 3364040 _84316: EVENT: rfid_tag_water#Tag=3364040 84416: EVENT: rfid_tag_water#Tag=3364040 84537: EVENT: rfid_tag_water#Tag=3364040 84609: EVENT: rfid_tag_water#Tag=3364040 84709: EVENT: rfid_tag_water#Tag=3364040 84809: EVENT: rfid_tag_water#Tag=3364040 84909: EVENT: rfid_tag_water#Tag=3364040 85027: EVENT: rfid_tagwater#Tag=3364040
The last 8 entries (84316 - 85027) appeared when I had already removed the token from coil.
Sawo
I need different log - directly from rfid module. You can try to get it by connect computer to usb on wemos d1 and use terminal app with settings 9600 8N1 (with hex display support - h-term/real term etc.) log same like before - 4s. with card and 4s. without card on coil.
@uzi18 I hope this is what you need, I user h-term.
output_2020-04-02_20-48-10.log output_2020-04-02_20-48-10_hex.log
Thx
@sa-wo ~what bin file did you flashed into esp?~ Will try to prepare build for you. ok it is in first post ;)
@TD-er do you have issues with envs?
[ESPEasy-mega_test]$ platformio run -v -e normal_ESP8266_1M
...
Error: VCS: Could not process command ['git', 'clone', '--recursive', '--depth', '1', '--branch', '2.6.3', 'https://github.com/esp8266/Arduino.git', '/home/users/linaja/.platformio/packages/_tmp_installing-i_r6q3ag-package']
@sa-wo you can try this and create log like before: firmware.bin.zip
@uzi18 Here are the log files, one in raw / Hex. I placed the token about 4 seconds on the coil.
output_2020-04-03_07-14-15.log output_2020-04-03_07-14-21.log
Thx sawo
@uzi18 Here are the log files, one in raw / Hex. I placed the token about 4 seconds on the coil.
this one is the best, I see some place to improvemen in plugin - on communication side but your problem is that you want to know when card is removed?
@sa-wo need also log when card is removed
@uzi18 Here is the log with removed card, for about 10seconds.
output_2020-04-03_10-09-51.log output_2020-04-03_10-09-58.log
sawo
@TD-er do you have issues with envs?
[ESPEasy-mega_test]$ platformio run -v -e normal_ESP8266_1M ... Error: VCS: Could not process command ['git', 'clone', '--recursive', '--depth', '1', '--branch', '2.6.3', 'https://github.com/esp8266/Arduino.git', '/home/users/linaja/.platformio/packages/_tmp_installing-i_r6q3ag-package']
Not that I was aware of. Sometimes a delete of the packages dir in your .platformio dir (user dir, not the .pio folder in the checked out repo) does help. But just make sure to backup this folder just in case it is related to some dependency which cannot be downloaded.
@TD-er so we should add event "no card detected" like
EVENT: rfid_tag_water#Tag=0
or/and ... plugin(s) sometimes should export some internals via predefinied variables like here rfid_tag_water#detected=1
via PLUGIN_UNCONDITIONAL_POLL
we actually repeat when card is available (maybe it should be option to report only new number?)
EVENT: rfid_tag_water#Tag=3364040
@TD-er so we should add event "no card detected" like
EVENT: rfid_tag_water#Tag=0
or/and ... plugin(s) sometimes should export some internals via predefinied variables like hererfid_tag_water#detected=1
via PLUGIN_UNCONDITIONAL_POLLwe actually repeat when card is available (maybe it should be option to report only new number?)
EVENT: rfid_tag_water#Tag=3364040
Yes a tag=0 when none is detected would be what to expect. And also if interval is set to more than zero just trigger the event. If interval=0 then trigger when a change is made, not flood the unit with events.
@Grovkillen via poll you only ask for variable value when needed in rules
if [rfid_tag_water#detected]=1 then
...
endif
All right, so then you remove it it will not trigger an event? I find it a bit unusual compared to what I would expect.
I would believe it to work like this:
Interval = 0, the same behavior as with a switch input (only trigger on change) Interval > 0, it will trigger once per interval
Interval=0 would render in the following scenarios User expose a RFID tag to the reader: RFID#Number=123456790 is triggered User removes the RFID tag from the reader: RFID#Number=0 is triggered
Interval>0 would render in the following scenario Time000: RFID#Number=0 Time001: RFID#Number=0 Time002: RFID#Number=123456790 Time003: RFID#Number=123456790 Time004: RFID#Number=123456790 Time005: RFID#Number=0 Time006: RFID#Number=0
I think it is also great to check a new received ID against the remembered last received one (as it is stored in the uservar) No need to give a new event immediately if the same card is detected. But it would make sense to have some timeout when we may need to detect the same one again. So either store the "0" in the Uservar when you don't see a tag and only send an event when the detected one differs from the last one. (just make sure you test unsigned long values, not floats. The unsigned longs are stored in 2 fields of the UserVar)
First minimal idea to reset card id to 0 when timedout. This should fullfill most of problems here.
We still not use all of data from cardid - it is 10x4 bits here and unsigned long is 32bit wide
@sa-wo try this build: firmware(1).bin.zip
@uzi18 What did you change? Just set the value to 0 when not read? That will make it impossible to refer to the value from rules (apart from an event) Or just no event update if it is the same value?
We also have 2 extra fields in the UserVar we don't yet use, so you can store other values in there like the last read millis() or something like that.
@TD-er have set timer 500ms at end of assign cardid, when timer triggers reset cardid to 0
@@ -56,6 +56,17 @@ boolean Plugin_040(byte function, struct EventStruct *event, String& string)
break;
}
+ case PLUGIN_TIMER_IN:
+ {
+ if (Plugin_040_init) {
+ // Reset card id on timeout
+ UserVar[event->BaseVarIndex] = 0;
+ UserVar[event->BaseVarIndex + 1] = 0;
+ success = true;
+ }
+ break;
+ }
+
@@ -133,6 +160,7 @@ boolean Plugin_040(byte function, struct EventStruct *event, String& string)
log += key;
addLog(LOG_LEVEL_INFO, log);
sendData(event);
+ setPluginTaskTimer(500, event->TaskIndex, event->Par1);
}
}
success = true;
But this does reset the output value, so you cannot use it anymore in rules for checks.
yes but who needs cardid when it is already removed?
Like @TD-er said, if you have the last registered id you could have a extra event value that is 1 if the id is other than the last registered one. Else 0.
hey, we got here 2 issues
in my opinion for such plugin interval value should be not in use - when new card is detected (card id change) we should force to send data to controller
@Grovkillen this will be new feature :)
You can use 2 output values (not sure what it does to controllers like Domoticz), one with the active one and one with the last one. But that also demands a new output type.
I think the main issue here is that you should only send an event when it is a new card, so use some timeout (which you can store in the last 2 values of UserVar) So a detected value of "no card" does not change anythIng (maybe send an event when the card ID has changed from "detected" to "no card detected")
To summarize:
Hi sorry that I am answering so late. Here is the last log with placing the tag for about 4 seconds on the coil. output_2020-04-05_10-33-18.log
and here with no tag on coil output_2020-04-05_10-34-57.log
Thx SAWO
@sa-wo from now you can send log without hex, please check it one more time also with different tag
@TD-er actual patch:
diff --git a/src/_P040_ID12.ino b/src/_P040_ID12.ino
index 40b90111..3cdf8743 100644
--- a/src/_P040_ID12.ino
+++ b/src/_P040_ID12.ino
@@ -47,7 +47,6 @@ boolean Plugin_040(byte function, struct EventStruct *event, String& string)
break;
}
-
case PLUGIN_INIT:
{
Plugin_040_init = true;
@@ -56,6 +55,19 @@ boolean Plugin_040(byte function, struct EventStruct *event, String& string)
break;
}
+ case PLUGIN_TIMER_IN:
+ {
+ if (Plugin_040_init) {
+ // Reset card id on timeout
+ UserVar[event->BaseVarIndex] = 0;
+ UserVar[event->BaseVarIndex + 1] = 0;
+ String log = F("RFID : Removed Tag");
+ addLog(LOG_LEVEL_INFO, log);
+ sendData(event);
+ success = true;
+ }
+ break;
+ }
case PLUGIN_SERIAL_IN:
{
@@ -125,14 +155,21 @@ boolean Plugin_040(byte function, struct EventStruct *event, String& string)
event->sensorType = Device[DeviceIndex].VType;
// endof workaround
- unsigned long key = 0;
+ unsigned long key = 0, old_key = 0;
+ old_key = ((uint32_t) UserVar[event->BaseVarIndex]) | ((uint32_t) UserVar[event->BaseVarIndex + 1])<<16;
for (byte i = 1; i < 5; i++) key = key | (((unsigned long) code[i] << ((4 - i) * 8)));
- UserVar[event->BaseVarIndex] = (key & 0xFFFF);
- UserVar[event->BaseVarIndex + 1] = ((key >> 16) & 0xFFFF);
- String log = F("RFID : Tag: ");
+ String log = F("RFID : ");
+ if (old_key != key) {
+ UserVar[event->BaseVarIndex] = (key & 0xFFFF);
+ UserVar[event->BaseVarIndex + 1] = ((key >> 16) & 0xFFFF);
+ sendData(event);
+ setPluginTaskTimer(500, event->TaskIndex, event->Par1);
+ log += F("New Tag: ");
+ } else {
+ log += F("Old Tag: ");
+ }
log += key;
addLog(LOG_LEVEL_INFO, log);
- sendData(event);
}
}
success = true;
@uzi18 I added the syntax highligher diff
to your post, makes it easier to read.
The timer to erase the value is set to 500 msec. in your code. Isn't it better to make it configurable? I can imagine it may take a while sometimes to process long rules when comparing against a number of allowed keys.
@TD-er if you look at logs from @sa-wo rfid reader report tag every 70-80 ms if in range, so 500ms is far optimistic in my opinion.
OK, then leave it like that and if someone ever runs into it, we can always make it configurable. Maybe just add a comment to this line then :)
of course, have also looked at our other rfid plugin, we should add simmilar behavior to have consistent environment.
@TD-er do you think UserVar could be anonymous union or something like that? So in some situations we could access bytes of float directly without voodoo magic?
So in some situations we could access bytes of float directly without voodoo magic?
Well it is not shared among platforms. I think we can do it, but make sure to add an assert to check its size at compile time.
Maybe a separate function (or class) to handle all these bit manipulations is a more backwards compatible solution.
The most elegant solution would be to have a single object representing all UserVar values of a single task with get/set functions for each of them. But that does require change in code of all existing plugins and most controllers.
So the second best would be a get/set class that can interact with this UserVar array and then you can call those from all plugin/controller code you wish to upgrade.
This can then also be used on other code that needs to store data in limited sized variables like we now do in the Dallas plugin and the places in the code using functions like getBitFromUL
(or however it is called)
@TD-er there is a workaround above 125 line is it still needed? If remember correctly there was some fixes for this in time of development of esteron plugin.
You mean this code?
// temp woraround, ESP Easy framework does not currently prepare this...
taskIndex_t index = INVALID_TASK_INDEX;
for (taskIndex_t y = 0; y < TASKS_MAX; y++)
if (Settings.TaskDeviceNumber[y] == PLUGIN_ID_040)
index = y;
const deviceIndex_t DeviceIndex = getDeviceIndex_from_TaskIndex(index);
if (!validDeviceIndex(DeviceIndex)) {
break;
}
event->TaskIndex = index;
event->BaseVarIndex = index * VARS_PER_TASK;
if (!validUserVarIndex(event->BaseVarIndex)) {
break;
}
event->sensorType = Device[DeviceIndex].VType;
// endof workaround
The place where PLUGIN_SERIAL_IN
is called, it is not yet known what plugin may process this data from the serial port.
So it seems still needed.
It is not really an elegant way of handling data from the serial port, so we may later add some handler to process this kind of data.
Right now, it does seem like it was meant to allow both serial logging and receiving commands via serial + allow a card reader to be present. Thus we have different ways plugins interact with the serial port:
The second one does allow for selecting a serial port (even SW serial or the recently added I2C serial)
@TD-er so in PLUGIN_TIMER_IN we also need this workaround?
void process_plugin_task_timer(unsigned long id) {
START_TIMER;
const systemTimerStruct timer_data = systemTimers[id];
struct EventStruct TempEvent;
TempEvent.TaskIndex = timer_data.TaskIndex;
TempEvent.Par1 = timer_data.Par1;
TempEvent.Par2 = timer_data.Par2;
TempEvent.Par3 = timer_data.Par3;
TempEvent.Par4 = timer_data.Par4;
TempEvent.Par5 = timer_data.Par5;
// TD-er: Not sure if we have to keep original source for notifications.
TempEvent.Source = VALUE_SOURCE_SYSTEM;
const deviceIndex_t deviceIndex = getDeviceIndex_from_TaskIndex(timer_data.TaskIndex);
/*
String log = F("proc_system_timer: Pluginid: ");
log += deviceIndex;
log += F(" taskIndex: ");
log += timer_data.TaskIndex;
log += F(" sysTimerID: ");
log += id;
addLog(LOG_LEVEL_INFO, log);
*/
systemTimers.erase(id);
if (validDeviceIndex(deviceIndex)) {
String dummy;
Plugin_ptr[deviceIndex](PLUGIN_TIMER_IN, &TempEvent, dummy);
}
STOP_TIMER(PROC_SYS_TIMER);
}
As you can see, the TaskIndex
is preserved, but if you need the BaseVarIndex
and/or `sensorType, then it should be set in this code I showed here.
Edit:
For example P091_SerSwitch
does set the BaseVarIndex
, which should have been set in this code calling the PLUGIN_TIMER_IN
@sa-wo this one: firmware(4).bin.zip
@TD-er not sure if we realy need validUserVarIndex() check
diff --git a/src/Scheduler.ino b/src/Scheduler.ino
index e474398c..cd61b157 100644
--- a/src/Scheduler.ino
+++ b/src/Scheduler.ino
@@ -419,6 +419,7 @@ void process_plugin_task_timer(unsigned long id) {
const systemTimerStruct timer_data = systemTimers[id];
struct EventStruct TempEvent;
TempEvent.TaskIndex = timer_data.TaskIndex;
+ TempEvent.BaseVarIndex = timer_data.TaskIndex * VARS_PER_TASK;
TempEvent.Par1 = timer_data.Par1;
TempEvent.Par2 = timer_data.Par2;
TempEvent.Par3 = timer_data.Par3;
@@ -440,7 +441,8 @@ void process_plugin_task_timer(unsigned long id) {
*/
systemTimers.erase(id);
- if (validDeviceIndex(deviceIndex)) {
+ if (validDeviceIndex(deviceIndex) && validUserVarIndex(TempEvent.BaseVarIndex)) {
+ TempEvent.sensorType = Device[deviceIndex].VType;
String dummy;
Plugin_ptr[deviceIndex](PLUGIN_TIMER_IN, &TempEvent, dummy);
}
In that part of the code we don't as it is a valid TaskIndex, so you know for sure you will not be out of range for the UserVar array. On the other hand, it is quite a simple check and the call for this function is not done a lot per second.
Hi first of all. do you use f.ex IOBroker or ESP as a stand alone Reader? I am using it with IObroker and Espeasy. I use dummy device for testing if it is connected to the broker or not. If not connected i am working with timers. Checking if it is in Reboot (no weird things during boot possible), Count of allowed and not allowed Cards (only with Broker alive, because this is done by broker) and so on.. Having no Problems with openning .
Rules (using 3 of the possible 4) on System#Boot do TaskValueSet,10,4,1 TaskValueSet,9,1,1 GPIO,5,1 TaskValueSet,9,2,1 timerSet,1,600 endon
on MQTT#Connected do Publish %sysname%/status/IP,%ip% Publish,%sysname%/Reset/status,1 Publish,%sysname%/RFID/status,[status2#Wert2] TaskValueSet,9,1,[status2#Wert2] Publish,%sysname%/alive/status,0 endon
on switch#Wert3 do If %eventvalue% = 1 TaskValueSet,10,4,0 Publish,%sysname%/Reset/status,0 endif endon
on RFID#Tag do if [status1#Boot_status]=0 and [status2#alive]=0 --> allowed/not allowed triggerd by Broker TaskValueSet,12,4,1 endif if [status2#alive]=1 ----> 1 means no connection to broker ;-) so this will be your way TaskValueSet,12,4,1 event,RFIDCHECK endif EndOn
On switch#Wert4 Do If [switch#Wert4]=1 event,rfidok endif If [switch#Wert4]=2 event,rfidnook endif //If [switch#Wert4]=0 // event,rlsaus //endif endon
on zaehlerreset do TaskValueSet,10,1,0 TaskValueSet,10,2,0 Publish,%sysname%/RFID_Zaehler/ok,[status1#ok_z] Publish,%sysname%/RFID_Zaehler/nook,[status1#nook_z] endon
On Rules#Timer=1 do
TaskValueSet,9,1,1
Publish,%sysname%/alive/status,1
timerSet,1,600
endon
on switch#Wert2 do If [switch#Wert2]=1 and [status1#Boot_status]=0 TaskValueSet,9,1,0 //timerSet,1,600 Publish,%sysname%/alive/status,0 EndIf Endon
On RFID_anaus#state do If [RFID_anaus#state]=0 event,rfidtoggle EndIf EndOn
on rfidtoggle do If [status2#Wert2]=1 GPIO,5,0 TaskValueSet,9,2,0 Publish,%sysname%/RFID/status,[status2#Wert2] else GPIO,5,1 TaskValueSet,9,2,1 Publish,%sysname%/RFID/status,[status2#Wert2] endif endon
On switch#Wert1 Do If [switch#Wert1]=1 event,rfidtoggle EndIf endon
on rfidok do if [status1#Boot_status]=0 and [status#Status]=1 GPIO,13,0 TaskValueSet,12,3,0 Publish,%sysname%/Fehler/status,0 GPIO,14,1 TaskValueSet,12,1,1 Publish,%sysname%/RLS/status,1 GPIO,12,1 TaskValueSet,12,2,1 Publish,%sysname%/RFID_OK/status,1 TaskValueSet,10,1,[status1#ok_z]+1 Publish,%sysname%/RFID_Zaehler/ok,[status1#ok_z] endif timerSet,2,2 endon
on rfidnook do If [status#Status]=1 GPIO,14,0 TaskValueSet,12,1,0 Publish,%sysname%/RLS/status,0 GPIO,12,0 TaskValueSet,12,2,0 Publish,%sysname%/RFID_OK/status,0 GPIO,13,1 TaskValueSet,12,3,1 Publish,%sysname%/Fehler/status,1 TaskValueSet,10,2,[status1#nook_z]+1 Publish,%sysname%/RFID_Zaehler/nook,[status1#nook_z] endif endon
on rlsaus do GPIO,14,0 TaskValueSet,12,1,0 Publish,%sysname%/RLS/status,0 GPIO,12,0 TaskValueSet,12,2,0 Publish,%sysname%/RFID_OK/status,0 GPIO,13,0 TaskValueSet,12,3,0 Publish,%sysname%/Fehler/status,0 TaskValueSet,12,4,0 TaskValueSet,10,3,0 EndOn
On RFIDCHECK do If [RFID#Tag]=1234567 event,rfidnot endif If [RFID#Tag]=1234568 event,rfidnot endif If [RFID#Tag]=1234569 event,rfidnot endif timerSet,3,4 endon
on rfidnot do if [status1#Boot_status]=0 and [status1#sperre]=0 If [status#Status]=1 GPIO,14,1 TaskValueSet,12,1,1 Publish,%sysname%/RLS/status,1 GPIO,12,1 TaskValueSet,12,2,1 Publish,%sysname%/RFID_OK/status,1 TaskValueSet,10,3,1 endif endif timerSet,2,2 endon
On Rules#Timer=2 do event,rlsaus endon
On Rules#Timer=3 do Publish,%sysname%/RFID/Tag,0 endon
@fraeggle did you tried my modified firmware or are you using original from release?
original mega-20200310
you have to use a timer or something to avoid multiple readings. but that is not a issue from espeasy, because the rdm6300 is reading the id as long as a card is in range, so your relais is being toggled all the time. (Works as designed). if the id was not read in all the time, you could never trigger an event with the same card one after the other, but you might have to take another id first. With a timer (as I solved it) you can also decide how long e.g. no other id can be read in or how long e.g. a relay should be activated.
Btw i learned not to use switch for an output or what you use the switch for? in my rules rfidnot means rfid "emergency" (No connection to broker, it has to handle the id's by itself)
Hi, I have an issue with a RDm6300 rfid reader, I have already discussed this topic here https://www.letscontrolit.com/forum/viewtopic.php?f=4&t=7549&p=43527#p43527
My current setup is:
It seams that the reading interval of the rdm6300 is to high, even when I hold the tag in front of the reader is will recognize it several times, which will cause the relais turn off and on serveral times.
We tried setting up different rules, nothing worked. This is my current rule:
on rfid_tag_water#Tag=3364040 do timerSet,1,2 Let,1,[water_pump#On] gpio,4,[VAR#1#!Z] endon
On Rules#Timer=1 do TaskValueSet,1,1,0 endon
It there a way to reduce the interval? THX sawo