PDA

View Full Version : Webserver - change a variable through a web page



Mastiff
December 4th, 2014, 06:36 AM
My lack of programming skills bites me in the ass again. I would like to be able to control my wake-up system so that members of the family can access their own webpage and change or order a wake-up (which is done with the speakers in the rooms, but that part has been running pretty flawlessly for many years). So when they go into the webpage they will see all the wake-up events with that zone. Here's my final wake-up call (yeah, I'm a sleeper...):


Timere.Vekking.Opp= scheduler.Create('opp',18)
Timere.Vekking.Opp:DayOfWeekTask(1, 1, 07, 44, scheduler.INFINITE) --mandag
Timere.Vekking.Opp:DayOfWeekTask(1, 2, 07, 44, scheduler.INFINITE) --tirsdag
Timere.Vekking.Opp:DayOfWeekTask(1, 3, 07, 44, scheduler.INFINITE) --onsdag
Timere.Vekking.Opp:DayOfWeekTask(1, 4, 07, 44, scheduler.INFINITE) --torsdag
Timere.Vekking.Opp:DayOfWeekTask(1, 5, 07, 44, scheduler.INFINITE) --fredag
Timere.Vekking.Opp:Start()
Timere.Vekking.politisk = Timere.Vekking.Opp:ListProperties()

