Page 1 of 1

BUG: dzvents: customEvent.data table value is returned as string

Posted: Monday 01 June 2020 22:27
by rrozema
Version: 2020.2 (build 12067)
Build Hash: 0fc3c7b70
Compile Date: 2020-05-17 13:15:45
dzVents Version: 3.0.5
Python Version: 3.7.3 (default, Dec 20 2019, 18:57:59) [GCC 8.3.0]

https://www.domoticz.com/wiki/DzVents:_ ... nd_methods
If I put a table variable in the 2nd variable [extra data] of emitEvent(name,[extra data]), that variable is of type string when the event triggers. In below code, the values of object.data.idx, object.data.bState and object.data.lastUpdate all equal nil. This is because object.data is of type "string", instead of type "table" that it was when it was emitted.

Code: Select all

domoticz.emitEvent('myTestEvent', { idx = object.idx, bState = object.bState, lastUpdate = object.lastUpdate } )
When the trigger fires, the value of data is no longer of type table. It is now "{"bState":true,"idx":552,"lastUpdate":{"addDays":"Function","addHours":"Function","addMinutes":"Function","addSeconds":"Function","compare":"Function","current":{"day":1,"hour":22,"isdst":true,"min":21,"month":6,"sec":28,"wday":2,"yday":153,"year":2020},"dDate":1591042886,"day":1,"dayAbbrOfWeek":"mon","dayName":"Monday","daysAgo":0,"getISO":"Function","hour":22,"hoursAgo":0,"isToday":true,"isUTC":false,"isdst":true,"makeTime":"Function","matchesRule":"Function","milliSeconds":0,"milliseconds":0,"millisecondsAgo":2995,"min":21,"minutes":21,"minutesAgo":0,"minutesSinceMidnight":1341,"month":6,"monthAbbrName":"jun","monthName":"June","msAgo":2995,"raw":"2020-06-01 22:21:26","rawDate":"2020-06-01","rawDateTime":"2020-06-01 22:21:26","rawTime":"22:21:26","ruleIsAfterCivilTwilightEnd":"Function","ruleIsAfterCivilTwilightStart":"Function","ruleIsAfterSunrise":"Function","ruleIsAfterSunset":"Function","ruleIsAtCivilDayTime":"Function","ruleIsAtCivilNightTime":"Function","ruleIsAtCivilTwilightEnd":"Function","ruleIsAtCivilTwilightStart":"Function","ruleIsAtDayTime":"Function","ruleIsAtNight":"Function","ruleIsAtSunrise":"Function","ruleIsAtSunset":"Function","ruleIsBeforeCivilTwilightEnd":"Function","ruleIsBeforeCivilTwilightStart":"Function","ruleIsBeforeSunrise":"Function","ruleIsBeforeSunset":"Function","ruleIsInWeek":"Function","ruleIsOnDate":"Function","ruleIsOnDay":"Function","ruleMatchesBetweenRange":"Function","ruleMatchesHourSpecification":"Function","ruleMatchesMinuteSpecification":"Function","ruleMatchesTime":"Function","ruleMatchesTimeRange":"Function","sec":26,"seconds":26,"secondsAgo":2,"secondsSinceMidnight":80486,"time":"22:21","utils":{"DZVERSION":"3.0.5","LOG_DEBUG":4,"LOG_ERROR":1,"LOG_FORCE":0.5,"LOG_INFO":3,"LOG_MODULE_EXEC_INFO":2,"cameraExists":"Function","centerPad":"Function","deviceExists":"Function","dumpSelection":"Function","dumpTable":"Function","fileExists":"Function","fromBase64":"Function","fromJSON":"Function","fromXML":"Function","groupExists":"Function","hsbToRGB":"Function","inTable":"Function","isJSON":"Function","isXML":"Function","leadingZeros":"Function","leftPad":"Function","log":"Function","numDecimals":"Function","osExecute":"Function","print":"Function","rgbToHSB":"Function","rightPad":"Function","round":"Function","sceneExists":"Function","setLogMarker":"Function","stringSplit":"Function","stringToSeconds":"Function","toBase64":"Function","toCelsius":"Function","toJSON":"Function","toXML":"Function","urlDecode":"Function","urlEncode":"Function","variableExists":"Function"},"wday":2,"week":23,"yday":153,"year":2020}}"

