Page 2 of 76
Re: LUA Pass2php
Posted: Saturday 08 October 2016 9:59
by Egregius
deennoo wrote:Hi there !
Since i got some great lighting speed reaction on my testing machine, i try now to provid the same on my Syno
DS216Play running DSM and PHP 5.6
All script are in place as they are on my test machine but your script isn't trigger.
Put them all right on 777 (not secure I now)
Put them all under domoticz user or admin or my name user, and still nothing, don't kno what to check, have you some idea ?
Hi,
I'm reacting here so other people can help or benefit from it.
I store my pass2php.php file in the webstation folder at /volume1/web/secure/pass2php.php
That way I can enable OPCache (speedup php parsing) and do a curl of the page in the lua script:
Code: Select all
JSON=loadfile('/volume1/@appstore/domoticz/var/scripts/JSON.lua')()
base64=loadfile('/volume1/@appstore/domoticz/var/scripts/base64.lua')()
c=base64.encode(JSON:encode(devicechanged))
s=base64.encode(JSON:encode(otherdevices))
i=base64.encode(JSON:encode(otherdevices_idx))
t=base64.encode(JSON:encode(otherdevices_lastupdate))
--os.execute('/volume1/web/secure/pass2php.php "'..c..'" "'..s..'" "'..i..'" "'..t..'" &')
os.execute('curl -s --data "c='..c..'&s='..s..'&i='..i..'&t='..t..'" http://127.0.0.1/secure/pass2php.php &')
commandArray={}
return commandArray
Thanks to that I improved my response time from 80-100msec down to 43msec.
This also requires a change in the php file:
Code: Select all
$c=json_decode(base64_decode($_REQUEST['c']),true);$s=json_decode(base64_decode($_REQUEST['s']),true);$i=json_decode(base64_decode($_REQUEST['i']),true);$t=json_decode(base64_decode($_REQUEST['t']),true);$a=$s[key($c)];$devidx=$i[key($c)];
Re: LUA Pass2php
Posted: Saturday 08 October 2016 17:46
by deennoo
Thanx for your help probleme was solve by using php file of my test machine on the syno webserver.
Lot of my switch script now goes with pass2php (WAF is near 90% !).
I solve some switch speed recieving/sending probleme by using rfxcom to recieve and rflink to send or reverse depending case.
I'm using some event with "set on for X minutes" : garden light when door open and light under 80lux, is there a way to provid the same ?
Got a small probleme with some chacon rf switch (54700 modules, the one you put being your real switch),some time they send order twice (On On or Off Off) using full toggle fonction (the one where we look about last change), On On make light blink (normal, script do the job, as fast as he can but light doesn't stay On or Off).
Is there a way to use only the first change and don't care about the second order ?
Looking at you php code next week and try to add scene/group control (coping/adapt the sw section)
Re: LUA Pass2php
Posted: Saturday 08 October 2016 18:42
by Egregius
For the blink you could try something like:
Code: Select all
if($s['switch']=='Off')sw($i['switch'],'On');
else sw($i['switch'],'Off');
For the on for...
I only switch them on when pirs is active.
Switch of is in a function that gets executed every minute and on every temperature update.
There I have a if stetement that checks if pir is off and lastupdate of pi and switch is more than x minutes ago.
So that truly switches off x minuets AFTER the last thing.
There are many lines like that in my big pass2php file.
Re: LUA Pass2php
Posted: Saturday 19 November 2016 1:07
by Nhzz
Great work! Got this kind of scripted myself, but I have Domoticz start a script on each device-input. This might be a good upgrade to my own code.
Just to be sure I got this correct: You make a event for each device. That event fires the LUA script, that on its turn runs the PHP code through curl.
Re: LUA Pass2php
Posted: Saturday 19 November 2016 5:23
by Egregius
Nhzz wrote:You make a event for each device.
Not sure what you mean by this. I only have one script in domoticz under scripts/lua/script_device_pass2php.lua
A script_device script is called by any device update you get.
There fore, in the script you have to catch witch device triggered. That's done in the $events array.
So, for example your PIR has idx 123 and you want to switch the light of the hall on with it:
Code: Select all
$events=array(123=>'PIRhall');
function PIRhall(){
global $a,$s,$i;
if($a=='On')sw($i['Lighthall'],'On');
}
Keep in mind that everything is case sensitive and that my code isn't equipped to handle spaces in de device names.
Re: LUA Pass2php
Posted: Saturday 19 November 2016 7:44
by Nhzz
Egregius wrote:Nhzz wrote:You make a event for each device.
Not sure what you mean by this. I only have one script in domoticz under scripts/lua/script_device_pass2php.lua
A script_device script is called by any device update you get.
There fore, in the script you have to catch witch device triggered. That's done in the $events array.
So, for example your PIR has idx 123 and you want to switch the light of the hall on with it:
Code: Select all
$events=array(123=>'PIRhall');
function PIRhall(){
global $a,$s,$i;
if($a=='On')sw($i['Lighthall'],'On');
}
Keep in mind that everything is case sensitive and that my code isn't equipped to handle spaces in de device names.
Maybe my question was a bit vague. What I meant was: How does Domoticz know to call your LUA script? On your website you state that we have to create a device lua script ("Maak in Domoticz Events een device lua script, pas eventueel de foldernamen aan."). I thought you made a setting of somekind that tells domoticz to run the LUA on a signal of PIRhall (and every other input) manually. But I understand this is just one script, but how does Domoticz know to run that script.
The PHP-part of your solution is pretty straight forward, kind of the same I allready have. The part interests me is the technique behind running one script for all devices.
Thanks!
Re: LUA Pass2php
Posted: Saturday 19 November 2016 8:11
by Egregius
Either you put the script in the database under the menu Setup -> More Options -> Events as device script.
Or you put it as file in the scripts/lua folder with the name script_device_pass2php.lua
Tests showed that file based scripts are executed before the ones in the database resulting in a few milliseconds faster response time.
On
http://www.domoticz.com/wiki/Events there's some explanation about the Domoticz Event system.
In short: all scripts with a name that start with script_device_***.lua are executed upon every device update.
Re: LUA Pass2php
Posted: Monday 21 November 2016 12:09
by Nhzz
Egregius wrote:Either you put the script in the database under the menu Setup -> More Options -> Events as device script.
Or you put it as file in the scripts/lua folder with the name script_device_pass2php.lua
Tests showed that file based scripts are executed before the ones in the database resulting in a few milliseconds faster response time.
On
http://www.domoticz.com/wiki/Events there's some explanation about the Domoticz Event system.
In short: all scripts with a name that start with script_device_***.lua are executed upon every device update.
Nice, that was what I meant.
Re: LUA Pass2php
Posted: Monday 28 November 2016 0:21
by G3rard
@Egregius
I am busy installing LUA pass2php, but having an error message running a test.
I get:
Code: Select all
Notice: Undefined index: Ledlampenzolder in /var/www/html/fp/php/secure/pass2php.php on line 14
Code: Select all
Fatal error: Call to undefined function dl
This is my pass2php lua file.
Code: Select all
function execute(command)
-- returns success, error code, output.
local f = io.popen(command..' 2>&1 && echo " $?"')
local output = f:read"*a"
return output
end
JSON=loadfile('/home/gerard/domoticz/scripts/lua/functions/JSON.lua')()
base64=loadfile('/home/gerard/domoticz/scripts/lua/functions/base64.lua')()
c=base64.encode(JSON:encode(devicechanged))
s=base64.encode(JSON:encode(otherdevices))
i=base64.encode(JSON:encode(otherdevices_idx))
t=base64.encode(JSON:encode(otherdevices_lastupdate))
--str=execute('/volume1/web/secure/pass2php.php "'..c..'" "'..s..'" "'..i..'" "'..t..'" &')
str=execute('curl -s --data "c='..c..'&s='..s..'&i='..i..'&t='..t..'" http://127.0.0.1/fp/php/secure/pass2php.php &')
print(str)
commandArray={}
print('PHP script runs')
return commandArray
And the PHP page
Code: Select all
#!/usr/bin/php
<?php
error_reporting(E_ALL);ini_set("display_errors","on");date_default_timezone_set('Europe/Amsterdam');
define('api',"http://127.0.0.1:8084/");
$t=microtime(true);$micro=sprintf("%03d",($t-floor($t))*1000);define('stamp',strftime("%Y-%m-%d %H:%M:%S.", $t).$micro);
$c=json_decode(base64_decode($_REQUEST['c']),true);$s=json_decode(base64_decode($_REQUEST['s']),true);$i=json_decode(base64_decode($_REQUEST['i']),true);$t=json_decode(base64_decode($_REQUEST['t']),true);$a=$s[key($c)];$devidx=$i[key($c)];
//Create the array of events. Wich idx calls wich function?
$events=array(369=>'Test_switch');
if(isset($events[$devidx]))call_user_func($events[$devidx]);
//Start of user functions
function Test_switch(){
global $a,$s,$i,$t;
if($a=="On"){
sw($i['Ledlampenzolder'],'On');
}
if($a=="Off"){
sw($i['Ledlampenzolder'],'Off');
}
}
//End of user functions
// ========== FUNCTIONS ==========
/* sw switches $idx on/off. If no action is provided a toggle is made. $info is optional logging */
function sw($idx,$action="",$info=""){
$t=microtime(true);$micro=sprintf("%03d",($t-floor($t))*1000);$stamp=strftime("%Y-%m-%d %H:%M:%S.", $t).$micro;
print $stamp." Switch ".$idx." (".ucfirst($info).") ".strtoupper($action)."
";
if(empty($action)) curl(api."json.htm?type=command¶m=switchlight&idx=".$idx."&switchcmd=Toggle");
else curl(api."json.htm?type=command¶m=switchlight&idx=".$idx."&switchcmd=".$action);
usleep(400000);
}
/* sl sets dimmer $idx to level $level. $info is optional logging */
function sl($idx,$level,$info=""){
$t=microtime(true);$micro=sprintf("%03d",($t-floor($t))*1000);$stamp=strftime("%Y-%m-%d %H:%M:%S.", $t).$micro;
print $stamp." Set Level ".$idx." ".ucfirst($info)." ".$level."
";
curl(api . "json.htm?type=command¶m=switchlight&idx=".$idx."&switchcmd=Set%20Level&level=".$level);
usleep(400000);
}
/* ud updates a device $idx with $nvalue and $svalue. $info is optional logging */
function ud($idx,$nvalue,$svalue,$info=""){
$t=microtime(true);$micro=sprintf("%03d",($t-floor($t))*1000);$stamp=strftime("%Y-%m-%d %H:%M:%S.", $t).$micro;
if(!in_array($idx, array(395,532,534))) print $stamp." --- UPDATE ".$idx." ".$info." ".$nvalue." ".$svalue."
";
curl(api.'json.htm?type=command¶m=udevice&idx='.$idx.'&nvalue='.$nvalue.'&svalue='.$svalue);
usleep(400000);
}
function curl($url){dl("curl.so");$headers=array('Content-Type: application/json',);$ch=curl_init();curl_setopt($ch,CURLOPT_URL,$url);curl_setopt($ch,CURLOPT_HTTPHEADER,$headers);curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);curl_setopt($ch, CURLOPT_FRESH_CONNECT, TRUE);$data=curl_exec($ch);curl_close($ch);return $data;}
Any ideas what I can do to fix this?
Re: LUA Pass2php
Posted: Monday 28 November 2016 0:37
by Egregius
'Ledlampenzolder' is exactly as it is in Domoticz? It is case sensitive...
Guess you can also remove "dl("curl.so");" from the curl function. I once needed it when I first moved to Syno, now I don't need it anymore.
Re: LUA Pass2php
Posted: Monday 28 November 2016 0:39
by G3rard
Yep the name is exactly the same.
Removed the DL part and no Domoticz is not responding anymore
Re: LUA Pass2php
Posted: Monday 28 November 2016 0:47
by Egregius
I do have another command for the curl, I can't call it by just using 'execute', I have to use 'os.execute'.
Code: Select all
JSON=loadfile('/volume1/@appstore/domoticz/var/scripts/JSON.lua')()
base64=loadfile('/volume1/@appstore/domoticz/var/scripts/base64.lua')()
c=base64.encode(JSON:encode(devicechanged))
s=base64.encode(JSON:encode(otherdevices))
i=base64.encode(JSON:encode(otherdevices_idx))
t=base64.encode(JSON:encode(otherdevices_lastupdate))
os.execute('curl -s --data "c='..c..'&s='..s..'&i='..i..'&t='..t..'" http://127.0.0.1/secure/pass2php.php &')
commandArray={}
return commandArray
Maybe add this just before //Create the array of events
That should print the complete idx array like [Ledlampenzolder] => 123
Or for testing, use the IDX in the sw command:
sw(123,'On');
Re: LUA Pass2php
Posted: Monday 28 November 2016 0:52
by G3rard
I made a function execute so I can see the output in the log, so that is working fine.
Just had to reboot my machine, because I couldn't restart Domoticz anymore (there goes my uptime
).
Re: LUA Pass2php
Posted: Monday 28 November 2016 0:56
by Egregius
I also see the output, don't needed to do anything about that.
But you're right, all the rest is good, otherwise you wouldn't even get that error.
So try my other 2 suggestions.
Re: LUA Pass2php
Posted: Monday 28 November 2016 1:13
by G3rard
With the IDX it is working. Now also working with the device name (renamed the switch in both places).
But still have the undefined function dl error message and I am a bit reluctant to do any changes to the function as I had to reboot the server as Domoticz was not responding and could not be restarted anymore.
Any ideas?
Re: LUA Pass2php
Posted: Monday 28 November 2016 6:59
by Egregius
Domoticz not responding has nothing to do with this script or the dl function.
I need the dl once because I couldn't get curl to work. Because your installation indicates that it an't find dl it makes no difference if you remove it or not. Only the error line will dissapear.
Strange thing about the name tough. There aren't duplicate names? Or was it a brand new switch?
Re: LUA Pass2php
Posted: Monday 28 November 2016 8:47
by G3rard
Egregius wrote:Domoticz not responding has nothing to do with this script or the dl function.
I need the dl once because I couldn't get curl to work. Because your installation indicates that it an't find dl it makes no difference if you remove it or not.
Yeah it does. When I only removed "dl" in the function, Domoticz log indicates that the LUA script is running for more then 10 seconds.
When I removed "dl("curl.so");", Domoticz did not respond anymore after I pressed the switch which was in the array in the PHP file.
I had an uptime of more then 100 days, so that's no coincidence.
I will try to find another solution for the curl function.
Re: LUA Pass2php
Posted: Monday 28 November 2016 10:15
by Egregius
Then your execute function is preventing the backgrounding of the process by the & at the end of the command. I never had a notification that it took to long.
You can replace curl with file_get_contents, something like this should do it (not tested)
Code: Select all
$ctx=stream_context_create(array('http'=>array('timeout' => 5)));
function sw($idx,$action="",$info="",$Usleep=600000){
global $ctx;
$t=microtime(true);$micro=sprintf("%03d",($t-floor($t))*1000);$stamp=strftime("%Y-%m-%d %H:%M:%S.", $t).$micro;
print $stamp." --- SWITCH ".$action." ".$info." ".PHP_EOL;
if(empty($action))file_get_contents("http://127.0.0.1:8084/json.htm?type=command¶m=switchlight&idx=".$idx."&switchcmd=Toggle",false,$ctx);
else file_get_contents("http://127.0.0.1:8084/json.htm?type=command¶m=switchlight&idx=".$idx."&switchcmd=".$action,false,$ctx);usleep($Usleep);
}
function sl($idx,$level,$info="",$Usleep=600000){
global $ctx;
$t=microtime(true);$micro=sprintf("%03d",($t-floor($t))*1000);$stamp=strftime("%Y-%m-%d %H:%M:%S.", $t).$micro;
print $stamp." --- SETLEVEL ".$level." ".$info." ".PHP_EOL;
file_get_contents("http://127.0.0.1:8084/json.htm?type=command¶m=switchlight&idx=".$idx."&switchcmd=Set%20Level&level=".$level,false,$ctx);usleep($Usleep);
}
function ud($idx,$nvalue,$svalue,$info="",$Usleep=600000){
global $ctx;
$t=microtime(true);$micro=sprintf("%03d",($t-floor($t))*1000);$stamp=strftime("%Y-%m-%d %H:%M:%S.", $t).$micro;
if(!in_array($idx, array(395,532,534)))print $stamp." --- UPDATE ".$nvalue." ".$svalue." ".$info.PHP_EOL;
file_get_contents('http://127.0.0.1:8084/json.htm?type=command¶m=udevice&idx='.$idx.'&nvalue='.$nvalue.'&svalue='.$svalue,false,$ctx);usleep($Usleep);
}
Re: LUA Pass2php
Posted: Monday 28 November 2016 23:31
by G3rard
Thanks for your help.
Tried the file_get_contents but that has influence on the event system as well, makes the other LUA scripts run > 10 seconds...
I get the following error
Code: Select all
Warning: file_get_contents(http://127.0.0.1:8084/json.htm?type=command¶m=switchlight&idx=338&switchcmd=On : failed to open stream: HTTP request failed! in /var/www/html/fp/php/secure/pass2php.php on line 33
Line 33 is
Code: Select all
else file_get_contents("http://127.0.0.1:8084/json.htm?type=command¶m=switchlight&idx=".$idx."&switchcmd=".$action,false,$ctx);usleep($Usleep);
I'll leave it at that for now.
Re: LUA Pass2php
Posted: Tuesday 29 November 2016 7:07
by Egregius
Did you revert the lua script to the original os.execute?