The "dag" at the end of the line is the day of the week. So on my page I would like to see all those scheduler times (I'm guessing that I would have to replace the time there with variables for each day), and then be able to write in those boxes to change it for one day, or for as many days as I'd like. But here comes the kicker: I would also like to have some way of choosing if this is for one day only or for good. And to deactivate the timer. And finally to save the changed variable in hard code somewhere (I could probably use LUA's registry write for that) so that a restart of the computer doesn't mess it up. I'm guessing I can't really do that in a script in Girder, right? Or would it be possible to do it in a LUA file?

So basically I'm asking for the moon and the stars. Maybe somebody has in his powers to give them to me? :D Or at least help me on the way?

Mastiff
December 5th, 2014, 01:28 AM
Oh, and I don't consider a hard kick in the pants as being help on the way, even if it takes me a few inches higher! ;)

Ron
December 9th, 2014, 03:02 PM
Sure that is possible, it will take some Lua glue to make it happen of course. Just remember you can place Lua code inside HTML pages. Together with CGI parameters ( like bla.html?hour=7&minute=40 ) you could make that dynamic.

Mastiff
December 10th, 2014, 01:35 AM
Thanks, Ron! Then I know it's possible, so next weekend I will start messing with it. This weekend I will be spending doing hardware stuff at the cabin, to get everything ready for our Christmas there!

jon1977
December 14th, 2014, 03:00 PM
I've done a fair bit of coding to interact with Girder variables and events to and from a set of web pages. I use this to control lighting and heating and to see status' of digital inputs to mention just a few from a web page.
I've used a lot of jquery (as per the manual and this forum with slight customisations), but as I was using quite large tables, and I didn't want to code them from scratch I used javascript to dynamically build tables.
if you don't need to dynamically build tables then its very easy using basic functions.
If you do (if for instance you had lots of names zones or rooms and didnt want to duplicate this coding in your webpage) then dynamic tables are (in my opinion) the way forward.
If this looks of any use, and you want further explanation then just ask. If its of no use, then no worries!
As for basic interaction, the interesting bit to send data to girder is:


function SendEventPayload( Event, Device, Payload1, Payload2, Payload3, Payload4 )
{
$.get("ajax_sendevent_payload.lhtml?event="+escape(Event)+"&device="+escape(Device)+"&payload1="+escape(Payload1)+"&payload2="+escape(Payload2)+"&payload3="+escape(Payload3)+"&payload4="+escape(Payload4));
return false;
}

noting, that you must have a file called "ajax_sendevent_payload.lhtml"
which needs to contain:

<%
webserver:SetGZIP(false)
webserver:SetHeader("Cache-Control: no-cache, must-revalidate")
webserver:SetHeader("Expires: Fri, 30 Oct 1998 14:19:41 GMT")
local table = webserver:GetCGI()
if ( gir ) then
gir.TriggerEvent( table['event'], table['device'], table['payload1'], table['payload2'], table['payload3'], table['payload4'] )
end
%>

and to look at variables within girder, you need the functions "checkGIRDER" and "checkDATA" and the associated functions to keep scanning the data you want to look at "$(document).ready(function()" renaming the variable paths to suit,
Note, in my doc they are split into checkGIRDER for static information (such as descriptions) to ones with are scanned every x ms for a change.

Also note, javascript is case sensitive.
Also note, alert() is like print in girder and is very useful to debug code that won't work.
I started from very basic building blocks and expanded gradually keeping backups as I went along, hence why its not too tidy. If I rewrote from scratch I'd hope it would be much neater.

To then change a variable, I'd send an event with a payload containing the variable to change plus the data and use a script in the girder tree to update the actual variable.

I tried to attach this as a file, but it won't work, so I've just copied the file in here:
Note, all the bits about key and sub key is to deal with lots of arrays of data and JsonOBJ strings, so may not be applicable to you.


<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html><head>
<meta http-equiv="PRAGMA" content="NO-CACHE">
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1"><title>Digital Inputs</title>

<link type="text/css" rel="stylesheet" href="styles.css">
<script src="jquery.min.js" type="text/javascript"></script>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.5.2.min.js"></script>
<script>

jsonOBJ = {};
function now(){
window.location.reload(true);
}
function SetImage(id, src)
{
var Image = document.getElementById(id);
if (Image != null)
{
Image.src = src;
}
return false;
}
function SendEventPayload( Event, Device, Payload1, Payload2, Payload3, Payload4 )
{
$.get("ajax_sendevent_payload.lhtml?event="+escape(Event)+"&device="+escape(Device)+"&payload1="+escape(Payload1)+"&payload2="+escape(Payload2)+"&payload3="+escape(Payload3)+"&payload4="+escape(Payload4));
return false;
}
function SendEventPayloadByID( Event, Device, Payload1, Payload2ID, Payload3, Payload4)
{
var Payload2 = document.getElementById(Payload2ID);
SendEventPayload(Event, Device, Payload1, Payload2.value, Payload3, Payload4);
return false;
}
function SendEventByID( EventID, DeviceID )
{
var Event = document.getElementById(EventID);
var Device = document.getElementById(DeviceID); SendEvent(Event.value, Device.value);return false;
}
//
//
function checkGIRDER(GirderVariable,LocalVariable,SetButton ) {
$.ajax({
type: "GET",
url: "ajaxreqjson.lhtml",
data: {Data : "myVal,"+GirderVariable},
async: true,
cache: false,
timeout:5000,
success: function(data){
checkDATA(data,GirderVariable,LocalVariable,SetBut ton);
},
error: function(XMLHttpRequest, textStatus, errorThrown){
$("#error").text("Comet Timeout ERROR: " + textStatus + " (" + errorThrown + ")");
},
});
}
//Scan once for source text data
function checkDATA(data,GirderVariable,LocalVariable,SetBut ton) {
try {
jsonOBJ = jQuery.parseJSON(data);
//alert(data);
$("#" + LocalVariable+"FullData").text(data);
var DataString = (jsonOBJ[GirderVariable]);
if (SetButton == 'array')
{
var Stringlength = DataString.length;
var arraymax = Stringlength + 1;
for (var a = 0; a < arraymax; a++)
{
$("#" + LocalVariable + "ID" + a).text(DataString[a]);
if (DataString[a]==1)
{
SetImage(LocalVariable + "Button" + a, "img/button_red_up.jpg");
}
if (DataString[a]==0)
{
SetImage(LocalVariable + "Button" + a, "img/button_green_up.jpg");
}
}
}
//variable = "string to look in"
//variable.indexof("string to find")
for (var key in jsonOBJ[GirderVariable])
//$("#" + LocalVariable+"FullData2").text(sonOBJ[GirderVariable][key]);
{
for (var subkey in jsonOBJ[GirderVariable][key])
{
//alert("Sub key found: key: "+key+" subkey:"+subkey+" Contains:"+jsonOBJ[GirderVariable][key][subkey]);
$("#" + LocalVariable + "_" + key + "_" + subkey).text(jsonOBJ[GirderVariable][key][subkey]);
$("#" + LocalVariable + "_key_"+ key + "_subkey_" + subkey).text(key + "_" + subkey);
}
if (jsonOBJ[GirderVariable].hasOwnProperty(key)) {
//alert(key)
$("#" + LocalVariable + key).text(jsonOBJ[GirderVariable][key]);
$("#" + LocalVariable + "key"+ key).text(key);
if (SetButton == 'true')
{
if (jsonOBJ[GirderVariable][key]=='1')
{
$("#" + LocalVariable + "txt"+ key).text("1");
SetImage(LocalVariable + "Button"+key, "img/button_green_up.jpg");
}
if (jsonOBJ[GirderVariable][key]=='0')
{
$("#" + LocalVariable + "txt"+ key).text("0");
SetImage(LocalVariable + "Button"+key, "img/button_blue_up.jpg");
}
}
}
}
}
catch(err) { $("#jsondata").text(data);
$("#error").append(" INCORRECTLY FORMED JSON DATA...");
}
}
//
//variables that need to update on page load only
//Girder source variable, Local source variable, true if set buttons, array if table array
//

$(document).ready(function() { setTimeout('checkGIRDER(\'HOUSE.IO_Diagnostics.DI_ Description\',\'DIName\',\'array\')',100); });
//
//variables that need to update regularily
//Girder source variable, Local source variable, true if set buttons
//
$(document).ready(function() { setTimeout('ScanInputs()',100);});

function ScanInputs()
{
$(document).ready(function() { setTimeout('checkGIRDER(\'HOUSE.IO_Diagnostics.DI_ Value\',\'DIValue\',\'array\')',100); });
$(document).ready(function() { setTimeout('checkGIRDER(\'HOUSE.IO_Diagnostics.DI_ Time0_string\',\'DITime0\',\'array\')',100); });
$(document).ready(function() { setTimeout('checkGIRDER(\'HOUSE.IO_Diagnostics.DI_ Time1_string\',\'DITime1\',\'array\')',100); });
setTimeout('ScanInputs()',1000);
}
//
// Build the table
function BuildTable()
{
var rows = 128; //here's your number of rows and columns
//var cols = 1;
$('#dynamictable').append('<table></table>');
var table = $('#dynamictable').children();
var tr = $('<tr>');
$('<td style=\"text-align: center; width: 80px; height: 45px;\">ID</td>').appendTo(tr);
$('<td style=\"text-align: center; width: 160px; height: 45px;\">Name</td>').appendTo(tr);
$('<td style=\"text-align: center; width: 80px; height: 45px;\">Status</td>').appendTo(tr);
$('<td style=\"text-align: center; width: 80px; height: 45px;\">Time1</td>').appendTo(tr);
$('<td style=\"text-align: center; width: 80px; height: 45px;\">Time0</td>').appendTo(tr);
tr.appendTo(table);
for(var r = 0; r < rows; r++)
{
var tr = $('<tr>');
var ID = r + 1;
var ID2 = r;
var ImageID = r;
$('<td style=\"text-align: center; width: 80px; height: 45px;\">'+ID+'</td>').appendTo(tr);
var Name = '<center><Div><Span id=\"DIName'+ID2+'\"></span></center>';
$('<td style=\"text-align: center; width: 160px; height: 45px;\">'+Name+'</td>').appendTo(tr);
var DigButton = '<center><a href=\"\" onclick=\'return SendEventPayload(\"DIGIO\", \"18\", \"\",\"\",\"'+ID2+'\",\"FromWeb\");\' onmousedown=\'return SetImage(\"DIValueButton'+ImageID+'\", \"img/button_blue_down.jpg\");\' onmouseup=\'return SetImage(\"DIValueButton'+ImageID+'\", \"img/button_blue_up.jpg\");\'><img src=\"img/button_blue_up.jpg\" id=\"DIValueButton'+ImageID+'\" border=\"0\"></a>&nbsp;</center>'
$('<td style=\"text-align: center; width: 80px; height: 45px;\">'+DigButton+'</td>').appendTo(tr);
var Time1= '<center><Div><Span id=\"DITime1'+ID2+'\"></span></center>';
$('<td style=\"text-align: center; width: 160px; height: 45px;\">'+Time1+'</td>').appendTo(tr);
var Time0= '<center><Div><Span id=\"DITime0'+ID2+'\"></span></center>';
$('<td style=\"text-align: center; width: 160px; height: 45px;\">'+Time0+'</td>').appendTo(tr);
tr.appendTo(table);
}
}
window.onload = BuildTable;
</script>
<style>
#dynamictable
{
border:solid 1px;
border-collapse:collapse;
}
#dynamictable th
{
border:solid 1px;
border-collapse:collapse;
}
#dynamictable td
{
border:solid 2px;
vertical-align:middle;
text-align:middle;
}
</style>
</head>
<body style="color: rgb(0, 0, 0); background-color: rgb(153, 153, 153);" alink="#000099" link="#000099" vlink="#990099">
<h1>Digital Inputs</h1>
<div id="dynamictable"></div>
</body></html>

Jon

Mastiff
December 14th, 2014, 03:03 PM
Holy Moly! :eek: This looks great! Thank you very much! I will certainly put this into a webpage and check it out next weekend, (or the week after), when I get the time to mess with this stuff! Appreciate it a lot!

jon1977
December 14th, 2014, 04:45 PM
No prob.
Jon

Mastiff
January 2nd, 2015, 02:39 PM
Hi agian, Jon! Finally got around to this (busy Christmas, ending up working a lot more than I really wanted to...). I have created the lhtml file and a html file with the code in the bottom window. But I do not get boxes to put any code into. I get a page with a table (digital inputs), but none of the columns are input boxes. Am I doing something wrong, or have I misunderstood you?

jon1977
January 2nd, 2015, 04:03 PM
Hi,
Rather than trying to work with my script,
I'll draft something up specifically over the next couple of days to:
Display a generic table of girder variables, text Input boxes, buttons and button statuses that should be easier to understand.
Jon.

Mastiff
January 3rd, 2015, 03:39 AM
That would be totally fantastic, thank you very much! :)

jon1977
January 4th, 2015, 09:14 AM
just to say i havent forgotten. im tidying and commenting the code (which helps me a well!) as and when i get a few spare mins.
a couple more days needed
jon.

Mastiff
January 4th, 2015, 09:40 AM
Don't worry, Jon! When I'm given a free ride I seldom tell the driver he's going to slow! :D And I won't have time to look at this until maybe next weekend anyway, the week's pretty much hysterical (like most weeks for selv-employed people).

jon1977
January 8th, 2015, 03:56 PM
Right,

see how this goes:

6805

Attached is a zipped folder with a html file called WebToGirderTest.html which should be placed in your httpd directory in girder.
You will also need to add the ajax_sendevent_payload.lhtml file to the same directory and the images in the img folder.

This assumes you already have a working web server and you can log onto it.

Next, in the girder tree, create a blank scripting action called testweblink and add the contents of the file testweblink.lua to it. Then run this action to create the variables.

Next create another blank scripting action called testsettime and add the contents of the file testsettime.lua to it. Then add an event from device 'Girder Events' with an Event String called setnewtime. Save this.

Next create another blank scripting action called testsetstatus and add the contents of the file testsetstatus.lua to it. Then add an event from device 'Girder Events' with an Event String called TestHTML_SetStatus. Save this.

I use a program called scite to view lua and html files.
Or use any other editing software.

Open the file in your browser, http : / /ip : port/WebToGirderTest.html substituting ip and port for your settings.
You should see a table with filled in data.
You should be able to update the times (which updates back onto the web page) in girder and a status for each row.

If this all works, have a look at the files an see if you can see what is going on, if you have a query, or it doesnt work for you then get back to me.

As an aside, this helped tidy up my various web pages as a rewrite!!

With regards

Jon

Mastiff
January 9th, 2015, 02:45 PM
Thank you very much, Jon! I have suddenly had to change my weekend plans (having a family sometimes can do that to me...), but I hope to dwell into this either Sunday or Monday. I will of course tell you what I get out of it! Again thank you!

Mastiff
January 11th, 2015, 08:05 AM
Jon, I don't know if I'm dumb or you have forgotten something, but where are the lua files? Testweblink and so on. They aren't in the archive, should I find them somewhere else? :eek:

jon1977
January 12th, 2015, 12:53 PM
sorry, I thought I had attached the correct zip file.
I've edited the post above with the correct attachment with the missing files included.
With regards
Jon

Mastiff
January 12th, 2015, 02:58 PM
Well this time I get those, but I don't see what I should see. I can see the table of variables in the variable inspector, but the three first columns on the webside are empty and not filled with them. I only see the one with the 0800 and the blue buttons. Should I have another action there somewhere that filles the variables into the webside table or is there something else that can be wrong? I can give you access if you need to try it on my setup.

jon1977
January 12th, 2015, 03:04 PM
Do you have a file called ajaxreqjson.lhtml in your http directory?
If not, put this in.
I can't remember what came as standard and what I've added, although the date stamp on this means its likely I added it.
Regards
Jon6806

Mastiff
January 12th, 2015, 03:18 PM
I didn't, and I put it there now. At first it didn't help, but then I saw that Firefox was blocking unecrypted content (I use HTTPS for my Girder webserver and HHTP for EventGhost) and opened for that I could see everything! So thanks! I will look more at this tomorrow, now it's time to go to bed here. Early up tomorrow for a new crazy day at work. Was expecting a slow week, suddenly the week changed totally. That's how it goes when you're a freelancer. ;) Thanks for the help so far! I may bug you more tomorrow when/if I get stuck!

Edit (that didn't take long...): I did a very quick test, and status changes and times work, thanks! But would it be possible to avoid the billions of ajaxreqjson calls in the Girder logger? I can't seem to turn it off in Girder, and it really messes up my logging so I can't see anything else there.

jon1977
January 16th, 2015, 06:03 AM
Hi,
Glad it worked. Do you think you can use that as a basis for what you want to do?

I don't use the logger so it didn't bother me.
I use lots of frequent events for things so had to avoid relying on it.

If you only want to see a change each time you load or refresh your web page then just move the lines that are in the scaninputs function (i.e. the status and alarm updates on lines 33 and 34) to join the id and name updates in the function now() after line 20.
You would then not get updates if you stay on the same page though.
Alternatively change the scan time on line 36 (in ms) to something longer like 10 minutes or whatever suits?
There may be an option to disable this in the logger?
Jon

Mastiff
January 16th, 2015, 06:09 AM
Thanks, I'll experiment with that! I think this is exactly what I needed! I can use it almost unchanged (except for the variable names, of course) for the wakeup-system. For the temperature control system I only need to widen the status column to three instead of two, so I can choose between three different statuses: Day, night and no frost. Is that difficult? At the moment I'm very close to something workeable on the receiving end, so when that's completely done I will start adapting the user interface, which is your system. :)

jon1977
January 16th, 2015, 06:22 AM
To add another column, just duplicate what is there already. I'd recommend doing mods slowly and keeping working backups as you go along.
Debugging Javascript is not easy as it just stops if there is any error with no reason why.
Using // to comment out lines is useful
as is alert(variable_to_print) will bring up a popup box on the web page, warning, some web browsers won't allow you to disable alerts, some (like google chrome) will so you may end up having to end a process to close the webpage! Apologies if you already know this. Just something I spent ages sorting.

I assume you mean three buttons?
create another column for the header, so for instance duplicate row 57 in WebToGirderTest.html
then duplicate rows 87 to 89, but rename all the references to make them unique, including the button ID's
Note, the status sent to girder is the 0 or 1, you can call this whatever you want, so perhaps "Day" or "Night" or "NoFrost" then do an if then else in girder to check for the respective status' and do whatever you want with them.
With regards
Jon

Mastiff
January 16th, 2015, 06:25 AM
Thanks! I will cry for help if I need it, but it will probably be a couple of weeks until I'm there. And yeah, backups is essential. Always keep them, because I always mess up some time! If I ever get to the point were I need debugging, I can tell you for sure that I need to go back to a backup, since that's way over my head with this stuff! :)

Mastiff
January 16th, 2015, 06:37 AM
The only sad thing about this is that it won't work on phones and tablets. But I don't suppose it's possible to create something so advanced that would work on them, right?

jon1977
January 16th, 2015, 06:39 AM
It works on all my phones and tablets, some back to version 2.x of android!
How are you accessing the web page?
Locally (i.e. inside your network) or externally? You will need the correct IP address and port.
Can you access any of the girder webserver from your phone or tablet?
Jon.

Mastiff
January 16th, 2015, 06:42 AM
Ah, I was thinking about with the standard browser, sorry! I can use it fine with Dolphin, it's just that so few use that. I don't know if it works on my daughter's iPhone, though. I seem to remember that Apple do not support any form of scripting. Or maybe I'm wrong about that, I'm an iHater, so I really don't know much about those! ;)