I do see that this is a json, so I will be able to convert it back into a table. But the point is: I shouldn't have to. I assigned a table, so I expect to receive a table.

Here's the code I used to verify this behavior:

Code: Select all

return {
	on = {
		devices = {
		    "myTest"
		},
		customEvents = {
			"myTestEvent*"
		}
	},
    execute = function(domoticz, object, triggerInfo)
        if object.isDevice then
            domoticz.log('Device ' .. object.name .. ': state ' ..tostring(object.bState).. '.', domoticz.LOG_FORCE)
            if object.bState == true then
                domoticz.emitEvent('myTestEvent', { idx = object.idx, bState = object.bState, lastUpdate = object.lastUpdate } ).afterSec(15)
--                domoticz.emitEvent( "myTestEvent" ).afterSec(30)
            end
        elseif object.isCustomEvent then
            domoticz.log('CustomEvent, ' .. type(object) .. '.', domoticz.LOG_ERROR)
            domoticz.log('CustomEvent, "' .. object.data .. '".', domoticz.LOG_ERROR)
            --domoticz.utils.dumpTable(object)
            domoticz.log('CustomEvent, ' .. type(object.data) .. ', idx = '.. tostring(object.data.idx) .. ', bState = ' ..tostring( object.data.bState) .. '.', domoticz.LOG_ERROR)
            if object.data == nil then
                domoticz.log('CustomEvent, data is nil.', domoticz.LOG_ERROR)
            elseif object.data.idx == nil then
                domoticz.log('CustomEvent, data.idx is nil.', domoticz.LOG_ERROR)
            else
                local dev = domoticz.devices(object.data.idx)
                if dev == nil then
                    domoticz.log('CustomEvent, device ' .. tostring(domoticz.data.idx) .. ' not found.', domoticz.LOG_ERROR)
                else
                    if dev.bState == object.data.bState and dev.lastUpdate == object.data.lastUpdate then
                        domoticz.log('CustomEvent, device ' .. dev.name .. ' is still on.', domoticz.LOG_FORCE)
                    else
                        domoticz.log('CustomEvent, device ' .. dev.name .. ' is off.', domoticz.LOG_FORCE)
                    end
                end
            end
        else
            domoticz.log( "unexpected trigger type.", domoticz.LOG_FORCE)
        end
	end
}

Re: BUG: dzvents: customEvent.data table value is returned as string

Posted: Tuesday 02 June 2020 1:15
by waaren
rrozema wrote: Monday 01 June 2020 22:27 I do see that this is a json, so I will be able to convert it back into a table. But the point is: I shouldn't have to. I assigned a table, so I expect to receive a table.
From the wiki:

json. Table. 3.0.3 When the customEvent data is a valid json string, the response data is automatically converted to a Lua table for quick and easy access.

check below (tested on dzVents 3.0.8):

Code: Select all

return {
	on = {
		devices = {
		    "customEventTrigger"
		},
		customEvents = {
			"myTestEvent*"
		}
	},
    execute = function(domoticz, object, triggerInfo)
        if object.isDevice then
            domoticz.log('Device ' .. object.name .. ': state ' ..tostring(object.bState).. '.', domoticz.LOG_FORCE)
            if object.bState == true then
                domoticz.emitEvent('myTestEvent', { idx = object.idx, bState = object.bState, lastUpdate = object.lastUpdate } ).afterSec(15)
--                domoticz.emitEvent( "myTestEvent" ).afterSec(30)
            end
    elseif object.isCustomEvent then
            domoticz.log('CustomEvent, ' .. type(object) .. '.', domoticz.LOG_FORCE)
            domoticz.log('CustomEvent.json, ' .. type(object.json) .. ', idx = '.. tostring(object.json.idx) .. ', bState = ' ..tostring( object.json.bState) .. '.', domoticz.LOG_FORCE)
            if object.json == nil then
                domoticz.log('CustomEvent, json is nil.', domoticz.LOG_FORCE)
            elseif object.json.idx == nil then
                domoticz.log('CustomEvent, json.idx is nil.', domoticz.LOG_FORCE)
            else
                local dev = domoticz.devices(object.json.idx)
                if dev == nil then
                    domoticz.log('CustomEvent, device ' .. tostring(domoticz.json.idx) .. ' not found.', domoticz.LOG_FORCE)
                else
                    if dev.bState == object.json.bState and dev.lastUpdate == object.json.lastUpdate then
                        domoticz.log('CustomEvent, device ' .. dev.name .. ' is still on.', domoticz.LOG_FORCE)
                    else
                        domoticz.log('CustomEvent, device ' .. dev.name .. ' is off.', domoticz.LOG_FORCE)
                    end
                end
            end
        else
            domoticz.log( "unexpected trigger type.", domoticz.LOG_FORCE)
        end
	end
}
log:

