[download] Module: MiniBrowser - supports mulitple user-interfaces

etc6849

Senior Member
I know the app I made that uses webview doesn't create multiple sessions. However, I'm experiencing a strange issue and I'm curious to see if others have also...

When I let my phone set idle for 20-30 minutes, the webpage loses the header when I click on an item following return from standby. Also, the background is white and there is only one column. Any ideas? The objects still show up with the correct icons and I can click them, but nothing returns the header except closing the browser or webview app and restarting it. Could the web session be timing out while the phone is in standby? When the phone wakes up and the user click refresh or on an item, they are greeted with a white screen similar to the pic attached :(

Luckily, the issue is easy to recreate on a PC. Here's how:
1. Open up ppc or xb in firefox.
2. Navigate to the webserver and delete the session.
3. In the firefox window, click the refresh button in the header.
4. Pic is attached...

What is interesting is this test causes 17 new web sessions to appear under the web server?!? For the issue with my android phone, only one session would appear, otherwise the symptoms are identical.

PS: I'm willing to donate if someone can fix this ;) I tried to study this module, but it is very intricate...

EDIT: I found one potential cause late last night. I had minibrowser above the automationbrowser module. 123's instructions said not to do this, so I've reorganized the folders: AB at the very top under default, plugins just below AB, and finally MB right under plug-ins. I'm not sure if order matters that much or not!?! I tried constructing a test once and things worked fine no matter where the folders were... If anyone knows the reasoning behind this, please chime in :)

Chuck as per your multi-session question: I see what you're talking about. Once briefly on my phone's browser (not the webview app), there were 4 sessions with the same date. I've only seen this once and the app version doesn't do it (at least on android 2.3).
 

Attachments

  • pic.jpg
    pic.jpg
    42.5 KB · Views: 18

chucklyons

Active Member
Fantastic! I'm not going insane...(at least on this problem). The white screen of death, I think, must be some kind of timeout issue. I also get that, on both PC and phone, neither of which are Google related...And yes, the multiple sessions - I think I've seen it kick off up to 8 sessions at once.

The reason for having the AB at the top, as once told to me by the Premise Sage Damon Deen (at least I think he told me) is due to inheritance. I'm not sure it applies in this case.

I too would also contribute to get this fixed. This is well beyond my pay grade...
 

etc6849

Senior Member
Bad news, my screen issue came back. Attached is the normal screen using my webview app...
 

Attachments

  • normal.jpg
    normal.jpg
    79.6 KB · Views: 48

etc6849

Senior Member
Here's the white screen of death that occurs after 25-40 minutes upon bringing the phone back from standby. Note the header and formatting are lost, but the session still shows the correct UI type and properties.

This might be an easy fix if I only knew how minibrowser worked...
 

Attachments

  • lostFormatting.jpg
    lostFormatting.jpg
    47.6 KB · Views: 10

etc6849

Senior Member
Here's another screen showing what seems to be a random issue. I'll post the lower half of the screen in my next post.
 

Attachments

  • methodNotFound.jpg
    methodNotFound.jpg
    96 KB · Views: 10

etc6849

Senior Member
So for the icons with a white background, this is what I think is happening:
1. the session times out in SYS after 20-40 minutes
2. a new session is made when the user brings the phone out of standby
3. this new session is missing 123's added UI properties, since when the session is recreated (either by a refresh or the user clicking something), SYS does not know how to restore the UI properties (they are only created once during the initial web request redirect)

How to fix it?
1. We MUST have some means to restore the UI properties for the pages to look correct following a session timeout/session deletion. I'm not sure how to properly do this as once the session is recreated following a timeout, all information is lost on what the view should look like (ppc,xb,ip). GUIID defaults to "", UIID defaults to 0, UIName defaults to "" etc...

The simplest approach I see is to create a fictitious user for each type of webpage and log in under that user. Since the WebUser object is always contained in a session, even if you delete the session then refresh the page, this would be one way to determine the type of page.

EDIT: There is a client session property called ClientSettng and Theme that is used for setting the theme. I think we should explore using one of the two along with 123's UI properties. Nevermind, theme information is lost if a session is deleted...


Code would be similar to this and added to gMBRenderHeaderEx():
(PS you would use a switch case if you had more than one user/interface type. My code here checks for WebUser="RemoteUser" and always gives them the ppc UI (UIID=0).
Code:
' Display the header
' Part 2
'
Function gMBRenderHeaderEx()
	with sysevent.ClientSession
		
		'ETC_CHANGES		
		on error resume next
		sUName = sysevent.ClientSession.WebUser.Name
		if sysevent.ClientSession.UIName = "" then
'		if sysevent.ClientSession.UIName = "" and sUName = "RemoteUser" then
			'SOMTHING HAS GONE WRONG!!!!!, RELOAD UI PROPERTIES
			for each oRoot in Schema.Modules.MiniBrowser.Templates.GetChildren()
				if oRoot.UIID = 0 then
					.UIID = oRoot.UIID
					.UIGUID = oRoot.ObjectID
					.UIName = oRoot.UIName
					.UIColumns = oRoot.UIColumns
					.UIRows = oRoot.UIRows
					.UIWidth = oRoot.UIWidth
					.UIAdvanced = oRoot.UIAdvanced
					.UICSS = oRoot.UICSS
					.UIClassImages = oRoot.UIClassImages
					.UIIconImages = oRoot.UIIconImages
					.UIBackgroundColor = oRoot.UIBackgroundColor
					.UITextColor = oRoot.UITextColor
					.UITextSize = oRoot.UITextSize
					.UIToolbarBackgroundColor = oRoot.UIToolbarBackgroundColor
					.UIToolbarTextColor = oRoot.UIToolbarTextColor
					.UIToolbarTextSize = oRoot.UIToolbarTextSize
					.UIRefreshInterval = oRoot.UIRefreshInterval
					exit for
				end if
			next
		end if
		on error goto 0



2. The easiest fix is to keep SYS from deleting our session! I'm not sure what makes a session timeout... but, a solution could be as easy as a keep alive method that would poke the session every 20 minutes?

I'd love to here what someone who knows a lot more than me thinks about all this. My changes appear to fix the white screen with icon issue though :)

EDIT: Also need to add this to the top of mbRenderStatus and mbFireMacro to account for the case of a session with no object reference for mbCurrentObject. If we try to call a method for an empty reference, it throws an error...
Code:
' ETC_CHANGE: Ensure mbCurrentObject contains an object
if sysevent.ClientSession.mbCurrentObject is nothing then 
	set sysevent.ClientSession.mbCurrentObject = home
end if
 

etc6849

Senior Member
Small change to the cleaver Status Traverse script. I added a condition to ensure fan was on before displaying speed.

Code:
		elseif oItem.IsOfExplicitType(Schema.Device.Fan.Path) then
			method.sHTML = method.sHTML & (sRowObject & sLink & oItem.ObjectID & sLinkMid & sTextFont & oItem.Name & "</FONT>" & sLinkEnd & sRowObjectMid)

			iSpeed = 0
			on error resume next
			iSpeed = CInt(oItem.GetValue("Speed") * 100)
			on error goto 0
			
			' ETC_CHANGE added oItem.PowerState condtion
			if iSpeed > 0 and iSpeed < 100 and oItem.PowerState then 
				method.sHTML = method.sHTML & (iSpeed & "%" & sRowObjectEnd)
			else
				if oItem.PowerState then sState = "On" else sState = "" end if
				method.sHTML = method.sHTML & (sState & sRowObjectEnd)
			end if

Also made these optional changes:
Code:
		' ETC_CAHNGE: added motion sensor
		elseif oItem.IsOfExplicitType(Schema.Device.Security.MotionDetector.Path) then
				method.sHTML = method.sHTML & (sRowObject & sLink & oItem.ObjectID & sLinkMid & sTextFont & oItem.Name & "</FONT>" & sLinkEnd & sRowObjectMid)
				if oItem.MotionDetected then sState = "Triggered" else sState = "" end if
				method.sHTML = method.sHTML & (sState & sRowObjectEnd)
				
		' ETC_CAHNGE: added garage door
		elseif oItem.IsOfExplicitType(Schema.Device.Security.GarageDoorSensor.Path) then
				method.sHTML = method.sHTML & (sRowObject & sLink & oItem.ObjectID & sLinkMid & sTextFont & oItem.Name & "</FONT>" & sLinkEnd & sRowObjectMid)
				if oItem.GarageDoorOpened then sState = "Open" else sState = "" end if
				method.sHTML = method.sHTML & (sState & sRowObjectEnd)
		end if
 

etc6849

Senior Member
Small change to the cleaver Status Traverse script. I added a condition to ensure fan was on before displaying speed.

Code:
		elseif oItem.IsOfExplicitType(Schema.Device.Fan.Path) then
			method.sHTML = method.sHTML & (sRowObject & sLink & oItem.ObjectID & sLinkMid & sTextFont & oItem.Name & "</FONT>" & sLinkEnd & sRowObjectMid)

			iSpeed = 0
			on error resume next
			iSpeed = CInt(oItem.GetValue("Speed") * 100)
			on error goto 0
			
			' ETC_CHANGE added oItem.PowerState condtion
			if iSpeed > 0 and iSpeed < 100 and oItem.PowerState then 
				method.sHTML = method.sHTML & (iSpeed & "%" & sRowObjectEnd)
			else
				if oItem.PowerState then sState = "On" else sState = "" end if
				method.sHTML = method.sHTML & (sState & sRowObjectEnd)
			end if

Also made these optional changes:
Code:
		' ETC_CAHNGE: added motion sensor
		elseif oItem.IsOfExplicitType(Schema.Device.Security.MotionDetector.Path) then
				method.sHTML = method.sHTML & (sRowObject & sLink & oItem.ObjectID & sLinkMid & sTextFont & oItem.Name & "</FONT>" & sLinkEnd & sRowObjectMid)
				if oItem.MotionDetected then sState = "Triggered" else sState = "" end if
				method.sHTML = method.sHTML & (sState & sRowObjectEnd)
				
		' ETC_CAHNGE: added garage door
		elseif oItem.IsOfExplicitType(Schema.Device.Security.GarageDoorSensor.Path) then
				method.sHTML = method.sHTML & (sRowObject & sLink & oItem.ObjectID & sLinkMid & sTextFont & oItem.Name & "</FONT>" & sLinkEnd & sRowObjectMid)
				if oItem.GarageDoorOpened then sState = "Open" else sState = "" end if
				method.sHTML = method.sHTML & (sState & sRowObjectEnd)
		end if

PS: I figured out how valid classes are handled. mbLocationEx calls IsValidClass which has this brilliant idea:
Code:
' Validate against all known classes.
for each oItem in Schema.Modules.MiniBrowser.Classes.ValidClasses.GetChildren()
	if Method.ObjectRef.IsOfExplicitType(oItem.Description) then
		bIsValid = true
		exit for
	end if
next

By storing valid classes as an enum, it's very easy to add new classes. I was able to add the GarageDoorSensor class very easily. I also really like how the class extensions are handled for the various device types. Thanks 123!
 

chucklyons

Active Member
So for the icons with a white background, this is what I think is happening:
1. the session times out in SYS after 20-40 minutes
2. a new session is made when the user brings the phone out of standby
3. this new session is missing 123's added UI properties, since when the session is recreated (either by a refresh or the user clicking something), SYS does not know how to restore the UI properties (they are only created once during the initial web request redirect)

1. I agree. I haven't specifically timed it, but that sounds about right
2. Yup
3. Sounds right

How to fix it?
1. We MUST have some means to restore the UI properties for the pages to look correct following a session timeout/session deletion. I'm not sure how to properly do this as once the session is recreated following a timeout, all information is lost on what the view should look like (ppc,xb,ip). GUIID defaults to "", UIID defaults to 0, UIName defaults to "" etc...

The simplest approach I see is to create a fictitious user for each type of webpage and log in under that user. Since the WebUser object is always contained in a session, even if you delete the session then refresh the page, this would be one way to determine the type of page.

EDIT: There is a client session property called ClientSettng and Theme that is used for setting the theme. I think we should explore using one of the two along with 123's UI properties. Nevermind, theme information is lost if a session is deleted...


Code would be similar to this and added to gMBRenderHeaderEx():
(PS you would use a switch case if you had more than one user/interface type. My code here checks for WebUser="RemoteUser" and always gives them the ppc UI (UIID=0).
Code:
' Display the header
' Part 2
'
Function gMBRenderHeaderEx()
	with sysevent.ClientSession
		
		'ETC_CHANGES		
		on error resume next
		sUName = sysevent.ClientSession.WebUser.Name
		if sysevent.ClientSession.UIName = "" then
'		if sysevent.ClientSession.UIName = "" and sUName = "RemoteUser" then
			'SOMTHING HAS GONE WRONG!!!!!, RELOAD UI PROPERTIES
			for each oRoot in Schema.Modules.MiniBrowser.Templates.GetChildren()
				if oRoot.UIID = 0 then
					.UIID = oRoot.UIID
					.UIGUID = oRoot.ObjectID
					.UIName = oRoot.UIName
					.UIColumns = oRoot.UIColumns
					.UIRows = oRoot.UIRows
					.UIWidth = oRoot.UIWidth
					.UIAdvanced = oRoot.UIAdvanced
					.UICSS = oRoot.UICSS
					.UIClassImages = oRoot.UIClassImages
					.UIIconImages = oRoot.UIIconImages
					.UIBackgroundColor = oRoot.UIBackgroundColor
					.UITextColor = oRoot.UITextColor
					.UITextSize = oRoot.UITextSize
					.UIToolbarBackgroundColor = oRoot.UIToolbarBackgroundColor
					.UIToolbarTextColor = oRoot.UIToolbarTextColor
					.UIToolbarTextSize = oRoot.UIToolbarTextSize
					.UIRefreshInterval = oRoot.UIRefreshInterval
					exit for
				end if
			next
		end if
		on error goto 0



2. The easiest fix is to keep SYS from deleting our session! I'm not sure what makes a session timeout... but, a solution could be as easy as a keep alive method that would poke the session every 20 minutes?

I'd love to here what someone who knows a lot more than me thinks about all this. My changes appear to fix the white screen with icon issue though :)

EDIT: Also need to add this to the top of mbRenderStatus and mbFireMacro to account for the case of a session with no object reference for mbCurrentObject. If we try to call a method for an empty reference, it throws an error...
Code:
' ETC_CHANGE: Ensure mbCurrentObject contains an object
if sysevent.ClientSession.mbCurrentObject is nothing then 
	set sysevent.ClientSession.mbCurrentObject = home
end if

So you've created a webuser? I'm not sure I am following the remote user part? Of course, I am virtually unable to test to this as my entire Premise world consists of a laptop and a couple of modules I am working on...(streaming media thru the MB), but I'll give it a try...
 

etc6849

Senior Member
Correct RemoteUser is a username I manually set up in Builder under WebUsers.

For my example, remove the comment from the line with RemoteUser and comment the line above. Then, whenever a mb session that is recreated for RemoteUser, the session's UI properties will be populated. In this example RemoteUser is assigned UIID = 0 or PPC.

This isn't an elegant solution since you'd have to require local users to log-in, which probably isn't ideal.

The code shown as-is sets any new session following time-out/deletion to be UIID=0 and sets all UI parameters. This is what I'm using since I only force log-in if the connection is from the internet.

1. I agree. I haven't specifically timed it, but that sounds about right
2. Yup
3. Sounds right



So you've created a webuser? I'm not sure I am following the remote user part? Of course, I am virtually unable to test to this as my entire Premise world consists of a laptop and a couple of modules I am working on...(streaming media thru the MB), but I'll give it a try...
 

chucklyons

Active Member
blush.gif
I have used authentication for my mini-browser internet access for a while...but I forgot I needed to set authentication for localhost..(which is all I have at the moment). So makes sense,; I'll dig around over the next few days...
 

etc6849

Senior Member
I prefer not having to log in if I'm using a browser on the subnet. I'm hoping there's a hidden property of a session object such as ip address, but I haven't looked in detail yet. The MB module could track UI selection by IP address; I think this is the best option.

Status on the android webview app:

I've been too busy working on the android app to figure that out. I think there's a lot of value in loading web class images locally from within the app's asset folder. Plugin images will also be loaded from within the android app as this will save time. To do this, I've modified how ClassImages are handled, now MB uses the file path and not the SYS redirect based on the image objectID. If the image is explicit, it will still be loaded normally, and will still use the ObjectID redirect.

I also figured out that the white screen with the text "Premise...Method Not Found..." is caused by the refresh function. It works fine on my PC though, which is strange. This isn't a deal killer as the app will have a menu system to allow the user to input a refresh rate locally.

I plan to add the app and source to the downloads section when in a few weeks, so hopefully others will add to it :)
 

etc6849

Senior Member
Anyone using javascript with MiniBrowser know why 123 uses syntax like this:

sHTML = sHTML & ("<script language=""JavaScript""><!-- " & vbcrlf & "var sURL = unescape(window.location.pathname);")
sHTML = sHTML & ("function refresh() { window.location.href = sURL + ""?d??mbRenderPage""; } //--></script>")

instead of:

sHTML = sHTML & ("<script type=""text/javaScript""> var sURL = unescape(window.location.pathname);")
sHTML = sHTML & ("function refresh() { window.location.href = sURL + ""?d??mbRenderPage""; }</script>")

I think with recent html versions, the latter is more common? Is this to allow backward compatibility with Audrey or something? Both should always work right?
 

etc6849

Senior Member
Ah ha! I figured out the refresh bug! :)

If you've ever got the method not found screen (see attached image), I bet I know why... The issue is pretty simple. 123's module has an auto refresh feature that uses javascript to resfresh the page.

The refresh javascript works like this:
a variable is sURL is set to the current path of the window
Code:
var sURL = unescape(window.location.pathname);

a function called refresh calls the render page method
Code:
function refresh() { window.location.href = sURL + "?d??mbRenderPage";}

The problem with this is each SYS object that you can potentially click on in the MiniBrowser page before the javascript function refresh is called must contain a method called mbRenderPage. However, for some special objects like custom panel buttons there is no "mbRenderPage" method!

To test my theory:
Set the UI refresh property to 10 seconds, open a MiniBrowser page, click on a "custom panel button" (custom button thingy under a home object that usually calls a scriptmacro). Wait for the next refresh interval and you're greeted with the attached screen!

The good news:
I think a solution could be simple, but I haven't tried to create one yet (and may not as my android app handles refreshes just fine) For now, don't use the auto refresh feature unless you click on something else after clicking on a "Custom Panel Button." I do plan to upload a new generic version of MiniBrowser that has several new home objects and will probably make a new javascript refresh() function.

The solution is to use an sURL = http://domain/rootdir in the javascript code or some relative address that points just to the roodir (ppc, xb, ip etc...).

Since SYS always tracks what home object you're using using a session object and SYS shouldn't create a new session if you go back to the root page, my solution should always refresh whatever object you're on. To test my solution, go to any home object, then type http://ipaddress:port/rootdir (ppc, xb etc...) and you'll see what I'm saying is correct ;)

PS: this is how my android app handles refreshing anyways (been using it just fine for a week now), so if you download it, everything will work fine :)

EDIT: Here's the solution
replace
Code:
sHTML = sHTML & ("function refresh() { window.location.href = sURL + ""?d??mbRenderPage""; }</script>")
with this
Code:
sHTML = sHTML & ("function refresh() { window.location.href = ""/" & sysevent.ClientSession.UIName & """" & "; }</script>")
 

Attachments

  • methodNotFound.JPG
    methodNotFound.JPG
    48 KB · Views: 4
Top