jon1977
January 16th, 2015, 06:45 AM
it works with my standard browser.
I tend to use Chrome on my phone and tablet anyhow and it works fine with that too, including the slider component that I use for temperature and lighting dimmer control. Not may browsers support that.
I don't know about iphone. It must be possble as its just javascript and json. A lot of websites will use that.
Jon.

Mastiff
January 16th, 2015, 06:52 AM
Strange. On my built-in browser (Samsung S4 Active, upgraded to 4.4) I can see the buttons and stuff, but pressing the buttons do nothing. I'll have to investigate when I get it running for pc's. In a couple of weeks.

Mastiff
January 17th, 2015, 02:47 AM
Had a few minutes to spare. Found the reason. I had accidentally renamed it index.html instead of index.lhtml! :)

Btw I'm pretty bad at coding, but I can use Dreamweaver, at least in design mode! But I couldn't get anything to show. I guess I'll have to whip out Notepad plus and see what's happening.

Mastiff
January 17th, 2015, 03:26 AM
I think I can survive this... ;) But do you by any chance have a list over what that has to be changed in the webpage itself when I change the variables, just to make sure that I don't forget anything important?

jon1977
January 17th, 2015, 09:05 AM
I'd download scite and use that to edit the page.
I use this for all my coding editing.
Its a better text editor that recognises the language and colour codes it to make it easier to use:
http://www.scintilla.org/SciTE.html
I guess Dreamweaver is breaking some of the code.
Jon.

jon1977
January 17th, 2015, 12:48 PM
Variables to change example:

line34:


$(document).ready(function() { setTimeout('checkGIRDER(\'test.myhtml2.time\',\'my time\',\'array\',\'false\')',200); });


test.myhtml2.time is the path to the folder and variable in girder, change this to suit your setup.
mytime is the name I've given the internal variable on the webpage.
My rule is to prefix 'my' to the girder variable name just to make it different, but easy to track through the code.

lines 72,73:


var mytime_REF = '<center><Div><Span id=\"mytimeID'+RowID+'\"></span></center>';
$('<td style=\"text-align: center; width: 80px; height: 45px;\">'+mytime_REF+'</td>').appendTo(tr);


The internal variable above is manipulated in the function checkDATA (line 141 onwards) and if there is a valid variable, it suffixes ID (see row 154) to the internal variable, so mytime becomes mytimeID.
Line 72 is building HTML code in javascript (including the RowID to make a unique id per row), so I suffix the internal variable with _REF, so mytime becomes mytime_REF.
The next row builds the html table row, so the mytime_REF is copied in here.

Where there are buttons, e.g. rows 84/85,


var setstatus0_REF = '<center><a href=\"\" onclick=\'return SendEventPayload(\"TestHTML_SetStatus\", \"18\", \"0\" ,\"\" ,\"'+RowID2+'\",\"FromWeb\");\' onmousedown=\'return SetImage(\"setstatus0Button'+RowID+'\", \"img/button_blue_down.jpg\");\' onmouseup=\'return SetImage(\"setstatus0Button'+RowID+'\", \"img/button_blue_up.jpg\");\'><img src=\"img/button_blue_up.jpg\" id=\"setstatus0Button'+RowID+'\" border=\"0\"></a>&nbsp;</center>'
$('<td style=\"text-align: center; width: 70px; height: 45px;\">'+setstatus0_REF+'</td>').appendTo(tr);


the same internal variable needs replacing each time you see it, noting that the variable ID is suffixed with 'Button' see rows 158/159 and 176/177 where this is done, depending on the variable type.

I would say for instance if you wanted to change the variable 'time' to ' date' take the rows, 34, 72 and 73 and just do a find replace for 'time' to 'date' and it should sort it self out.

Does that make sense?
It would be possible to make this more generic, and just change the variables in one place with not a great deal of work, but this approach works for me!
With regards
Jon

Mastiff
January 21st, 2015, 02:43 PM
Hi again! Well, after a few hours of work I have sort of gotten it to work. Only sort of, though. I have a few problems. Here's the shortlist:

1. Clicking on a line makes the color button below change to red or green! So there's a wrong read of the row number.

2. I can't understand how to make the third to fifth button rows (yeah, I managed to make them, and they work!) turn the button to a third, fourth and fifth version, since it seems like the button change rely on true/false, not variable 0 or 1. I use 0-4, where 0 means off, 1 is day, 2 is night, 3 is no frost and 4 are special temperatures, like running 20 degrees in the bedroom when my wife's extra cold one day.

3. Something in the system can't take (norwegian characters). I think it's Girder since the values Kjkken is black even whithin quotes. So I just have to work around that somehow. Is that possible to do that in the script, with a translate table?

4. I would like the temperatures to change with the thermostat mode. Something like if thermostat mode == 1 then use the temperature for that mode. I guess that should be done in Girder, right? Or should it be done in the html? If the latter, how do I do that?

5. I have hidden the ID column, but I need to keep it in the html for the page to work, right? As far as I can see that is the thing that keeps all the other stuff in the right row. I did that after the funky problem with wrong button changing happened, so it's not the reason for that problem.

I have attached the contents of the html page I have so far. I have changed the variables, but I'm guessing that you understand what's been changed where. They are of course changed accordingly in the scripts (well, I guess almost accordingly, since I get the wrong line when pressing a button!).

Mastiff
January 21st, 2015, 02:48 PM
Oh, in case you need my GML as well, here's that. :)

jon1977
January 22nd, 2015, 07:03 AM
I started answering this while in work, but I need to run your code to see what is going on so It'll be a few days to answer fully.

Short answers as follows:

1. Clicking on a line makes the color button below change to red or green! So there's a wrong read of the row number.
JPF: My mistake, I believe that for all the rows with buttons where you have onmouse down etc, the RowID should be RowID2.
See line 67 where it sets an offset by 1. This is needed for the send event to girder, and is also needed for the button ID (I think). Play around with it and see what happens.

2. please explain how you want to use the buttons in more detail.
I'd try and keep the web page simple and generic, working with only true / false for button status'. If you want more buttons to do different things then do all the smart stuff in girder and have a girder table for each button.
e.g.
local SettID = pld3
local SettTermostatmodus = pld1
local n
local modus
local max_n = table.getn(Temperaturstyring.Nettside.ID)
--by default this is 13, but coded like this just in case you add more ID's

for n = 1,max_n,1 do
for modus = 0,4,1 do
if modus == SettTermostatmodus then
Temperaturstyring.Nettside.Termostatmodus[modus][SettID] = true
else
Temperaturstyring.Nettside.Termostatmodus[modus][SettID] = false
end
end
end

then have multiple versions of this row (but looking at the 5 tables) for each button
$(document).ready(function() { setTimeout('checkGIRDER(\'Temperaturstyring.Nettsi de.Termostatmodus\',\'mintermostatmodus\',\'key\', \'true\')',200); });

