RoomMe - Presence Detector

I’ve worked out that I can use the following code to get rid of the backslashes

local str = [[ {\"type\": \"Event\",\"userId\": 0, \"userName\": \"Joe\", \"roomName\": \"Living Room\", \"sensorId\": \"98072D0B9B72\", \"event\": {\"name\": \"RoomEntry\", \"inControl\": true}} ]]

print(str:gsub("\\", ""))

You’re working too hard at it. In the original code as I first gave it to you, just change the function’s beginning to:

function RoomMeHandler( req, params, outputfmt )
    local data = params
    if "RoomEntry" == data.event then
        -- and continue with the rest of the function

It seems there’s slightly different behavior in the handling of params depending on what else is in the query (e.g. if there are additional query params, more work needed). When I was testing, I happened to have other query parameters on the request, where you do not.

By the way, what firmware are you running? I wonder if there’s a change there as well…

Thanks again @rigpapa, I’ll give that a go…

In regards to…

It says I’m - “running the latest version 1.7.5186 (7.31)

Hey @rigpapa

I really couldn’t get the handler function to work as cleanly as you were expecting. For some reason the json POST is coming into the function with extra bits added at the front and back, plus it’s full of backslashes.

The json content/format I send via the HTTP Post script shared earlier.

{"type": "Event","userId": 0, "userName": "Joe", "roomName": "Living Room", "sensorId": "98072D0B9B72", "event": {"name": "RoomEntry", "inControl": true}}

Here’s the json content/format that the handler/function receives…

 {"{\"type\": \"Event\",\"userId\": 0, \"userName\": \"Joe\", \"roomName\": \"Living Room\", \"sensorId\": \"98072D0B9B72\", \"event\": {\"name\": \"RoomEntry\", \"inControl\": true}}":""}

To process the above here’s the updated code for the RoomMe handler function so it can now also re-format the json received so its in the valid format.


function RoomMeHandler( req, params, outputfmt )
    luup.log("RoomMe Starting")
	local json = require( 'dkjson' ) -- typical/default JSON parser for Veras
	
	luup.log( "debug start " )
	luup.log( "check req = " .. tostring(req) )
	luup.log( "check params = " .. tostring( params) )
	luup.log( "check outputfmt = " .. tostring( outputfmt) )
	luup.log( "Formatting the RoomMe json " )
	local paramsV1 = json.encode( params )
	luup.log( "paramsV1 - Original format with extras and backslashes = " .. tostring(paramsV1))
	local paramsV2 = paramsV1:gsub("\\", "")
	-- luup.log( "paramsV2 - Removing the backslashes = " .. tostring(paramsV2))
	local paramsV3 = paramsV2:sub(3)
	-- luup.log( "paramsV3 = Trimming the start to remove unnecessary characters = " .. tostring(paramsV3))
	local paramsV4 = paramsV3:sub(1, -6)
	-- luup.log( "paramsV4 = Trimming the end to remove unnecessary characters = " .. paramsV4)
	local paramsV5 = tostring(paramsV4)
	luup.log( "paramsV5 - Final format with all extras and backslashes removed = " .. tostring(paramsV5))
	luup.log( "debug end " )
	
	local j = json.decode(paramsV5)
	local Type, userId, userName, roomName, sensorId, eventName, eventControl = j.type, j.userId, j.userName, j.roomName, j.sensorId, j.event.name, j.event.inControl

    if "RoomEntry" == eventName then
		luup.log( userName .. " has entered the " .. roomName)
        -- Add your code here to handle a RoomEntry event
    elseif "RoomExit" == eventName then
		luup.log( userName .. " has exited the " .. roomName )
        -- Add your code here to handle a RoomExit event
    else
        -- Unhandled event type (use of tostring() is defensive/guard nil)
        luup.log( "Ignoring unhandled event " )
        return "Ignored unhandled event", "text/plain"
    end
    return "OK", "text/plain"
end

Now whenever I run a HTTP Post with the required RoomMe APi json file, the following shows what is captured in the luup log.

50	07/30/21 0:17:44.299	luup_log:0: RoomMe Starting <0x74946520>
50	07/30/21 0:17:44.299	luup_log:0: debug start  <0x74946520>
50	07/30/21 0:17:44.299	luup_log:0: check req = RoomMe <0x74946520>
50	07/30/21 0:17:44.300	luup_log:0: check params = table: 0xc6fad8 <0x74946520>
50	07/30/21 0:17:44.300	luup_log:0: check outputfmt =  <0x74946520>
50	07/30/21 0:17:44.300	luup_log:0: Formatting the RoomMe json  <0x74946520>
50	07/30/21 0:17:44.301	luup_log:0: paramsV1 - Original format with extras and backslashes = {"{\"type\": \"Event\",\"userId\": 0, \"userName\": \"Joe\", \"roomName\": \"Living Room\", \"sensorId\": \"98072D0B9B72\", \"event\": {\"name\": \"RoomEntry\", \"inControl\": true}}":""} <0x74946520>
50	07/30/21 0:17:44.301	luup_log:0: paramsV5 - Final format with all extras and backslashes removed = {"type": "Event","userId": 0, "userName": "Joe", "roomName": "Living Room", "sensorId": "98072D0B9B72", "event": {"name": "RoomEntry", "inControl": true}} <0x74946520>
50	07/30/21 0:17:44.301	luup_log:0: debug end  <0x74946520>
50	07/30/21 0:17:44.303	luup_log:0: Joe has entered the Living Room <0x74946520>

What are your thoughts, can it be Improved ?

I’m thinking the addition of the post_data key to params in this instance, which is what I’m seeing, is new for 7.32, because it’s not in yours but is in mine (I’m on 7.32), and makes this much easier than what you’re doing here. Do what you must to get the result you want.

Thanks again @rigpapa

What do you mean by post_data ? and also how do I get 7.32 when the console is telling me it’s on the latest version.

FYI - I also tried to send the json via a curl command too (below)…

curl -i -X POST -H "Content-Type: application/json" -d '{"type": "Event","userId": 0, "userName": "Joe", "roomName": "Living Room", "sensorId": "98072D0B9B72", "event": {"name": "RoomEntry", "inControl": true}}' http://192.168.102.10:3480/data_request?id=lr_RoomMe

… and the handler function still received the same extended and backslash converted json content…

Looking at that function’s parameters req, params, outputfmt, do I need all of them specified ?

It’s “beta” firmware thread here.

Thanks @cw-kid

That looks a big update, but following your link, the subsequent firmware links returns a “404 Not Found” message…

Yes I thought the links might be dead.

You’ll have to scan the rest of the thread, I think other links were posted.

Thanks @cw-kid - I found one further down the thread…

My next question for the forum is what device category should I use for a ‘presence sensor’ ? Something that is ultimately either on (a specif person is present) or off (that person is no longer there)

http://wiki.micasaverde.com/index.php/Luup_Device_Categories

A virtual motion sensor maybe? Or just a switch.

Yes, I also like the idea (although not sure how to do it) of using a ‘Security Sensor’ (cat 4) ‘Binary Sensor’ (subcat 8)

You can easily add your own virtual devices with an uploaded implementation file, I’ve posted how to do it before on the forum.

Or there are some plugins for creating virtual devices.

It’s then just a case of setting thst virtual devices variable to a 1 or 0 for tripped or not tripped or on or off etc.

Thanks, I’ll look into that too - for now I’m continuing to try and create, what I’m calling ‘Information Widgets’ for Vera, (Static JSON files for devices - templates/examples? - #11 by parkerc ) which aim to just be a single block of code in the start up (or one uploaded luup.file.)

So in this case other than creating the luup.register handler, everything needed to maintain the RoomMe widget on the dashboard will ideally be in a single luup file called a xxRoomMe.lua.

I use the following luup.create_device call to create a device with its required variables, and then each time a http post is received, it will check if that device exists, and if so, it will update the variables.

Here a test script of a RoomMe detector device initial creation, its currently using the D_GenericIO1.xml but I’ll explore other ones.

-- example json content sent by the RoomMe API
local Type = "Event"
local userId = 0
local id = "myregisteredemail@mail.com"
local userName = "parkerc"
local roomName = "Kitchen"
local eventTime = "2021-07-30T20:55:11 01:00"
local sensorId = "5C63C900117A"
local eventName = "RoomExit"
local eventControl = ""

-- Create a RoomMe Presence device with all associated variables
luup.create_device("", userName, "RoomMe Presence Widget", "D_GenericIO1.xml", "", "", "", false, false, 0, 0, 0, "urn:nodecentral-net:serviceId:RoomMe1,userId="..userId.."\nurn:nodecentral-net:serviceId:RoomMe1,id="..id.."\nurn:nodecentral-net:serviceId:RoomMe1,userName="..userName.."\nurn:nodecentral-net:serviceId:RoomMe1,roomName="..roomName.."\nurn:nodecentral-net:serviceId:RoomMe1,eventTime="..eventTime.."\nurn:nodecentral-net:serviceId:RoomMe1,sensorId="..sensorId.."\nurn:nodecentral-net:serviceId:RoomMe1,eventName="..eventName.."\nurn:nodecentral-net:serviceId:RoomMe1,eventControl="..eventControl.."\nurn:nodecentral-net:serviceId:RoomMe1,Version=v0.1\n,manufacturer=NodeCentral", 0, "", "", true, false)
1 Like

And with all this you’re over 80% of the way to having written a plugin. (That’s a Good Thing)

Thanks @rigpapa

I was trying to avoid a full on plug-in, as I’ve never been successful before, but it seems certain files are unavoidable… (I used the mousetrap one as the basis for RoomMe device xml file)

Device File
D_RoomMeSensor1.xml

<?xml version="1.0"?>
<root xmlns="urn:schemas-upnp-org:device-1-0">
	<specVersion>
		<major>1</major>
		<minor>0</minor>
	</specVersion>
	<device>
		<deviceType>urn:schemas-micasaverde-com:device:RoomMe:1</deviceType>
		<staticJson>D_RoomMeSensor1.json</staticJson>
		<Category_Num>29</Category_Num>
		<serviceList>
			<service>
				<serviceType>urn:schemas-micasaverde-com:service:SecuritySensor:1</serviceType>
				<serviceId>urn:micasaverde-com:serviceId:SecuritySensor1</serviceId>
				<SCPDURL>S_SecuritySensor1.xml</SCPDURL>
			</service>
			<service>
				<serviceType>urn:schemas-micasaverde-com:service:HaDevice:1</serviceType>
				<serviceId>urn:micasaverde-com:serviceId:HaDevice1</serviceId>
				<SCPDURL>S_HaDevice1.xml</SCPDURL>
			</service>
		</serviceList>
	</device>
</root>

and then my current static.json is as follows…

D_RoomMeSensor1.json

{
	"default_icon": "meter_default.png",
	"x": "2",
	"y": "3",
	"inScene": "0",
	"Tabs": [
		{
			"Label": {
				"lang_tag": "ui7_tabname_control",
				"text": "Control"
			},
			"Position": "0",
			"TabType": "flash",
			"top_navigation_tab": 1,
			"ControlGroup": [
				{
					"id": "1",
					"scenegroup": "1"
				},
				{
					"id": "2",
					"scenegroup": "2"
				}
			],
			"SceneGroup": [
				{
					"id": "1",
					"top": "1",
					"left": "0",
					"x": "2",
					"y": "1"
				},
				{
					"id": "2",
					"top": "2",
					"left": "0",
					"x": "2",
					"y": "1",
					"isSingle": "1"
				}
			],
			"Control": [
				{
					"ControlGroup": "1",
					"ControlType": "label",
					"top": "0",
					"left": "0",
					"Label": {
						"lang_tag": "ui4_Room",
						"text": "Room : "
					},
					"Display": {
						"Top": 60,
						"Left": 50,
						"Width": 75,
						"Height": 20
					}
				},
				{
					"ControlGroup": "1",
					"ControlType": "variable",
					"top": "0",
					"left": "1",
					"Display": {
						"Service": "urn:nodecentral-net:serviceId:RoomMe1",
						"Variable": "roomName",
						"Top": 60,
						"Left": 125,
						"Width": 75,
						"Height": 20
					}
				},
				{
					"ControlGroup": "2",
					"ControlType": "label",
					"top": "1",
					"left": "0",
					"Label": {
						"lang_tag": "ui8_Event",
						"text": "Event : "
					},
					"Display": {
						"Top": 90,
						"Left": 50,
						"Width": 75,
						"Height": 20
					}
				},
				{
					"ControlGroup": "2",
					"ControlType": "variable",
					"top": "1",
					"left": "1",
					"Display": {
						"Service": "urn:nodecentral-net:serviceId:RoomMe1",
						"Variable": "eventName",
						"Top": 90,
						"Left": 125,
						"Width": 75,
						"Height": 20
					}
				}
			]
		},
		{
			"Label": {
				"lang_tag": "ui7_settings",
				"text": "Settings"
			},
			"Position": "1",
			"TabType": "javascript",
			"ScriptName": "shared.js",
			"Function": "simple_device"
		},
		{
			"Label": {
				"lang_tag": "ui7_advanced",
				"text": "Advanced"
			},
			"Position": "2",
			"TabType": "javascript",
			"ScriptName": "shared.js",
			"Function": "advanced_device"
		}
	],
	"eventList2": [],
	"device_type": "urn:schemas-micasaverde-com:device:RoomMe:1"
	}

Which is currently giving me the following…

… which for the life of me I can’t get the text sizes to all be the same , nor can I move the bottom text over, so it’s in the middle (or to the right) more…

1 Like

That’s because css styles on Vera are messed up. Something got fixed in 7.32 beta, but the layout sucks.

Hi @therealdb

Quick question : for things like labels, do you know what the "lang_tag" value does, as it seems to used in a variety of different ways in other Vera json files I’ve looked at ?

Is it something to do with /mios/www/cmh/js/config/lang.js as there is a lot of similar/related ui7 values in there?

For example in the lightSensor json, it has the following…

				{
					"ControlGroup":"1",
					"ControlType": "label",
					"top": "0",
					"left": "0",
					"Label": {
						"lang_tag": "ui7_lux_sign",
						"text": "lux"
					},

And then in the lang.js file it has what looks like a corresponding lux entry like this…

"ui7_lux_sign":"lux",

So not to derail my RoomMe widget/plugin thread, I’ve posted a separate thread for the lang.js / javascript stuff - Vera JavaScript - Lang.js (/mios/www/cmh/js/config/lang.js)

I have updated the json so that the UI tile, now shows a user icon and 3 bits of information, sadly it’s annoying that the formatting is all over the place, but hey-ho it is what it is…

I’m trying to think of the best way to set this up, should each device I create be for a person, or for a presence sensor ?

I have 3 sensors, (hallway, kitchen and living room.) and the RoomMe app installed on 4 people’s phones - and I believe its the app that sends the location information to Vera once that person’s device has entered or exited a monitored room.