Extra command message type for local data requests
-
Every now and then i'd think about sensors which rely on data from other sensors/nodes.
The current way of gathering this data, is request the data direct from the other MySensors-node using the message command type "req" (see api: https://www.mysensors.org/download/serial_api_20) This limits the data gathering to MySensors nodes.
My proposal would be to extend the message API with an additional message command type called "localrequest"
where the payload of this command holds the unique device id as known by the HA-controller (each HA has such ID's)A localrequest message would look like this:
30;1;5;0;15;215\n
requesting node id (reply-to node);child id (reply-to sensor id);localrequest-command;nack;V_ARMED;HA-unique ID\n
By having this localrequest command and using the unique HA-ID all devices connected to this HA can provide data to the MySensors nodes. At least for Vera this will work fine. (i can provide the correct code for the Vera plugin)
This localrequest will also work for data provided by battery powered nodes which are sleeping most of their time.
-
@BartE I had (and maybe have) a similar need. Domoticz does something like that with S_CUSTOM which can request all kinds of data from the the controller. I have 'solved' it by duplicating the data with a controller script to a sensor specific 'dummy sensor' so that it can be retrieved with a request from the controller.
Problem with having a controller dependent number would be 'controller dependency' so I'm not sure...
(and a better name would be 'controllerRequest' )
-
@AWI i was actually referring to an additional "command" (third byte) and not a V-type.
The V-type should represent the type of value which is requested from the controller. HA controller like Vera need the message type to be able to retrieve the data.ControlleRequest is indeed a better name than local request.
Using V_CUSTOM could be an alternative. with the first payload byte the request V-type followed by and HA Controller ID.
I can make a prototype with this implementation.
-
OK i did make a prototype implementation using the V_CUSTOM message type.
This works for Vera only.I had to change only one file: L_Arduino.lua
The function starting on line 244 has te be extened with this if statement:-- Handle Local Request variables if (varType == "CUSTOM") then local bit = require("bit") local varReqIndex = bit.band(tonumber(value), 0xFF); local varVeraId = bit.rshift(tonumber(value), 8); local varReqType = tVarLookupNumType[varReqIndex] local varReq = tVarTypes[varReqType] if (varReq[2] ~= nil) then log("Local request '" .. varReq[3] .. "' from Device ID: ".. varVeraId .. " sensor type '" .. varReqType .. "'") local localValue = luup.variable_get(varReq[2], varReq[3], varVeraId) if (localValue ~= nil) then -- Send variable value to actuator sendRequestResponse(nodeId .. ";" .. childId, varReqType, localValue) end end else
The complete function will then look like this:
local function setVariable(incomingData, childId, nodeId) if (childId ~= nil) then -- Set variable on child sensor. local index = tonumber(incomingData[5]); local varType = tVarLookupNumType[index] local var = tVarTypes[varType] local value = incomingData[6] local timestamp = os.time() -- Handle Local Request variables if (varType == "CUSTOM") then local bit = require("bit") local varReqIndex = bit.band(tonumber(value), 0xFF); local varVeraId = bit.rshift(tonumber(value), 8); local varReqType = tVarLookupNumType[varReqIndex] local varReq = tVarTypes[varReqType] if (varReq[2] ~= nil) then log("Local request '" .. varReq[3] .. "' from Device ID: ".. varVeraId .. " sensor type '" .. varReqType .. "'") local localValue = luup.variable_get(varReq[2], varReq[3], varVeraId) if (localValue ~= nil) then -- Send variable value to actuator sendRequestResponse(nodeId .. ";" .. childId, varReqType, localValue) end end elseif (var[2] ~= nil) then log("Setting variable '".. var[3] .. "' to value '".. value.. "'") setVariableIfChanged(var[2], var[3], value, childId) -- Handle special variables battery level and tripped which also -- should update other variables to os.time() if (varType == "TRIPPED" and value == "1") then local variable = tVeraTypes["LAST_TRIP"] setVariableIfChanged(variable[2], variable[3], timestamp, childId) else local variable = tVeraTypes["LAST_UPDATE"] setVariableIfChanged(variable[2], variable[3], timestamp, childId) end end -- Always update LAST_UPDATE for node if (nodeId ~= nil) then local nodeDevice = childIdLookupTable[nodeId .. ";" .. NODE_CHILD_ID] setLastUpdate(nodeDevice) end end end
Now the Vera HA-contoller response on V_CUSTOM messages.
Use the feature in a MySensors node:
void requestValue(byte type, unsigned int id) { MyMessage msgRequest(1, V_CUSTOM); unsigned long msgData; msgData = type + ((unsigned long)id * 0x100); send(msgRequest.set(msgData)); } void loop() { // Request the status from Vera Device 4 requestValue(V_STATUS, 4); // Request the dimn level from Vera Device 20 requestValue(V_LEVEL, 20); // etc.. }
Make sure you can handle the incoming messages
void receive(const MyMessage &message) { if (message.type==V_STATUS) { Serial.print(" New value: "); Serial.println(message.getBool()); } if (message.type==V_LEVEL) { Serial.print(" New value: "); Serial.println(message.getByte()); } if (message.type==V_TEMP) { Serial.print(" New value: "); Serial.println(message.getFloat()); } }
If you need the same value type from different Device a different sensor id can be used, the requestValue will then look like this:
void requestValue(byte type, unsigned int id, byte sensorid) { MyMessage msgRequest(sensorid, V_CUSTOM); unsigned long msgData; msgData = type + ((unsigned long)id * 0x100); send(msgRequest.set(msgData)); }
In the receive function "message.sensor" can be used to determine for which device a request was made