Code: Select all

2020-06-02 01:11:14.312  Status: dzVents: Info: Handling events for: "customEventTrigger", value: "On"
2020-06-02 01:11:14.312  Status: dzVents: Info: ------ Start internal script: 20200602 dz customEvent json: Device: "customEventTrigger (Virtual)", Index: 222
2020-06-02 01:11:14.313  Status: dzVents: !Info: Device customEventTrigger: state true.
2020-06-02 01:11:14.314  Status: dzVents: Info: ------ Finished 20200602 dz customEvent json

2020-06-02 01:11:29.377  Status: dzVents: Info: Handling Domoticz custom event for: "myTestEvent"
2020-06-02 01:11:29.377  Status: dzVents: Info: ------ Start internal script: 20200602 dz customEvent json: Custom event: "myTestEvent"
2020-06-02 01:11:29.379  Status: dzVents: !Info: CustomEvent, table.
2020-06-02 01:11:29.379  Status: dzVents: !Info: CustomEvent.json, table, idx = 222, bState = true.
2020-06-02 01:11:29.385  Status: dzVents: !Info: CustomEvent, device customEventTrigger is off.
2020-06-02 01:11:29.385  Status: dzVents: Info: ------ Finished 20200602 dz customEvent json

Re: BUG: dzvents: customEvent.data table value is returned as string

Posted: Tuesday 02 June 2020 8:35
by rrozema
waaren wrote: Tuesday 02 June 2020 1:15 From the wiki:

json. Table. 3.0.3 When the customEvent data is a valid json string, the response data is automatically converted to a Lua table for quick and easy access.
Thanks for the sample code, that should work great. Much appreciated!

The quoted piece of wiki however doesn't cover my problem area: the [extra data] I put in isn't a valid json string, it is a table.

I suggest to add a mention of the table to json conversion behavior within the emitEvent() function:
emitEvent(name,[extra data ]):Function. 3.0.0 Have Domoticz ‘call’ a customEvent. If you just pass a name then Domoticz will execute the script(s) that subscribed to the named customEvent after your script has finished. You can optionally pass extra information as a string or table. If you pass in a table, that table will be automatically converted into a json string. Supports command options.
And add another bit of information in the 'Sections of the script' part to clarify that the data can be retrieved from the json or the xml property as a LUA table, while the data property holds the json or xml string:
  • data: Raw customEvent data.
  • isJSON: Boolean.3.0.3 true when the customEvent data is a valid json string.
  • isXML: Boolean.3.0.3 true when the customEvent data is a valid xml string.
  • json. Table.3.0.3 If isJSON is true, json will hold the extra data passed in, converted into a LUA table for quick and easy access. nil if isJSON is not true.
  • trigger, customEvent: String.3.0.3 The string that triggered this customEvent instance. This is useful if you have a script that is triggered by multiple different customEvent strings.
  • xml. Table. 3.0.3 If isXML is true, xml will hold the extra data passed in, converted into a Lua table for quick and easy access. nill if isXML is not true.

Re: BUG: dzvents: customEvent.data table value is returned as string  [SOLVED]

Posted: Tuesday 02 June 2020 11:50
by waaren
rrozema wrote: Tuesday 02 June 2020 8:35 I suggest to add a mention of the table to json conversion behavior within the emitEvent() function:
Will do.