e.g.
$(document).ready(function() { setTimeout('checkGIRDER(\'Temperaturstyring.Nettsi de.Termostatmodus.0\',\'mintermostatmodus0\',\'key \',\'true\')',200); });
$(document).ready(function() { setTimeout('checkGIRDER(\'Temperaturstyring.Nettsi de.Termostatmodus.1\',\'mintermostatmodus1\',\'key \',\'true\')',200); });
$(document).ready(function() { setTimeout('checkGIRDER(\'Temperaturstyring.Nettsi de.Termostatmodus.2\',\'mintermostatmodus2\',\'key \',\'true\')',200); });
$(document).ready(function() { setTimeout('checkGIRDER(\'Temperaturstyring.Nettsi de.Termostatmodus.3\',\'mintermostatmodus3\',\'key \',\'true\')',200); });
$(document).ready(function() { setTimeout('checkGIRDER(\'Temperaturstyring.Nettsi de.Termostatmodus.4\',\'mintermostatmodus4\',\'key \',\'true\')',200); });

updating the button references as applicable

3. Something in the system can't take (norwegian characters). I think it's Girder since the values Kjkken is black even whithin quotes. So I just have to work around that somehow. Is that possible to do that in the script, with a translate table?
JPF: The only bits that interact with girder are the checkGIRDER string and the SendEvent string. So I doubt it is girder. It could be Javascript. You could prehaps print the ASCII code rather that type the character? Luckily in the UK we don't have strange characters!

4. I don't fully understand what you want to happen.

5. The RowID variable is used, but it does not need displaying. See the comment above re RowID and RowID2. Some arrays start at 0, others 1.

Jon

Mastiff
January 25th, 2015, 05:12 AM
Hi and thanks! Sorry I'm late answering, I'm at my cabin for the weekend, and I'll look at this when I get back Monday or Tuesday. But as for 4 I have different temperature lists for different modes (night temperatures, day temperatures, no frost temperatures and special temperatures for each room). I want the current temperature in the webpage to show the temperature for each room associated with the current mode. :) Was that easier to understand?

Mastiff
January 28th, 2015, 04:05 AM
Well, I'm back. And I'm back scratching my head. I think one thing at a time, so if you have the time I would like to consentrate on the setting of the modus first. I have changed the lines in the webpage as you said, so this is the function now:


function ScanInputs()
{
//$(document).ready(function() { setTimeout('checkGIRDER(\'girder_variable_path\',\ 'local name\',\'data type\',\'set button image\')',200); });
//where
//girder variable path is either to one table (e.g example Temperaturstyring.Nettside) or to a single path with nested tables (e.g example Temperaturstyring.myhtml)
//datatype is
$(document).ready(function() { setTimeout('checkGIRDER(\'Temperaturstyring.Nettsi de.Termostatmodus\',\'mintermostatmodus\',\'key\', \'true\')',200); });
$(document).ready(function() { setTimeout('checkGIRDER(\'Temperaturstyring.Nettsi de.Termostatmodus.0\',\'mintermostatmodus0\',\'key \',\'true\')',200); });
$(document).ready(function() { setTimeout('checkGIRDER(\'Temperaturstyring.Nettsi de.Termostatmodus.1\',\'mintermostatmodus1\',\'key \',\'true\')',200); });
$(document).ready(function() { setTimeout('checkGIRDER(\'Temperaturstyring.Nettsi de.Termostatmodus.2\',\'mintermostatmodus2\',\'key \',\'true\')',200); });
$(document).ready(function() { setTimeout('checkGIRDER(\'Temperaturstyring.Nettsi de.Termostatmodus.3\',\'mintermostatmodus3\',\'key \',\'true\')',200); });
$(document).ready(function() { setTimeout('checkGIRDER(\'Temperaturstyring.Nettsi de.Termostatmodus.4\',\'mintermostatmodus4\',\'key \',\'true\')',200); });


//set the number (default 1000) for the rescan time in milliseconds
setTimeout('ScanInputs()',1000);
}

Also I have changed the LUA script in Girder setting the variables, with a more descriptive (for me, at least) text:


print ("Termotstatmodus: "..pld1)
--print ("payload2: "..pld2)
print ("Linjenummer: "..pld3)
--print ("payload4: "..pld4)

local SettID = pld3
local SettTermostatmodus = pld1
local n
local modus
local max_n = table.getn(Temperaturstyring.Nettside.ID)

for n = 1,max_n,1 do
for modus = 0,4,1 do
print(modus)
if modus == SettTermostatmodus then
Temperaturstyring.Nettside.Termostatmodus[modus][SettID] = true
print('True')
else
print('False')
Temperaturstyring.Nettside.Termostatmodus[modus][SettID] = false
end
end
end

But I get error messages. It seems whatever I click on the outcome is false, and there is a field that isn't indexed:


Termotstatmodus: 2
Linjenummer: 13
0
False
[string "VM-Girder som hovedmaskin.gml:\Webserver ti..."]:20: attempt to index field `?' (a nil value)
stack traceback:
[string "VM-Girder som hovedmaskin.gml:\Webserver ti..."]:20: in main chunk



The line in question is this:

Temperaturstyring.Nettside.Termostatmodus[modus][SettID] = false

Do you by any chance see the probable reason for this? I'm afraid the for statements are confusing me a bit, so I can't debug it, even if I see that something goes wrong between the payload (which is correctly set from the button) to line 14, where the modus is 0 every time. :confused:

jon1977
January 28th, 2015, 02:44 PM
first thing:
$(document).ready(function() { setTimeout('checkGIRDER(\'Temperaturstyring.Nettsi de.Termostatmodus.0\',\'mintermostatmodus0\',\'key \',\'true\')',200); });
has a space after 'key which should not be there. Not sure if this is effecting your code, but it won't help.

Regarding the error message for Temperaturstyring.Nettside.Termostatmodus[modus][SettID] = false,
does the table Temperaturstyring.Nettside.Termostatmodus exist?, plus the sub table fields 0-4 plus in each of these the sub tables for each of the SettID's?
I'm guessing your trying to write to a variable in a table which has not been defined yet Thats normally what the ? means.
Check the variable inspector to see.

You may have to code this to create the empty table:



print ("Termotstatmodus: "..pld1)
--print ("payload2: "..pld2)
print ("Linjenummer: "..pld3)
--print ("payload4: "..pld4)

local SettID = pld3
local SettTermostatmodus = pld1
local n
local modus
local max_n = table.getn(Temperaturstyring.Nettside.ID)

Temperaturstyring.Nettside.Termostatmodus = Temperaturstyring.Nettside.Termostatmodus or {}

for n = 1,max_n,1 do
for modus = 0,4,1 do
print(modus)

Temperaturstyring.Nettside.Termostatmodus[modus] = Temperaturstyring.Nettside.Termostatmodus[modus] or {}
Temperaturstyring.Nettside.Termostatmodus[modus][SettID] = Temperaturstyring.Nettside.Termostatmodus[modus][SettID] or {}

if modus == SettTermostatmodus then
Temperaturstyring.Nettside.Termostatmodus[modus][SettID] = true
print('True')
else
print('False')
Temperaturstyring.Nettside.Termostatmodus[modus][SettID] = false
end
end
end


Try that first, and then come back to me.

Regards
Jon

Mastiff
January 28th, 2015, 03:13 PM
Thanks for answering, Jon! The extra space is now corrected. Actually there's another, extra space in your code, "Nettsi de." should be "Nettside.", I changed that before I did anything else the last time.

I also checked the variable inspector before I tried your new code, and the table was there. Emtpy, but there. It's created in the startup script:


if not Temperaturstyring then
Temperaturstyring={}
end

if not Temperaturstyring.Timere.Termostatmodus then
Temperaturstyring.Timere.Termostatmodus={}
end

if not Temperaturstyring.Nettside then
Temperaturstyring.Nettside={}
end

if not Temperaturstyring.Nettside.Termostatmodus then
Temperaturstyring.Nettside.Termostatmodus={}
end

Then I tried using your code, and that removed the error. But it sets all the five variables (0-4) to False, none to True, no matter what button I press. Still I guess that it's a step forward. :)

jon1977
January 28th, 2015, 03:54 PM
If it returns false, are you comparing a number to a string?
Do print(SettTermostatmodus) to check or better still store as a global variable so you can use the variable inspector to see if bothSettTermostatmodus and modus are numbers.
Jon.

Mastiff
January 29th, 2015, 02:00 AM
Sorry, I had gone to bed when that answer came. :) The problem seems to be that there is a number compared to nothing. I tried this code, first commenting out some of the print statements because they clogged up my logger and then printed SettTermostatmodus and modus:

print ("Termotstatmodus: "..pld1)
--print ("payload2: "..pld2)
print ("Linjenummer: "..pld3)
--print ("payload4: "..pld4)

local SettID = pld3
local SettTermostatmodus = pld1
print(SettTermostatmodus)
local n
local modus
local max_n = table.getn(Temperaturstyring.Nettside.ID)

Temperaturstyring.Nettside.Termostatmodus = Temperaturstyring.Nettside.Termostatmodus or {}

for n = 1,max_n,1 do
for modus = 0,4,1 do
--print(modus)

Temperaturstyring.Nettside.Termostatmodus[modus] = Temperaturstyring.Nettside.Termostatmodus[modus] or {}
Temperaturstyring.Nettside.Termostatmodus[modus][SettID] = Temperaturstyring.Nettside.Termostatmodus[modus][SettID] or {}

if modus == SettTermostatmodus then
Temperaturstyring.Nettside.Termostatmodus[modus][SettID] = true
--print('True')
else
--print('False')
Temperaturstyring.Nettside.Termostatmodus[modus][SettID] = false
end
end
end

print(modus)

And that final print(modus) gives nil as a result. I'm guessing that's not right. Or is it my mind that isn't right?

Printing the two tables gave me:

table: 0BE82E10
table: 0BE82E40

jon1977
January 29th, 2015, 05:27 AM
Send me your gml and web page and I'll have a look.
It'll be something daft.
Use table.print() to see the contents of a table. Print() won't work.
Jon.

Mastiff
January 29th, 2015, 05:40 AM
Thanks, Jon! Here it is.

jon1977
January 29th, 2015, 04:59 PM
Is this what you want to happen?
6817
Jon

jon1977
January 29th, 2015, 05:07 PM
If so, I'll explain what I did to do this.
Jon.

Mastiff
January 30th, 2015, 02:14 AM
Nice, sir! :) That's very nice! Yes, it works for me! I see that you have cleaned up the startup as well, I didn't know I could cut down the table making to one line like that! And yes, I'd very much like to know what you did. I see you have the different modes defined in the script as a to e, but I don't understand why it isn't used in the rest of the script.

Anyway, almost all the questions in the post on the previous page are addressed in this! And there's only one thing missing before I can try this script in "production", in other words let my wife and daughter loose on it and see if they can break it. If they can't, nobody can! I don't know if I have told you this, but my wife's the world's only living and walking Bermuda Triangle for technology! If there is just a small glitch anywhere in any thinkable system (car, home automation, anything!) it will surface when she's using it! :D The missing thing is what I tried to explain, but probably didn't explain well enough, under question 4. I don't know if it's possible, but I would like this to happen. Let me first explain how the full system works:

I have EventGhost with an attached RFXtrx433 to control the actual power and temperature with Nexa power plugs, while I use Girder to control the advanced stuff, just like this. EventGhost is more like a workhorse, while Girder's the brains behind. So as long as nothing happens in Girder, EventGhost will just keep the temperature within the set parameters. When Girder sends a message (command line) to change mode, EventGhost will still keep the temp within the parameters, only with the new parameters. Like my home office. At 6 in the morning a timer makes Girder send the commands to go from night mode (10 degrees) to day mode (20 degrees). Then, at 17 another timer sets it back to night mode. This is true for many of the rooms. The master bedroom has 10 degrees in the day, 16 at night because we don't use it in the daytime, and my wife can't sleep if it's less than 16. And our daughter's room has three temps: No frost 10 degrees while she's at school, 22 when she's at home (she has inherited my wife's sensitivity to cold) and 16 at night, when she's sleeping. Then there's the home theater and home gym, which both has 10 degrees as the regular temp and are set to 20 manually (which will be done with the buttons on the web page) a couple of hours before use. That can be done with any other room as well, for instance to set the master bedroom to 20 degrees if we are going to use it during the daytime.

There will be one real action in the mode script: To tell EventGhost to change mode. EG will at the same time put the new mode into the system registry. So when I have to reboot the automation VM or the physical server, the values for the rooms will be retained there. On startup EG will read the values to start keeping the right temperature again while Girder will read the values so that the buttons on the webpage will be correct. So when I open the webpage, the modes will be set to whatever EG is using at the moment. This means that there will be different modes for the different rooms. And here the main thing comes:

I would like the current temperature in column 3 (visible column 2, since the ID is hidden) to reflect the mode. So if the master bedroom is set to day, the temp for that room should be set to the day temp there, 10 degrees. And if the home gym is in use mode, I would like the set temp in the column to show 20 degrees. Likewise I would like column 4 (visible column 3) that canges the temperature in the column before to change the temperature in the current mode. So a long explanation for a short (and hopefully easy) request.

I hope that's clear enough, remember that English is not my first languague. :)

Mastiff
January 30th, 2015, 07:40 AM
Oh, another thing: With this system the fifth visible column (Modus n) isn't necessary at all. I commented it out for startes, and it doesn't seem to mess up anything. Am I right in that assumption?

Also I change the garbled names to ascii code, that seemed to work nicely. The only thing I'm not sure how to do there is to make the room name variable from Girder into that. Using &oslash instead of the made it print it literally in the webpage and &#248 came through to the webpage, but with the same garbling as . Is it possible do do a conversion in HTML so the input will send &oslash to the browser using the page?

Finally a cosmetic thing: The think frame round the table in the browser goes beyond the right end of the table. I was looking for the place that defines this border, but I could not find that. Dreamweaver won't show anything in design mode, probably because of all the variables. Is that fixable too?

And thank you very much for helping me out with this! :)

jon1977
February 2nd, 2015, 02:23 AM
Sorry, I've been away so have only just picked these messages up.
Please send through your GML and webpage file so I can see where your up to.
With regards
Jon

Mastiff
February 2nd, 2015, 03:21 AM
Thanks! And nNo worries, I'm not the one to complain about a short delay when somebody's helping me out! Well, I might make an exception if I'm drowning, of course... ;) Here's the package.

jon1977
February 2nd, 2015, 04:48 PM
With regards to the original error, and the reason I replaced the:
$(document).ready(function() { setTimeout('checkGIRDER(\'Temperaturstyring.Nettsi de.Termostatmodus.0\',\'mintermostatmodus0\',\'key \',\'true\')',200); });
with
$(document).ready(function() { setTimeout('checkGIRDER(\'Temperaturstyring.Nettsi de.Termostatmodus.a\',\'mintermostatmodus0\',\'key \',\'true\')',200); });

this was to prove a point, the table's within Temperaturstyring.Nettside.Termostatmodus in girder were identified with numbers, the text above was looking for a string.
Mixing up strings and numbers doesn't work with Javascript or Girder.
I added a mode_lookup table to substitute a number with a letter to permit using the for, next loop (numerical), but to change to a string.
You could change the a, b, c, d etc to "0", "1", "2" etc if you wanted.

I also ensured all buttons and rows had the correct id's for all on event's, there was a big mix up.

See the attached code, I've added a table to the startup script defining a temperature for modes 0, 1, 2, 3 and 4 (which are editable).
I've added a line of code to the sett termostatmodus girder code to set the respective thermnostat to that temperature. Is that what you mean?

As to finding text and replacing it on a web page, I'm sure its possible.
Can I suggest you browse some javascript web sites for find / replace in string.

see lines 198, 199 where the JSON datastring is split into a table of comma separated strings called DataStringSplit

see this website:
http://www.w3schools.com/jsref/jsref_replace.asp

I would suggest something like (note, this is incomplete, and will not work as written, but may get you started):



var DataStringSplit = DataString.toString().split(seperator);
//alert(DataStringSplit);
for (var i = 0; i < DataStringSplit.length; i++)
{
DataStringSplit[i] = DataStringSplit[i].replace("","&oslash")
DataStringSplit[i] = DataStringSplit[i].replace("findnext","replacewith")
etc...
$("#" + LocalVariable + "ID" + i).text(DataStringSplit[i]);

var res = str.replace("Microsoft", "W3Schools");




The settings for the dynamic table border are towards the end of the lhtml file within <STYLE> and </STYLE> and are defined seperetly for the table, rows and columns. Again, have a play with them and see what they do.


6821

Is this what you mean?

With regards

Jon

Mastiff
February 3rd, 2015, 03:02 AM
Hi again, and thanks a lot again! This is very close! ;) I must admit (as if it's something new - ha-ha) that this stuff is gettingway over my head. I will spend the evening trying to get my head around the suggestions you have made and see if I can understand them.

As for the "very close" there are two things that I probably just didn't explain properly, and I have no idea how to do them myself:

1. Changing the temperature in a mode does not retain the change if I switch into another mode and then go back. The next time I go into the mode where I changed the temperature before, it has reverted back to the original temperature for that mode from the startup script.

2. Finally for this to work as intended I need to be able to set not one common mode temperature, but separate temperatures for the different modes in the separate rooms. So if the day temp for room 1 is 20, the day temp for room 3 should still be able to be set at 22 (or whatever I like, from a startup script or by the dynamic change in the webpage), and so on. Is that undrstandable? Independent temperatures for all rooms in their different modes.

jon1977
February 6th, 2015, 06:43 AM
So, do I understand that you want to be able to update a mode default temperature for each individual room when it is selected from the web page and keep that update (even on a restart)
Not have a set of predefined defaults temperatures with a manual override temperature? i.e. which would reset on startup?
I understand what you mean by 2. If you wanted to have a go yourself, you just need a bigger default temperature table covering each room id and each mode, the question is how to store the updated default from the requirement above.
Do I recall that you store defaults in the registry? I guess you'd store the variables when updated and ensure you read them back on a restart.
I personally avoided that and use text files to store data as they're much more visible.
Have a stab at it.
If your struggling come back to me and I'll do it for you.
With regards
Jon

Mastiff
February 8th, 2015, 03:25 AM
Hi! Sorry about the late answer. I'm at my cabin right now, been busy with some automation and other stuff there.

Yeah, that's right. I have the temperatures defined in the system registry already, and I should be able to get them out pretty easily. And Girder would only need to read the changes on startup and not care any more about them since all the changes are done from Girder while the actual control is done in EventGhost (with an RFXtrx). So if Girder reads the values into the tables at startup and then works from that, and keeps the rest as regular variables the changes are recorded to the registry in EventGhost, so the next time I need a restart Girdre will read the current values from there. I prefer the registry to text files because I once had a text file getting garbled on a power outage (maybe because it was written to in the second that the power went out). That's never been a problem with registry. And I have a separate key in the registry for automation stuff, with subkeys for audio/video, lights and heat. Do you mean that I can do the rest in Girder? If I can it may actually be possible that I can manage in an evening or three this week. :) I can have a look when I get home again in a couple of days. Thanks!

Mastiff
February 13th, 2015, 02:59 PM
OK, no. Not that simple. I'm trying withy something like this:


if Temperaturstyring.Nettside.Termostatmodus == "a"
then Temperaturstyring.Nettside.Temperatur1[SettID] = SettTemperatur
end

But I can't really get it working at all. I really have a hard time wrapping my head around the true/false method. :( I know very well what I want to do, but not how to do it. So I hope you can help me getitng this finished. It's not far away, I think. You at least understand what I want to achieve, right?

jon1977
February 15th, 2015, 05:38 PM
Hi, only just seen this post. For some reason I don't always get an email if a new post in in a subscribed thread.
Reply with your lhtml file and gml and I'll have a look.
Jon.

Mastiff
February 15th, 2015, 11:03 PM
THank you! I just figured you were busy, so I took it easy. :) To be honest I didn't save much of my work, it didn't really work anyway. I did save the startup script, though:

Temperaturstyring = Temperaturstyring or {}
Temperaturstyring.Timere = Temperaturstyring.Timere or {}
Temperaturstyring.Timere.Termostatmodus = Temperaturstyring.Timere.Termostatmodus or {}
Temperaturstyring.Nettside = Temperaturstyring.Nettside or {}
Temperaturstyring.Nettside.Termostatmodus = Temperaturstyring.Nettside.Termostatmodus or {}


Temperaturstyring.Nettside.ID ={
[1] = 1,
[2] = 2,
[3] = 3,
[4] = 4,
[5] = 5,
[6] = 6,
[7] = 7,
[8] = 8,
[9] = 9,
[10] = 10,
[11] = 11,
[12] = 12,
[13] = 13
}

local max_n = table.getn(Temperaturstyring.Nettside.ID)
local n
local modus

local modus_lookup = {
[0] = "a",
[1] = "b",
[2] = "c",
[3] = "d",
[4] = "e"
}

for n = 1,max_n,1 do
for modus = 0,4,1 do
local modus_string = modus_lookup[modus]
Temperaturstyring.Nettside.Termostatmodus[modus_string] = Temperaturstyring.Nettside.Termostatmodus[modus_string] or {}
Temperaturstyring.Nettside.Termostatmodus[modus_string][n] = true
end
end

Temperaturstyring.Nettside.Rom ={
[1] = "WC",
[2] = "Garderoberom",
[3] = "Midtsoverom",
[4] = "Hjrnesoverom",
[5] = "Hovedsoverom",
[6] = "Bad",
[7] = "Stue",
[8] = "Kjkken",
[9] = "Kino",
[10] = "Biljardrom",
[11] = "Kjellerkontor",
[12] = "Treningsrom",
[13] = "Gjesterom",
}

Temperaturstyring.Nettside.Temperatur1 ={
[1] = "22",
[2] = "20",
[3] = "20",
[4] = "21",
[5] = "10",
[6] = "23",
[7] = "20",
[8] = "20",
[9] = "20",
[10] = "20",
[11] = "20",
[12] = "20",
[13] = "20"
}

Temperaturstyring.Nettside.Temperatur2 ={
[1] = "16",
[2] = "16",
[3] = "16",
[4] = "16",
[5] = "16",
[6] = "16",
[7] = "16",
[8] = "16",
[9] = "16",
[10] = "16",
[11] = "16",
[12] = "16",
[13] = "16"
}

Temperaturstyring.Nettside.Temperatur3 ={
[1] = "5",
[2] = "5",
[3] = "5",
[4] = "5",
[5] = "5",
[6] = "5",
[7] = "5",
[8] = "5",
[9] = "5",
[10] = "5",
[11] = "5",
[12] = "5",
[13] = "5"
}

Temperaturstyring.Nettside.Temperatur4 ={
[1] = "-",
[2] = "-",
[3] = "-",
[4] = "-",
[5] = "20",
[6] = "-",
[7] = "-",
[8] = "-",
[9] = "-",
[10] = "-",
[11] = "-",
[12] = "-",
[13] = "-"
}
Temperaturstyring.Nettside.status ={
[1] = 1,
[2] = 2,
[3] = 3,
[4] = 1,
[5] = 2,
[6] = 3,
[7] = 1,
[8] = 2,
[9] = 3,
[10] = 1,
[11] = 1,
[12] = 1,
[13] = 1
}

The difference is one separate table for each mode. And the corresponding setting of temperature that should take the mode in account:


local SettID = tonumber(pld3)
local SettTemperatur = pld2

print (Temperaturstyring.Nettside.Termostatmodus[SettID])
if Temperaturstyring.Nettside.Termostatmodus == "a"
then Temperaturstyring.Nettside.Temperatur1[SettID] = SettTemperatur
end

That's all that was left after 3-4 hours of head scratching. Not impressive, I know... The rest is just like the previous package you uploaded.

Btw another thing: You mentioned that you only took in the letter version of the mode to prove that I was comparing a string to a number. Is it possible to clean up that as well? A smaller script makes it easier for me to understand. :confused: On the other hand I have used some of the methods of manipulating tables and using an ID for the room here to create a new setup for the internet radio (callable from remote controls in all the rooms that has speakers), with saving of the channel, amp status and a bunch more! So I've already started putting it to use. I will use the first, simpler version of the web page as well for this, since the amps only need to show on/off, not different modes. :) Thanks for helping me improving my system!

jon1977
February 16th, 2015, 04:43 PM
is this what your after?
I've also made it clear the selection if set manually. I wasn't sure what the last column was for, but you can configure it in the setup script.
I haven't coded any of the interactions with the registry.
I also need to keep the number to string conversion, but I've used 1 = "1" rather than 1 = a, so it all looks similar.
I've also changed the temperature config table to a nested table to make it neater.
Hopefully that all makes sense.
I've included all files to make this work just in case anyone else wants to use this for info.
6834
With regards
Jon

Mastiff
February 17th, 2015, 02:42 AM
I'm afraid this one doesn't work. It locks up my browsers. I tried it with Firefox and IE (which I only use for testing), and both were stuck. Firefox had to be stopped from the task manager, while IE said "Localhost does not answer" and gave me a button to reload the webside. Which lead to a new lockup. So something is strange here. I have not had that problem with any of the earlier versions. And in the Girder log the WebServer entries keep going even though the browser has locked up. Do you have any idea what this can be?

I don't know if it's related, but when I opened the page I saw that the temperatures indicated different modi, but all the buttons were blu. None were green. Clicking on one of them gave a small, black cross (probably an indication that the correct image wasn't found or something).

jon1977
February 17th, 2015, 06:18 AM
Can you try again. It works fine for me.
I've re zipped the files, see attached in case they somehow got corrupted:
6835
Please make sure you replace the lhtml file and load the new GML. The other files are just for reference, you should already have them, they are unchanged.
Regards
Jon

Mastiff
February 17th, 2015, 06:51 AM
Now it worked, thanks! I have no idea what was wrong the last time, but I guess something was garbled. And it's even closer now, but I see three things that are a bit off, they may be related:

1. On startup there are different modes set for the different rooms (which I can see on the temperatures), but all buttons are red, so I can't see on the button which mode's selected.

2. When I set a new temperature for a mode even if the mode is set, so the button is green, the mode button will turn red (no matter what mode I had it set to), so all buttons in that row are red again, like on startup.

3. The new temperatures may not be saved in the variable. So if I set a new temperature for a mode in a room, switch the room to another mode and then go back to the mode where I changed the temperature, it will have the original temperature for that mode, not the new one I set.

Mastiff
February 17th, 2015, 07:04 AM
Forget this great discovery! It wasn't that after all, of course. I thought I had something there... Just made a fool of myself again... But it seems to update the regular table "Temperatur" instead of the SettTemperatur" table, and on a change of mode the Temperatur is the one being read. Can that be something?

You are not going to believe this, but I found the reason for number 3: There was a t missing in a few lines, so what should have been the nested table SettTemperatur was turned into a regular table called SetTemperatur! I am so shocked because I actually found this that I'm totally speachless! Good thing I'm writing this... :o

jon1977
February 17th, 2015, 03:32 PM
OK, this one will update the selected mode with the new temperature.
It loads with the selected mode highlighted.
I have added comments where the registry keys need entering to read (in the startup script) and write (when the temperature is updated). I'm reluctant to play with my registry on my live system in case something goes wrong, so are you ok doing this?
6836
Jon

Mastiff
February 18th, 2015, 02:11 AM
Bullseye, I think! :) Thank you very much! I have only tested it a little bit (work first, then play) but it seems to do exactly what I needed it to. As for the registry that's no problem at all, I'm very used to that kind of stuff. I have a registry key under HKLM called Automatisering (automation in Norwegian) where I store a bunch of stuff. I've been doing it like this since I started with Girder and I have had no problems with it. So I'll put in the registry write, as well as the actual send to the "workhorse" EventGhost of the changes in mode and temperature.

Btw interesting way of changing string to number, didn't know that one. :) I have used tostring(pld1) to do that. You don't know a good way of changing a string true to boolean true as well? I'm using an if pld1 == "true" then variable_x = true, but I'm guessing there is a better way.

Thank you very much again for all your work, this one will be used for the temperature and also modified to control wakeup times and a few other things! :)

Mastiff
February 18th, 2015, 04:48 AM
The only thing I didn't think about with reading from the registry (probably about the same if you read from a file) is how to do a full table. If not the nested table would make for insanely long lines with something like win.CreateRegistry('HKEY_CURRENT_USER', 'Software\\Automatisering\\Termostat\\1', 0):Read(1) five times in a row (one for each mode) for each of the rooms. Do you by any chance know how to do that easier? I'm not expecting it to be possible for the full nested table, but maybe a shorter line for each subtable? I can write a table to the registry:


for x,y in Temperaturstyring.Nettside.SettTemperatur[1] do
win.CreateRegistry('HKEY_CURRENT_USER', 'Software\\Automatisering\\Termostat', 0):Write(x,y)
end

This will write one full entry from the nested table (in this case the room with the ID 1), not the full nested table. Still it's much better than writing one value of the subtable at a time. :)

Edit: Got the nested stuff down as well:


for x in Temperaturstyring.Nettside.SettTemperatur do
for y,z in Temperaturstyring.Nettside.SettTemperatur[x] do
win.CreateRegistry('HKEY_CURRENT_USER', 'Software\\Automatisering\\Termostat\\'..x, 0):Write(y,z)
end
end

So it can be written, but I can't read it from the registry yet.

Mastiff
April 16th, 2015, 01:48 PM
I'm now fully up and running with the system, and it all works great! Thanks a lot for the help, Jon! The only thing left is to get the page itself to look a bit more fancy. I have now spent three hours trying to get it the way I want to, but I just cant get it! This is what it looks like now (never mind the color of the background and the buttons, I can fix that):

http://www.promixis.com/forums/attachment.php?attachmentid=6872&stc=1

I am simply unable to get the height and vertical alignment for the rows 4-9 right. I want the height to be four pixels more than the height of the buttons, which I have resized to a height of 25 pixels. And I have experimented with different heights for the rows, but for some reason they do not react. It's almost like there is something invisible somewhere that's two lines, but I can't figure out what. I believe the code interacting with the webpage is pretty much the same way it was when you made your last version. Do you have time to look at this for me? I think that will be the last time I bug you about this! :)

Here's the code I have now for the page (and it doesn't seem to obey the height and with at all, really).

jon1977
April 17th, 2015, 03:07 AM
Hi, I'm on holiday at the moment with no access to a PC to test. But there are a couple of things you can try. Note that a style sheet is used and the dynamic table also has attached style definitions (at the bottom of the file). These set styles for the table, rows and columns. I can't remember if these override what ever you set when you build the table, but they might do. I see there are styles setting justification.
I'm back next week and will be able to look then. Until then, suggest you see if these styles are overriding what your trying to do.
With regards.
Jon.

Mastiff
April 17th, 2015, 03:57 AM
Wow! I'm impressed. You're a better man than me. I would never manage a holiday without a pc that could do everything! ;) Enjoy your holiday, I will wait until you have the time. I haven't found anything in in the style sheet (or elsewhere) that specifies pixel height, so I think that's probably not it.

Have a great holiday in the meantime! :)

Mastiff
April 17th, 2015, 07:56 AM
By the way, when I'm at it: Is it possible to have one button that changes all rooms in an easy way? That would be very nice for when we're going to the cabin for a week or something like that. :)

jon1977
April 20th, 2015, 03:56 PM
Do you mean this?
6873

If so, at the end of each bit of code to build the table was the following:

&nbsp;

This is used for a none line break space, and I'm guessing because the column width was the same size as the button, it created a space anyway. Its strictly not necessary so I've deleted it.

I've also added a simple html based (rather than using a dynamic table) single button at the base of the page. This will create an event which you can use girder to do whatever you want with.
Is that what you mean?

With regards
Jon

Mastiff
April 21st, 2015, 02:22 AM
Great, it now looks exactly like I want to, and it obeys changes in height! Thanks a lot! :)

As for the "change all" I was really wanting to do that in a dynamic table, like the rest. So I could change all in the same way as I change room for room. I suppose I would have to let an extra "if then" in the Girder action script check for the ID of that and then do a full change of all the rest of the rooms, but that's not a problem to fix for me, at least in a dirty way (by having one line for each room in that "if then"). The problem is building the table.

I know I have to add an entry for that in the tables. I tried calling that 100, but of course that wasn't visible before I had 100 columns. And 0 didn't work at all. I could of course designate it 14 (since the number of rooms is 13 at the moment), but that would have to be changed when adding another room later. Is there a neat trick I could use for that? For instance a way to remove columns without any data before the table is built?

Finally, I forgot one little detail: The in the rooms "kjkken" (kitchen) and "hjrnesoverom" (bedroom in the corner of the house) is getting killed in the webpage. As long as it's inside Girder, the is drawn correctly, but when it comes to the webpage it's turned into �. Is there a way to fix that? It has to be a coding thing because I have the Norwegian character in the heading of the table (Temperatur n, or Temperature now), but in some way it's messed up somewhere between Girder and the table.

Edit: I tried to do that by changing the in Girder to and to &oslash; (HTML number and name for the letter), but that didn't work. It works if I write it into the regular HTML code of the page, but it doesn't work in the dynamic table.

jon1977
April 21st, 2015, 04:58 PM
I'm not sure what you mean.
Can I check. Do you mean columns (i.e. across) or rows (i.e. down).
I noticed in a previous post you referred to rows 4-9 when I assume you meant columns.
Can you sketch what your after in excel or word or hand sketch and scan in?
Do you mean make another table under the one displayed for different data?

I would guess to make the character, it may be an issue with the character set used.
See this line at the top of the code.


<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">

I seem to remember having a similar issue getting to display.

Try googling it. I think the character is missing from ISO-8859-1 and you may need to use a different one.

With regards
Jon

Mastiff
April 22nd, 2015, 02:15 AM
I mean like the attached image. It's "Alle rom" at the bottom, meaning "All rooms". So when I click that, they should all chang to that setting. I guess I do mess with the naming conventions at times, but I do mean to have it as a row (horizontally) like the single rooms. Maybe even separated from the other rooms with a double border, or something, so nobody clicks wrong by accident?

http://www.promixis.com/forums/attachment.php?attachmentid=6874&stc=1

As for the charset I actually do have UTF-8 there, and it doesn't help. The non dynamic characters are OK (like you can see in the heading row), but dynamic data is getting garbled. I guess it's something between the javascripts code and the data from Girder. Maybe the only way is to change the room naming column from dynamic to a regular column?

Edit: I see that Charset is mentioned in the file jquery.min.js. Is it possible that there is something there changing it?

Edit 2: I think this is a Girder problem, maybe an ajax problem. I tried the Girder Webserver standard page scripting.lhtml, set a variable dilldall = "aa", and the result in Firefox was "���aa". So there's something strange there.

jon1977
April 25th, 2015, 03:47 PM
See attached, I've added a second table to cover Alle rom.
Is this what you mean?

6875

This will send an different event to girder (I've assumed you can deal with the girder code, just copy the other code but get it to set all rooms rather than just one).
I've assumed you don't need to highlight the button pressed for Alle rom, as each rooms button will be highlighted.
Sounds like the character set maybe a girder thing. Perhaps raise a new thread and see if anyone can help.

Jon

Mastiff
April 27th, 2015, 06:25 AM
Thank you very much, Jon! That's very exactly what I wanted! :) I'll fiddle with the Girder code myself, I'm pretty sure I can get that working! :o

Mastiff
May 4th, 2015, 04:06 PM
I have now gone a bit further, trying to learn a rudimentary bit of CSS! Talk about teaching an old Mastiff new tricks! :D I have put most of the style info (except for that in a few lines of plain text) in a separate file to make it easier to change and make the main code easier to understand. And I have managed to get it pretty much the way I want to, except for two things. The first is that pesky special character. I had a back and forth with Ron and found out that I could add a line to the ajaxreq to get it working. The problem is that if I add the same line to your ajaxreqjson it kills the contents of the table (so no variables seem to be processed). The line is this:


webserver:SetHeader("Content-Type: application/json; charset=ISO-8859-1", true);

Do you have any idea why this line works to get special characters in the demo setup for the Girder webserver but stops everything here?

The second thing is that I have split the "alle rom" (all rooms) from the main table since I only need four choices (day temp, night temp, frost guard and off). So far so good, but what I can't get is how to make this into a table with two rows - one for the heading and one for the buttons. I only get them in front. I'm pretty sure it's because I haven't defined the table to have more rows. Could you please take a quick look at the allerom table and show me how to get that correct? I have attached the changed files (the lhtml and the CSS), the Girder stuff is not changed. I don't think you need the background graphics, so I haven't attached that.

It would be great if you could please take a look at those two things. The main system is still running without a hitch, so I'm really just doing the final niceties that make it look good as well as work good!

jon1977
May 9th, 2015, 02:11 PM
I can help you with the second issue.
When your building a dynamic table, or any table for that matter, you build it in rows.
So this bit:


$('#termostattabellAllerom').append('<table></table>');
var tableAllerom = $('#termostattabellAllerom').children();
var trAllerom = $('<tr>');

$('<td>Dag- temp</td>').appendTo(trAllerom);
$('<td>Natte- temp</td>').appendTo(trAllerom);
$('<td>Frost- vakt</td>').appendTo(trAllerom);
$('<td>Term. av</td>').appendTo(trAllerom);
trAllerom.appendTo(tableAllerom);

creates the first row of columns which are the titles.

You then need to say there is another row, so you need to add this:


var trAllerom = $('<tr>');

i.e. new row
before all of this:



//Sett dagtemperatur
var mintermostatmodus1Allerom_REF = '<center><a href=\"\" onclick=\'return SendEventPayload(\"SettTermostatmodusAllerom\", \"18\", \"1\" ,\"\" ,\"\",\"FromWeb\");\' onmousedown=\'return SetImage(\"mintermostatmodusAllerom1Button\", \"img/button_blue_down.jpg\");\' onmouseup=\'return SetImage(\"mintermostatmodusAllerom1Button\", \"img/button_blue_up.jpg\");\'><img src=\"img/button_blue_up.jpg\" id=\"mintermostatmodusAllerom1Button\" border=\"1\"></a></center>'
$('<td>'+mintermostatmodus1Allerom_REF+'</td>').appendTo(trAllerom);


etc.

I've spent a bit of time looking at the special character. I haven't been able to work out what is wrong. I don't think I've touched any of this default code and can only suspect that its something to do with json (which isn't used with the standard demo webserver).
I've googled using Norwegian characters and it appears to be a known issue.
I'm going to have to leave others to sort this out, it's beyond me!

With regards
Jon

Mastiff
May 10th, 2015, 05:13 AM
Thank you very much! Works perfectly! :o I'll pester Ron about that json thing. But if I'm not mistaken, json is used in the webserver's variable check. Because the line he gave me:

webserver:SetHeader("Content-Type: application/json; charset=ISO-8859-1", true)must mean that it is json that should be affected by this change. Still it doesn't seem to do anything to it.

Mastiff
May 10th, 2015, 05:22 AM
Oh, I see what you mean now. There's the require json, that's missing in the other one. Strange, though, since the line fixed the variables in the original webserver. According to a site I found on Google (https://developer.appcelerator.com/question/140334/preserve-special-characters-in-json-string) using this code should fix it, but I can't find out how:
utf8_encode('')

Mastiff
May 10th, 2015, 01:07 PM
But maybe you can help me with this: I have an annoying crash between timers and control from the website. I would like to have the main script check a variable to see if they're allowed to change the mode (for instance when I'm at the cabin and don't need the home office to be 20 degrees at 8 a.m.). I have so far used the mode 0, off, to do that, but when the winter comes again this will not work well because it may get too cold down there. So I added a column to the table:


//Deactivate timer control
var mintermostattimer_REF = '<center><a href=\"\" onclick=\'return SendEventPayload(\"SettTermostattimer\", \"18\", \"0\" ,\"\" ,\"'+RowID2+'\",\"FromWeb\");\' onmousedown=\'return SetImage(\"mintermostattimerButton'+RowID+'\", \"img/button_blue_down.jpg\");\' onmouseup=\'return SetImage(\"mintermostattimerButton'+RowID+'\", \"img/button_blue_up.jpg\");\'><img src=\"img/button_blue_up.jpg\" id=\"mintermostattimerButton'+RowID+'\" border=\"1\"></a></center>'
$('<td>'+mintermostattimer_REF+'</td>').appendTo(tr);

This sends to this script:


local SettID = pld3*1
local n
local timer
local max_n = table.getn(Temperaturstyring.Nettside.ID)

if not Temperaturstyring.Nettside.Termostattimer[SettID]
then Temperaturstyring.Nettside.Termostattimer[SettID] = "true"
end

if Temperaturstyring.Nettside.Termostattimer[SettID] == "false"
then Temperaturstyring.Nettside.Termostattimer[SettID] = "true"
else Temperaturstyring.Nettside.Termostattimer[SettID] = "false"
end

print("Room number"..SettID .. "now has the timermodus " .. Temperaturstyring.Nettside.Termostattimer[SettID])

And everything works (it changes the variable and all) except for one thing: I only see the blue button, and it doesn't change. So the web page doesn't get the true and false stuff. And I belive that's the only thing I don't understand yet of the script, how the buttons actually turn red and green. Maybe you could enlighten me about that and tell me how I can get that running too? I assume it's something I'm missing either in the webpage or maybe in the startup script? I haven't changed the startup script, I have only added this script with it's triggering event.

jon1977
May 12th, 2015, 04:09 PM
The way this bit of the code works is:

To define some girder tables to check once on startup, reference a local (web side) variable for use on the web page and define the table type (array, comma separated variable CSV or json keys) and whether a button needs its image changing i.e. true or false.
Then separately define girder tables to look at repeatedly for updating variables.

You have a new girder table to look at, and you want this to be updated automatically so you need to add the following:


$(document).ready(function() { setTimeout('checkGIRDER(\'Temperaturstyring.Nettsi de.Termostattimer\',\'Termostattimer\',\'key\',\'t rue\')',200); });

at line 38 (on the last copy of the code you sent me).

Next, looking at the function 'CheckData' on line 170, this is checking what data type was filled in (array, CSV or key) and parses the json datastream appropriately. If you temporarily uncomment (i.e. remove the //) from the line 173, leaving alert(data); (remembering to refresh the webpage to see the update) you will see a popup with the actual Json string that needs parsing. Recomment it to remove the popups.
Each version of the parsing code sets the javascript variable to the value in the girder table, building the javascript variable name up as 'local variable' (as defined above) concatenated with "ID" and a number representing the nth bit of data in the string or table.
The button javascript variable name is built up as 'local variable' concatenated with "Button" and a number representing the nth bit of data in the string or table.

So in this example, we have defined a local variable as 'Termostattimer'
So the 3rd button javascript variable would be TermostattimerButton3

So to update your code:


var mintermostattimer_REF = '<center><a href=\"\" onclick=\'return SendEventPayload(\"SettTermostattimer\", \"18\", \"0\" ,\"\" ,\"'+RowID2+'\",\"FromWeb\");\' onmousedown=\'return SetImage(\"TermostattimerButton'+RowID+'\", \"img/button_blue_down.jpg\");\' onmouseup=\'return SetImage(\"TermostattimerButton'+RowID+'\", \"img/button_blue_up.jpg\");\'><img src=\"img/button_blue_up.jpg\" id=\"TermostattimerButton'+RowID+'\" border=\"1\"></a></center>'
$('<td>'+mintermostattimer_REF+'</td>').appendTo(tr);


is that what your after?
Jon

Mastiff
May 13th, 2015, 01:18 PM
That's exactly what I want, thanks a lot! Worked as a charm, I can use that same code to turn on and off amps in the multi-zone system, and then use the "modus" setup for radio channels! Nifty trick to see what gets parsed as well, nice for debuggin! :)

Mastiff
December 16th, 2015, 03:49 AM
Jon, I'm back again! :) First of all I managed to fix the special character problem with the help of a local web guru, he found out that adding this line to the ajaxreqjson file:

webserver:SetHeaderEx("Content-Type", "text/plain; charset=iso-8859-1", true)

But if you have the time and would be so kind one day there is one thing I'd really love to add: A way to change alarm temperatures for the zones/rooms. I have one column for turning on and off the timer changes (the last column) and a column to write in the temperatures. The problem is of course that to write in temperatures only work when I'm in one of the modes (day, night and so on). So I could easily make a column for turning on and off alarm temperatures, or I could make one to select alarm temperatures. But that would mean that the day, night and whatever temperature wouldn't work. Is there a way to use the temperature editing column at the same time as having a on/off for alarm temperature? I have attached the setup, both the scripts in Girder, the changed ajaxreqson and the index.lhtml.

jon1977
December 18th, 2015, 11:14 AM
Hi. I'll have a look at your code when I get a minute.
Im not sure I fully understand what your after at the moment though.
Jon.

Mastiff
December 19th, 2015, 03:52 AM
Thanks a lot! Let me try to clarify: For each zone/room there are 4 modes that has their own individual temperatures (day, night, frost guard and special temperatures) plus "off" which doesn't do any temperature to choose between. Off is the second to last column. They are mutually exclusive. If one of them are selected, the other four can not be. This way it's possible to choose the type of temperature from the web page, so a few hours before somebody's going to use the home gym they will set it from frost guard (which will be 5 degrees) to day temp (which will be 20). Also if they think it's too warm or too cold with regular day temp they can edit the temperature for that mode in the text input column and click on "set temp" to change the temp for that mode. Then there's the last column, which sets a varible for the timer to off or on. That way I can have my office go into night mode (the heater keeping it above 12 degrees) at 5 p.m. and then start heating it up to 20 at 5 a.m. Now I'm at the cabin, so I have clicked the timer to off, and then it won't do that. So that's what there so far.

What I wish for is a separate alarm mode (that I can set to for instance 5 degrees in a regular room or -15 in the freezer) that can be turned off and on, like the timer column, but which will also have a temperature associated with it. And the alarm mode should not be mutually exclusive with the regular modes, so it should be possible to have an alarm active at the same time as a regular heating mode is active. I'm starting to think that this would be better in a separate table though, to avoid having too much in the main table. So if you could make a separate table just for that, with the possibility to turn the alarm mode on and off, and to input a temperature to associate with the alarm mode, that would probably be the best. Then I could have that table further down in the same page.

Did that make it any clearer?