PageRenderTime 102ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/main.php

https://github.com/morksmail/OpenSprinkler-Controller
PHP | 1599 lines | 1468 code | 91 blank | 40 comment | 158 complexity | e6df31b5ce654aa8bde12b8713e95ff8 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. #Refuse if a direct call has been made
  3. if(!defined('Sprinklers')){header($_SERVER['SERVER_PROTOCOL'].' 404 Not Found', true, 404);exit();}
  4. #Check if config exists, if not redirect to install
  5. if (!file_exists("config.php")) {header("Location: install.php");exit();}
  6. #Change time out to 5 seconds (default is 60)
  7. ini_set('default_socket_timeout', 5);
  8. #Set script timeout to 6 seconds to give time for socket to timeout and return error
  9. set_time_limit(6);
  10. #Include configuration
  11. require_once("config.php");
  12. date_default_timezone_set('UTC');
  13. #Check if PHP has str_getcsv function or if it needs a fallback
  14. if (!function_exists('str_getcsv')) {
  15. function str_getcsv($input, $delimiter = ',', $enclosure = '"') {
  16. $fh = fopen('php://temp', 'r+');
  17. fwrite($fh, $input);
  18. rewind($fh);
  19. $row = fgetcsv($fh,0,$delimiter,$enclosure);
  20. fclose($fh);
  21. return $row;
  22. }
  23. }
  24. #Help migrate older configurations
  25. if (!isset($auto_delay)) {
  26. changeConfig("auto_delay",0);
  27. $auto_delay = 0;
  28. }
  29. if (!isset($auto_mm)) {
  30. changeConfig("auto_mm",0);
  31. $auto_mm = 0;
  32. }
  33. if (!isset($auto_delay_duration)) {
  34. changeConfig("auto_delay_duration",24);
  35. $auto_delay_duration = 24;
  36. }
  37. if (!isset($woeid)) {
  38. $woeid = get_woeid();
  39. changeConfig("woeid",$woeid);
  40. }
  41. #Get Base URL of Site
  42. if (isset($_SERVER['SERVER_NAME'])) $base_url = (($force_ssl) ? "https://" : "http://").$_SERVER['SERVER_NAME'].$_SERVER['PHP_SELF'];
  43. #Call action if requested and allowed
  44. if (isset($_REQUEST['action'])) {
  45. if (is_callable($_REQUEST['action'])) {
  46. if (($_REQUEST['action'] == "gettoken" || $_REQUEST['action'] == "checktoken" || $_REQUEST['action'] == "login") || is_auth()) {
  47. if (in_array($_REQUEST["action"], array("clear_logs","change_user","add_user","delete_user","make_user_list","auto_mm_on","auto_mm_off","current_status","submit_stations","make_stations_list","get_autodelay","submit_autodelay","get_weather","make_list_logs","gettoken","checktoken","login","runonce","send_en_mm","make_settings_list","make_list_status","make_list_manual","fresh_program","make_all_programs","make_runonce","spoff","spon","mm_off","mm_on","en_on","en_off","rbt","rsn","raindelay","submit_options","delete_program","update_program","get_preview","import_config","export_config"))) {
  48. call_user_func($_REQUEST['action']);
  49. }
  50. } else {
  51. header($_SERVER['SERVER_PROTOCOL'].' 401 Unauthorized', true, 401);
  52. }
  53. exit();
  54. } else {
  55. exit();
  56. }
  57. }
  58. #Weather functions
  59. #Resolve location to WOEID
  60. function get_woeid() {
  61. $options = get_options();
  62. $data = file_get_contents("http://query.yahooapis.com/v1/public/yql?q=select%20woeid%20from%20geo.placefinder%20where%20text=%22".urlencode($options["loc"])."%22");
  63. preg_match("/<woeid>(\d+)<\/woeid>/", $data, $woeid);
  64. return intval($woeid[1]);
  65. }
  66. #Get the current weather code and temp
  67. function get_weather_data() {
  68. global $woeid;
  69. $data = file_get_contents("http://weather.yahooapis.com/forecastrss?w=".$woeid);
  70. if ($data === false) return array();
  71. preg_match("/<yweather:condition\s+text=\"([\w|\s]+)\"\s+code=\"(\d+)\"\s+temp=\"(\d+)\"\s+date=\"(.*)\"/", $data, $newdata);
  72. preg_match("/<title>Yahoo! Weather - (.*)<\/title>/",$data,$loc);
  73. preg_match("/<yweather:location .*?country=\"(.*?)\"\/>/",$data,$region);
  74. $region = $region[1];
  75. if ($region == "United States" || $region == "Bermuda" || $region == "Palau") {
  76. $temp = $newdata[3]."&#176;F";
  77. } else {
  78. $temp = intval(($newdata[3]-32)*(5/9))."&#176;C";
  79. }
  80. $weather = array("text"=>$newdata[1],"code"=>$newdata[2],"temp"=>$temp,"date"=>$newdata[4],"location"=>$loc[1]);
  81. return $weather;
  82. }
  83. #Lookup code and get the set delay
  84. function code_to_delay($code) {
  85. global $auto_delay_duration;
  86. $adverse_codes = array(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,35,37,38,39,40,41,42,43,44,45,46,47);
  87. $reset_codes = array(36);
  88. if (in_array($code, $adverse_codes)) return $auto_delay_duration;
  89. if (in_array($code, $reset_codes)) return 0;
  90. return false;
  91. }
  92. #Check the current weather for the devices location, and set the appropriate delay, if needed
  93. function weather_to_delay() {
  94. $weather = get_weather_data();
  95. $delay = code_to_delay($weather["code"]);
  96. if ($delay === false) return;
  97. send_to_os("/cv?pw=&rd=".$delay);
  98. }
  99. function get_weather() {
  100. echo json_encode(get_weather_data());
  101. }
  102. #Export/Import
  103. function export_config() {
  104. $data = get_from_os("/gp?d=0");
  105. preg_match("/pd=\[\];(.*);/", $data, $progs);
  106. $progs = explode(";", $progs[1]);
  107. $i = 0;
  108. foreach ($progs as $prog) {
  109. $tmp = explode("=", $prog);
  110. $newdata["programs"][$i] = $tmp[1];
  111. $i++;
  112. }
  113. $newdata["options"] = get_options();
  114. $vs = get_stations();
  115. $newdata["stations"] = $vs["stations"];
  116. $newdata["masop"] = $vs["masop"];
  117. echo json_encode($newdata);
  118. }
  119. function import_config() {
  120. if (!isset($_REQUEST["data"])) echo 0;
  121. $data = json_decode($_REQUEST["data"],true);
  122. if (is_null($data)) echo 0;
  123. $cs = "/cs?pw="; $co = "/co?pw="; $cp_start = "/cp?pw="; $i = 0;
  124. foreach ($data["options"] as $key => $value) {
  125. if (is_array($value)) {
  126. if (in_array($key, array(16,21,22,25)) && $value["val"] == 0) continue;
  127. $co .= "&o".$key."=".$value["val"];
  128. } else if ($key == "loc") {
  129. $co .= "&".$key."=".urlencode($value);
  130. }
  131. }
  132. send_to_os($co);
  133. foreach ($data["stations"] as $station) {
  134. $cs .= "&s".$i."=".urlencode($station);
  135. $i++;
  136. }
  137. $i = 0;
  138. foreach ($data["masop"] as $bit) {
  139. $cs .= "&m".$i."=".urlencode($bit);
  140. $i++;
  141. }
  142. send_to_os($cs);
  143. send_to_os("/dp?pw=&pid=-1");
  144. foreach ($data["programs"] as $prog) {
  145. send_to_os($cp_start."&pid=-1&v=".$prog);
  146. }
  147. }
  148. #OpenSprinkler functions
  149. #Get station names
  150. function get_stations() {
  151. $data = get_from_os("/vs");
  152. preg_match("/snames=\[(.*)\];/", $data, $matches);
  153. $rawstations = str_getcsv($matches[1],",","'");
  154. preg_match("/nboards=(\d+)/", $data, $matches);
  155. $total = $matches[1] * 8; $current = 1;
  156. foreach ($rawstations as $station) {
  157. if ($current > $total) break;
  158. $station = preg_replace("/\\\u([0-9a-eA-E]{4})/", "&#x\\1;", $station);
  159. $stations[] = $station;
  160. $current++;
  161. }
  162. preg_match("/masop=\[(.*?)\]/", $data, $masop);
  163. $masop = explode(",",$masop[1]);
  164. return array("stations" => $stations,"masop" => $masop);
  165. }
  166. #Get program information
  167. function get_programs() {
  168. $data = get_from_os("/gp?d=0");
  169. preg_match_all("/(nprogs|nboards|ipas|mnp)=[\w|\d|.\"]+/", $data, $opts);
  170. foreach ($opts[0] as $variable) {
  171. if ($variable === "") continue;
  172. $tmp = str_replace('"','',explode("=", $variable));
  173. $newdata[$tmp[0]] = $tmp[1];
  174. }
  175. preg_match("/pd=\[\];(.*);/", $data, $progs);
  176. if (empty($progs)) return $progs;
  177. $progs = explode(";", $progs[1]);
  178. $i = 0;
  179. foreach ($progs as $prog) {
  180. $tmp = explode("=", $prog);
  181. $tmp2 = str_replace("[", "", $tmp[1]);
  182. $tmp2 = str_replace("]", "", $tmp2);
  183. $program = explode(",", $tmp2);
  184. #Reset variables
  185. $days0 = $program[1]; $days1 = $program[2]; $even = false; $odd = false; $interval = false; $days = ""; $stations = "";
  186. $newdata["programs"][$i]["en"] = $program[0];
  187. $newdata["programs"][$i]["start"] = $program[3];
  188. $newdata["programs"][$i]["end"] = $program[4];
  189. $newdata["programs"][$i]["interval"] = $program[5];
  190. $newdata["programs"][$i]["duration"] = $program[6];
  191. for ($n=0; $n < $newdata["nboards"]; $n++) {
  192. $bits = $program[7+$n];
  193. for ($s=0; $s < 8; $s++) {
  194. $stations .= ($bits&(1<<$s)) ? "1" : "0";
  195. }
  196. }
  197. $newdata["programs"][$i]["stations"] = $stations;
  198. if(($days0&0x80)&&($days1>1)){
  199. #This is an interval program
  200. $days=array($days1,$days0&0x7f);
  201. $interval = true;
  202. } else {
  203. #This is a weekly program
  204. for($d=0;$d<7;$d++) {
  205. if ($days0&(1<<$d)) {
  206. $days .= "1";
  207. } else {
  208. $days .= "0";
  209. }
  210. }
  211. if(($days0&0x80)&&($days1==0)) {$even = true;}
  212. if(($days0&0x80)&&($days1==1)) {$odd = true;}
  213. }
  214. $newdata["programs"][$i]["days"] = $days;
  215. $newdata["programs"][$i]["is_even"] = $even;
  216. $newdata["programs"][$i]["is_odd"] = $odd;
  217. $newdata["programs"][$i]["is_interval"] = $interval;
  218. $i++;
  219. }
  220. return $newdata;
  221. }
  222. function get_preview() {
  223. process_programs($_REQUEST["m"],$_REQUEST["d"],$_REQUEST["y"]);
  224. }
  225. function process_programs($month,$day,$year) {
  226. $newdata = array();
  227. $newdata["settings"] = get_settings();
  228. $vs = get_stations();
  229. $newdata["stations"] = $vs["stations"];
  230. $data = get_from_os("/gp?d=".$day."&m=".$month."&y=".$year);
  231. preg_match_all("/(seq|mas|wl|sdt|mton|mtoff|devday|devmin|dd|mm|yy|nprogs|nboards|ipas|mnp)=[\w|\d|.\"]+/", $data, $opts);
  232. foreach ($opts[0] as $variable) {
  233. if ($variable === "") continue;
  234. $tmp = str_replace('"','',explode("=", $variable));
  235. $newdata[$tmp[0]] = $tmp[1];
  236. }
  237. preg_match("/masop=\[(.*?)\]/", $data, $masop);
  238. $newdata["masop"] = explode(",",$masop[1]);
  239. preg_match("/pd=\[\];(.*);/", $data, $progs);
  240. $progs = explode(";", $progs[1]);
  241. $i = 0;
  242. foreach ($progs as $prog) {
  243. $tmp = explode("=", $prog);
  244. $tmp2 = str_replace("[", "", $tmp[1]);
  245. $tmp2 = str_replace("]", "", $tmp2);
  246. $newdata["programs"][$i] = explode(",",$tmp2);
  247. $i++;
  248. }
  249. $simminutes=0;
  250. $simt=strtotime($newdata["mm"]."/".$newdata["dd"]."/".$newdata["yy"]);
  251. $simdate=date(DATE_RSS,$simt);
  252. $simday = ($simt/3600/24)>>0;
  253. $match=array(0,0);
  254. $st_array=array($newdata["nboards"]*8);
  255. $pid_array=array($newdata["nboards"]*8);
  256. $et_array=array($newdata["nboards"]*8);
  257. for($sid=0;$sid<$newdata["nboards"]*8;$sid++) {
  258. $st_array[$sid]=0;$pid_array[$sid]=0;$et_array[$sid]=0;
  259. }
  260. do {
  261. $busy=0;
  262. $match_found=0;
  263. for($pid=0;$pid<$newdata["nprogs"];$pid++) {
  264. $prog=$newdata["programs"][$pid];
  265. if(check_match($prog,$simminutes,$simdate,$simday,$newdata)) {
  266. for($sid=0;$sid<$newdata["nboards"]*8;$sid++) {
  267. $bid=$sid>>3;$s=$sid%8;
  268. if($newdata["mas"]==($sid+1)) continue; // skip master station
  269. if($prog[7+$bid]&(1<<$s)) {
  270. $et_array[$sid]=$prog[6]*$newdata["wl"]/100>>0;$pid_array[$sid]=$pid+1;
  271. $match_found=1;
  272. }
  273. }
  274. }
  275. }
  276. if($match_found) {
  277. $acctime=$simminutes*60;
  278. if($newdata["seq"]) {
  279. for($sid=0;$sid<$newdata["nboards"]*8;$sid++) {
  280. if($et_array[$sid]) {
  281. $st_array[$sid]=$acctime;$acctime+=$et_array[$sid];
  282. $et_array[$sid]=$acctime;$acctime+=$newdata["sdt"];
  283. $busy=1;
  284. }
  285. }
  286. } else {
  287. for($sid=0;$sid<$newdata["nboards"]*8;$sid++) {
  288. if($et_array[$sid]) {
  289. $st_array[$sid]=$simminutes*60;
  290. $et_array[$sid]=$simminutes*60+$et_array[$sid];
  291. $busy=1;
  292. }
  293. }
  294. }
  295. }
  296. if ($busy) {
  297. $endminutes=run_sched($simminutes*60,$st_array,$pid_array,$et_array,$newdata,$simt)/60>>0;
  298. if($newdata["seq"]&&$simminutes!=$endminutes) $simminutes=$endminutes;
  299. else $simminutes++;
  300. for($sid=0;$sid<$newdata["nboards"]*8;$sid++) {$st_array[$sid]=0;$pid_array[$sid]=0;$et_array[$sid]=0;}
  301. } else {
  302. $simminutes++;
  303. }
  304. } while($simminutes<24*60);
  305. }
  306. function check_match($prog,$simminutes,$simdate,$simday,$data) {
  307. if($prog[0]==0) return 0;
  308. if (($prog[1]&0x80)&&($prog[2]>1)) {
  309. $dn=$prog[2];$drem=$prog[1]&0x7f;
  310. if(($simday%$dn)!=(($data["devday"]+$drem)%$dn)) return 0;
  311. } else {
  312. $wd=(date("w",strtotime($simdate))+6)%7;
  313. if(($prog[1]&(1<<$wd))==0) return 0;
  314. $dt=date("j",strtotime($simdate));
  315. if(($prog[1]&0x80)&&($prog[2]==0)) {if(($dt%2)!=0) return 0;}
  316. if(($prog[1]&0x80)&&($prog[2]==1)) {
  317. if($dt==31) return 0;
  318. else if ($dt==29 && date("n",strtotime($simdate))==2) return 0;
  319. else if (($dt%2)!=1) return 0;
  320. }
  321. }
  322. if($simminutes<$prog[3] || $simminutes>$prog[4]) return 0;
  323. if($prog[5]==0) return 0;
  324. if((($simminutes-$prog[3])/$prog[5]>>0)*$prog[5] == ($simminutes-$prog[3])) {
  325. return 1;
  326. }
  327. return 0;
  328. }
  329. function run_sched($simseconds,$st_array,$pid_array,$et_array,$data,$simt) {
  330. $endtime=$simseconds;
  331. for($sid=0;$sid<$data["nboards"]*8;$sid++) {
  332. if($pid_array[$sid]) {
  333. if($data["seq"]==1) {
  334. time_to_text($sid,$st_array[$sid],$pid_array[$sid],$et_array[$sid],$data,$simt);
  335. if(($data["mas"]>0)&&($data["mas"]!=$sid+1)&&($data["masop"][$sid>>3]&(1<<($sid%8))))
  336. echo "{'start': ".($st_array[$sid]+$data["mton"]).",'end': ".($et_array[$sid]+$data["mtoff"]).",'content':'','className':'master','group':'Master'},";
  337. $endtime=$et_array[$sid];
  338. } else {
  339. time_to_text($sid,$simseconds,$pid_array[$sid],$et_array[$sid],$data,$simt);
  340. if(($data["mas"]>0)&&($data["mas"]!=$sid+1)&&($data["masop"][$sid>>3]&(1<<($sid%8))))
  341. $endtime=($endtime>$et_array[$sid])?$endtime:$et_array[$sid];
  342. }
  343. }
  344. }
  345. if($data["seq"]==0&&$data["mas"]>0) echo "{'start': ".$simseconds.",'end': ".$endtime.",'content':'','className':'master','group':'Master'},";
  346. return $endtime;
  347. }
  348. function time_to_text($sid,$start,$pid,$end,$data,$simt) {
  349. $class = "program-".(($pid+3)%4);
  350. if (($data["settings"]["rd"]!=0)&&($simt+$start+($data["settings"]["tz"]-48)*900<=$data["settings"]["rdst"])) $class="delayed";
  351. echo "{'start': ".$start.",'end': ".$end.",'className':'".$class."','content':'P".$pid."','group':'".$data["stations"][$sid]."'},";
  352. }
  353. #Get OpenSprinkler options
  354. function get_options() {
  355. $data = get_from_os("/vo");
  356. preg_match("/var opts=\[(.*)\];/", $data,$opts);
  357. preg_match("/loc=\"(.*)\"/",$data,$loc);
  358. preg_match("/nopts=(\d+)/", $data, $nopts);
  359. $newdata["loc"] = $loc[1];
  360. $newdata["nopts"] = $nopts[1];
  361. $data = explode(",", $opts[1]);
  362. for ($i=3; $i <= count($data); $i=$i+4) {
  363. $o = intval($data[$i]);
  364. if (in_array($o, array(1,12,13,15,16,17,18,19,20,21,22,23,25))) $newdata[$o] = array("en" => $data[$i-2],"val" => $data[$i-1]);
  365. }
  366. $newdata = move_keys(array(15,17,19,20,23),$newdata);
  367. $newdata = move_keys(array(16,21,22,25),$newdata);
  368. return $newdata;
  369. }
  370. #Get OpenSprinkler settings
  371. function get_settings() {
  372. $data = get_from_os("");
  373. preg_match_all("/(ver|devt|nbrd|tz|en|rd|rs|mm|rdst|mas|urs|wl|ipas)=[\w|\d|.\"]+/", $data, $matches);
  374. preg_match("/loc=\"(.*)\"/",$data,$loc);
  375. preg_match("/lrun=\[(.*)\]/", $data, $lrun);
  376. preg_match("/ps=\[(.*)\];/",$data,$ps);
  377. $ps = explode("],[",$ps[1]);
  378. $i = 0;
  379. foreach ($ps as $p) {
  380. $ps[$i] = explode(",",str_replace(array("[","]"), "", $ps[$i]));
  381. $i++;
  382. }
  383. $newdata = array("ps" => $ps, "lrun" => explode(",", $lrun[1]), "loc" => $loc[1]);
  384. foreach ($matches[0] as $variable) {
  385. if ($variable === "") continue;
  386. $tmp = str_replace('"','',explode("=", $variable));
  387. $newdata[$tmp[0]] = $tmp[1];
  388. }
  389. return $newdata;
  390. }
  391. function get_station_status() {
  392. preg_match("/\d+/", get_from_os("/sn0"), $data);
  393. return str_split($data[0]);
  394. }
  395. #Check if operation and manual mode are enabled. Also return version information
  396. function start_data() {
  397. $settings = get_settings();
  398. $en = ($settings["en"] == 1) ? "selected" : "";
  399. $mm = ($settings["mm"] == 1) ? "selected" : "";
  400. $ver = join(".",str_split($settings["ver"]));
  401. return array("en"=>$en,"mm"=>$mm,"ver"=>$ver);
  402. }
  403. function get_autodelay() {
  404. global $auto_delay,$auto_delay_duration;
  405. echo json_encode(array("auto_delay"=>$auto_delay,"auto_delay_duration"=>$auto_delay_duration));
  406. }
  407. #Send command to OpenSprinkler
  408. function send_to_os($url) {
  409. global $os_ip, $os_pw;
  410. $url = str_replace("pw=", "pw=".$os_pw, $url);
  411. $result = file_get_contents("http://".$os_ip.$url);
  412. if ($result === false) { echo 0; exit(); }
  413. echo 1;
  414. }
  415. function get_from_os($url) {
  416. global $os_ip, $os_pw;
  417. $url = str_replace("pw=", "pw=".$os_pw, $url);
  418. return file_get_contents("http://".$os_ip.$url);
  419. }
  420. #Updates a program
  421. function update_program() {
  422. send_to_os("/cp?pw=&pid=".$_REQUEST["pid"]."&v=".$_REQUEST["data"]);
  423. }
  424. #Deletes a program
  425. function delete_program() {
  426. send_to_os("/dp?pw=&pid=".$_REQUEST["pid"]);
  427. }
  428. #Submit auto-delay settings
  429. function submit_autodelay() {
  430. global $auto_delay,$auto_delay_duration;
  431. $autodelay = json_decode($_REQUEST["autodelay"],true);
  432. $switch = ($autodelay["auto_delay"] === "on") ? 1 : 0;
  433. if ($switch !== $auto_delay) {
  434. $auto_delay = $switch;
  435. if (!changeConfig("auto_delay",$switch)) {
  436. echo 2;
  437. exit();
  438. }
  439. }
  440. $switch = intval($autodelay["auto_delay_duration"]);
  441. if ($switch !== $auto_delay_duration) {
  442. $auto_delay_duration = $switch;
  443. if (!changeConfig("auto_delay_duration",$switch)) {
  444. echo 2;
  445. exit();
  446. }
  447. }
  448. echo 1;
  449. }
  450. #Submit updated options
  451. function submit_options() {
  452. send_to_os("/co?pw=&".http_build_query(json_decode($_REQUEST["options"])));
  453. $woeid = get_woeid();
  454. changeConfig("woeid",$woeid);
  455. }
  456. #Submit updated stations
  457. function submit_stations() {
  458. $masop = (isset($_REQUEST["masop"])) ? "&".http_build_query(json_decode($_REQUEST["masop"])) : "";
  459. send_to_os("/cs?pw=&".http_build_query(json_decode($_REQUEST["names"])).$masop);
  460. }
  461. #Submit run-once program
  462. function runonce() {
  463. send_to_os("/cr?pw=&t=".$_REQUEST["data"]);
  464. }
  465. #Submit rain delay
  466. function raindelay() {
  467. send_to_os("/cv?pw=&rd=".$_REQUEST["delay"]);
  468. }
  469. #Reset all stations (turn-off)
  470. function rsn() {
  471. send_to_os("/cv?pw=&rsn=1");
  472. }
  473. #Reboot OpenSprinkler
  474. function rbt() {
  475. send_to_os("/cv?pw=&rbt=1");
  476. }
  477. #Change operation to on
  478. function en_on() {
  479. send_to_os("/cv?pw=&en=1");
  480. }
  481. #Change operation to off
  482. function en_off() {
  483. send_to_os("/cv?pw=&en=0");
  484. }
  485. #Switch manual mode on
  486. function mm_on() {
  487. send_to_os("/cv?pw=&mm=1");
  488. }
  489. #Switch manual mode off
  490. function mm_off() {
  491. send_to_os("/cv?pw=&mm=0");
  492. }
  493. #Turn specific station on
  494. function spon() {
  495. send_to_os("/sn".$_REQUEST["zone"]."=1&t=0");
  496. }
  497. #Turn specific station off
  498. function spoff() {
  499. send_to_os("/sn".$_REQUEST["zone"]."=0");
  500. }
  501. #Turn off automatic disable of manual mode
  502. function auto_mm_off() {
  503. if (changeConfig("auto_mm",0)) {
  504. $auto_mm = 0;
  505. echo 1;
  506. exit();
  507. }
  508. echo 0;
  509. }
  510. #Turn on automatic disable of manual mode
  511. function auto_mm_on() {
  512. if (changeConfig("auto_mm",1)) {
  513. $auto_mm = 1;
  514. echo 1;
  515. exit();
  516. }
  517. echo 0;
  518. }
  519. #Content generation functions
  520. function make_list_logs() {
  521. #Adapted from the script written by David B. Gustavson, 20121021
  522. global $log_file;
  523. $graphing = isset($_REQUEST["type"]) && $_REQUEST["type"] == "graph";
  524. if (!$graphing) $list = "<div data-role='collapsible-set' data-inset='true' data-theme='b' data-collapsed-icon='arrow-d' data-expanded-icon='arrow-u'>";
  525. $vs = get_stations();
  526. $ValveName = $vs["stations"];
  527. $settings = get_settings();
  528. $tz = $settings["tz"] - 48;
  529. $tz = (($tz>=0) ? "+" : "-").((abs($tz)/4)*60*60)+(((abs($tz)%4)*15/10).((abs($tz)%4)*15%10) * 60);
  530. $SprinklerValveHistory=file_get_contents($log_file);
  531. $Lines=explode("\n",$SprinklerValveHistory);
  532. $SprinklerPattern = array();
  533. for ($i=0;$i<count($Lines);$i++){
  534. $ELines[$i]=explode("--",$Lines[$i]);
  535. if (count($ELines[$i])>1){
  536. $timeThis=strtotime($ELines[$i][1]);
  537. if (!(($timeThis >= $_REQUEST["start"]) && ($timeThis <= $_REQUEST["end"]))) continue;
  538. $SprinklerPattern[]=str_split($ELines[$i][0]);
  539. $SprinklerTime[]=$ELines[$i][1];
  540. $SprinklerTimeConverted[]=strtotime($ELines[$i][1]);
  541. if ($settings["urs"] == 1 && isset($ELines[$i][2])) $RainSensor[]=$ELines[$i][2];
  542. if (isset($ELines[$i][3])) $RainDelay[]=$ELines[$i][3];
  543. };
  544. };
  545. for ($i=0;$i<count($SprinklerPattern);$i++){
  546. if (isset($RainSensor[$i])) {
  547. if (($i>0) && ($RainSensor[$i-1]=="1") && ($RainSensor[$i]=="0") || ($i==count($RainSensor)-1) && ($RainSensor[$i]=="1")) {
  548. $TimeNow = $SprinklerTimeConverted[$i];
  549. $TimeBegin = $TimeNow;
  550. for ($k=1;$k<$i;$k++) {
  551. if ($RainSensor[$i-$k]=="1"){
  552. $TimeBegin=$SprinklerTimeConverted[$i-$k];
  553. } else { break; };
  554. };
  555. if (($i==count($RainSensor)-1)&&($RainSensor[$i]=="1")) $TimeNow = time();
  556. $TimeElapsed=$TimeNow-$TimeBegin;
  557. $now = (($i==count($RainSensor)-1)&&($RainSensor[$i]=="1"));
  558. if (!$TimeElapsed && !$now) continue;
  559. $RainHistory[]= array($SprinklerTime[$i], $TimeElapsed, ($now ? " Running Now" : ""));
  560. }
  561. }
  562. if (isset($RainDelay[$i])) {
  563. if (($i>0) && ($RainDelay[$i-1]=="1") && ($RainDelay[$i]=="0") || ($i==count($RainDelay)-1) && ($RainDelay[$i]=="1")) {
  564. $TimeNow = $SprinklerTimeConverted[$i];
  565. $TimeBegin = $TimeNow;
  566. for ($k=1;$k<$i;$k++) {
  567. if ($RainDelay[$i-$k]=="1"){
  568. $TimeBegin=$SprinklerTimeConverted[$i-$k];
  569. } else { break; };
  570. };
  571. if (($i==count($RainDelay)-1)&&($RainDelay[$i]=="1")) $TimeNow = time();
  572. $TimeElapsed=$TimeNow-$TimeBegin;
  573. $now = (($i==count($RainDelay)-1)&&($RainDelay[$i]=="1"));
  574. if (!$TimeElapsed && !$now) continue;
  575. $DelayHistory[]= array($SprinklerTime[$i], $TimeElapsed, ($now ? " Running Now" : ""));
  576. }
  577. }
  578. for ($j=0;$j<count($ValveName);$j++){
  579. if (!isset($SprinklerPattern[$i-1][$j])) continue;
  580. if (($i>0) && ($SprinklerPattern[$i-1][$j]=="1") && ($SprinklerPattern[$i][$j]=="0")|| ($i==count($SprinklerPattern)-1) && ($SprinklerPattern[$i][$j]=="1")) {
  581. $TimeNow = $SprinklerTimeConverted[$i];
  582. $TimeBegin = $TimeNow;
  583. for ($k=1;$k<$i;$k++) {
  584. if ($SprinklerPattern[$i-$k][$j]=="1"){
  585. $TimeBegin=$SprinklerTimeConverted[$i-$k];
  586. } else { break; };
  587. };
  588. if (($i==count($SprinklerPattern)-1)&&($SprinklerPattern[$i][$j]=="1")) $TimeNow = time();
  589. $TimeElapsed=$TimeNow-$TimeBegin;
  590. $now = (($i==count($SprinklerPattern)-1)&&($SprinklerPattern[$i][$j]=="1"));
  591. if (!$TimeElapsed && !$now) continue;
  592. $ValveHistory[$j][]= array($SprinklerTime[$i], $TimeElapsed, ($now ? " Running Now" : ""));
  593. };
  594. };
  595. };
  596. $table_header = "<table><thead><tr><th data-priority='1'>Runtime</th><th data-priority='2'>Date/Time</th></tr></thead><tbody>";
  597. $hour = array(array(0,0),array(1,0),array(2,0),array(3,0),array(4,0),array(5,0),array(6,0),array(7,0),array(8,0),array(9,0),array(10,0),array(11,0),array(12,0),array(13,0),array(14,0),array(15,0),array(16,0),array(17,0),array(18,0),array(19,0),array(20,0),array(21,0),array(22,0),array(23,0));
  598. $month = array(array(0,0),array(1,0),array(2,0),array(3,0),array(4,0),array(5,0),array(6,0),array(7,0),array(8,0),array(9,0),array(10,0),array(11,0));
  599. $dow = array(array(0,0),array(1,0),array(2,0),array(3,0),array(4,0),array(5,0),array(6,0));
  600. $data = array();
  601. for ($j=0;$j<count($ValveName);$j++) {
  602. if ($graphing) {
  603. if (isset($_REQUEST["sort"])) {
  604. switch ($_REQUEST["sort"]) {
  605. case 'dow':
  606. $data[$j] = $dow;
  607. $date_needed = "w";
  608. break;
  609. case 'month':
  610. $data[$j] = $month;
  611. $date_needed = "n";
  612. break;
  613. case 'hour':
  614. $data[$j] = $hour;
  615. $date_needed = "G";
  616. break;
  617. default:
  618. break;
  619. }
  620. } else {
  621. $data[$j] = array();
  622. $date_needed = "U";
  623. }
  624. }
  625. if (!isset($ValveHistory[$j])) continue;
  626. if (!$graphing) {
  627. $ct=count($ValveHistory[$j]);
  628. $list .= "<div data-role='collapsible' data-collapsed='true'><h2><div class='ui-btn-up-c ui-btn-corner-all custom-count-pos'>".$ct.(($ct == 1) ? " run" : " runs" )."</div>".$ValveName[$j]."</h2>".$table_header;
  629. }
  630. for ($k=0;$k<count($ValveHistory[$j]);$k++){
  631. $theTime = strtotime($ValveHistory[$j][$k][0])+$tz;
  632. $mins = round($ValveHistory[$j][$k][1]/60);
  633. if ($graphing) {
  634. $info = intval(date($date_needed,$theTime));
  635. if (isset($_REQUEST["sort"])) {
  636. $data[$j][$info][1] += $mins;
  637. } else {
  638. $data[$j][] = array($info*1000,0);
  639. $data[$j][] = array($info*1000,$mins);
  640. $data[$j][] = array(($info+($mins*60))*1000,0);
  641. }
  642. } else {
  643. $list .= "<tr><td>".$mins.(($mins == 1) ? " min" : " mins")."</td><td>".date('D, d M Y H:i',$theTime).$ValveHistory[$j][$k][2]."</td></tr>";
  644. }
  645. };
  646. if (!$graphing) $list .= "</tbody></table></div>";
  647. };
  648. $ValveName[$j] = "Rain Sensor";
  649. if ($graphing) {
  650. if (isset($_REQUEST["sort"])) {
  651. switch ($_REQUEST["sort"]) {
  652. case 'dow':
  653. $data[$j] = $dow;
  654. $date_needed = "w";
  655. break;
  656. case 'month':
  657. $data[$j] = $month;
  658. $date_needed = "n";
  659. break;
  660. case 'hour':
  661. $data[$j] = $hour;
  662. $date_needed = "G";
  663. break;
  664. default:
  665. break;
  666. }
  667. } else {
  668. $data[$j] = array();
  669. $date_needed = "U";
  670. }
  671. }
  672. if (isset($RainHistory)) {
  673. if (!$graphing) {
  674. $ct=count($RainHistory);
  675. $list .= "<div data-role='collapsible' data-collapsed='true'><h2><div class='ui-btn-up-c ui-btn-corner-all custom-count-pos'>".$ct.(($ct == 1) ? " switch" : " switches" )."</div>Rain Sensor</h2>".$table_header;
  676. }
  677. for ($k=0;$k<count($RainHistory);$k++){
  678. $theTime=strtotime($RainHistory[$k][0])+$tz;
  679. $mins = round($RainHistory[$k][1]/60);
  680. if ($graphing) {
  681. $info = intval(date($date_needed,$theTime));
  682. if (isset($_REQUEST["sort"])) {
  683. $data[$j][$info][1] += $mins;
  684. } else {
  685. $data[$j][] = array($info*1000,0);
  686. $data[$j][] = array($info*1000,$mins);
  687. $data[$j][] = array(($info+($mins*60))*1000,0);
  688. }
  689. } else {
  690. $list .= "<tr><td>".$mins.(($mins == 1) ? " min" : " mins")."</td><td>".date('D, d M Y H:i',$theTime).$RainHistory[$k][2]."</td></tr>";
  691. }
  692. };
  693. if (!$graphing) $list .= "</tbody></table></div>";
  694. }
  695. $j++; $ValveName[$j] = "Rain Delay";
  696. if ($graphing) {
  697. if (isset($_REQUEST["sort"])) {
  698. switch ($_REQUEST["sort"]) {
  699. case 'dow':
  700. $data[$j] = $dow;
  701. $date_needed = "w";
  702. break;
  703. case 'month':
  704. $data[$j] = $month;
  705. $date_needed = "n";
  706. break;
  707. case 'hour':
  708. $data[$j] = $hour;
  709. $date_needed = "G";
  710. break;
  711. default:
  712. break;
  713. }
  714. } else {
  715. $data[$j] = array();
  716. $date_needed = "U";
  717. }
  718. }
  719. if (isset($DelayHistory)) {
  720. if (!$graphing) {
  721. $ct=count($DelayHistory);
  722. $list .= "<div data-role='collapsible' data-collapsed='true'><h2><div class='ui-btn-up-c ui-btn-corner-all custom-count-pos'>".$ct.(($ct == 1) ? " change" : " changes" )."</div>Rain Delay</h2>".$table_header;
  723. }
  724. for ($k=0;$k<count($DelayHistory);$k++){
  725. $theTime=strtotime($DelayHistory[$k][0])+$tz;
  726. $mins = round($DelayHistory[$k][1]/60);
  727. if ($graphing) {
  728. $info = intval(date($date_needed,$theTime));
  729. if (isset($_REQUEST["sort"])) {
  730. $data[$j][$info][1] += $mins;
  731. } else {
  732. $data[$j][] = array($info*1000,0);
  733. $data[$j][] = array($info*1000,$mins);
  734. $data[$j][] = array(($info+($mins*60))*1000,0);
  735. }
  736. } else {
  737. $list .= "<tr><td>".$mins.(($mins == 1) ? " min" : " mins")."</td><td>".date('D, d M Y H:i',$theTime).$DelayHistory[$k][2]."</td></tr>";
  738. }
  739. };
  740. if (!$graphing) $list .= "</tbody></table></div>";
  741. }
  742. if ($graphing) {
  743. echo json_encode(array("data" => $data, "stations" => $ValveName));
  744. } else {
  745. echo $list."</div>";
  746. }
  747. }
  748. #Make run-once list
  749. function make_runonce() {
  750. $list = "<p style='text-align:center'>Value is in minutes. Zero means the station will be excluded from the run-once program.</p><div data-role='fieldcontain'>";
  751. $n = 0;
  752. $data = get_programs();
  753. $vs = get_stations();
  754. $stations = $vs["stations"];
  755. foreach ($stations as $station) {
  756. $list .= "<label for='zone-".$n."'>".$station.":</label><input type='number' data-highlight='true' data-type='range' name='zone-".$n."' min='0' max='50' id='zone-".$n."' value='0'>";
  757. $n++;
  758. }
  759. $list .= "</div><a data-role='button' onclick='submit_runonce();'>Submit</a><a data-role='button' data-theme='a' onclick='reset_runonce();'>Reset</a>";
  760. $progs = array();
  761. if (count($data["programs"])) {
  762. foreach ($data["programs"] as $program) {
  763. $prog = array();
  764. $set_stations = str_split($program["stations"]);
  765. for ($i=0;$i<count($stations);$i++) {
  766. $prog[] = (isset($set_stations[$i]) && $set_stations[$i]) ? $program["duration"] : 0;
  767. }
  768. $progs[] = $prog;
  769. }
  770. }
  771. echo json_encode(array("page"=>$list,"progs"=>$progs));
  772. }
  773. #Make the list of all programs
  774. function make_all_programs() {
  775. $data = get_programs();
  776. $total = count($data["programs"]);
  777. if ($total == 0) {
  778. echo "<p style='text-align:center'>You have no programs currently added. Tap the Add button on the top right corner to get started.</p>";
  779. return;
  780. }
  781. $vs = get_stations();
  782. $stations = $vs["stations"];
  783. $n = 0;
  784. $list = "<p style='text-align:center'>Click any program below to expand/edit. Be sure to save changes by hitting submit below.</p><div data-role='collapsible-set'>";
  785. foreach ($data["programs"] as $program) {
  786. $list .= make_program($n,$total,$stations,$program);
  787. $n++;
  788. }
  789. echo $list."</div>";
  790. }
  791. #Generate a new program view
  792. function fresh_program() {
  793. $vs = get_stations();
  794. $stations = $vs["stations"];
  795. echo make_program("new",1,$stations);
  796. }
  797. function make_program($n,$total,$stations,$program=array("en"=>0,"is_interval"=>0,"is_even"=>0,"is_odd"=>0,"duration"=>0,"interval"=>0,"start"=>0,"end"=>0)) {
  798. $week = array("M", "T", "W", "R", "F", "Sa", "Su");
  799. if (isset($program["days"])) {
  800. if (is_array($program["days"])) {
  801. $days = $program["days"];
  802. } else {
  803. $days = str_split($program["days"]);
  804. }
  805. } else {
  806. $days = array(0,0,0,0,0,0,0);
  807. }
  808. if (isset($program["stations"])) $set_stations = str_split($program["stations"]);
  809. $list = "<fieldset ".((!$n && $total == 1) ? "data-collapsed='false'" : "")." id='program-".$n."' ".(($n === "new") ? "" : "data-role='collapsible'").">";
  810. if ($n !== "new") $list .= "<legend>Program ".($n + 1)."</legend>";
  811. $list .= "<input data-mini='true' type='checkbox' ".(($program["en"] || $n==="new") ? "checked='checked'" : "")." name='en-".$n."' id='en-".$n."'><label for='en-".$n."'>Enabled</label>";
  812. $list .= "<fieldset data-role='controlgroup' data-type='horizontal' style='text-align: center'>";
  813. $list .= "<input data-mini='true' type='radio' name='rad_days-".$n."' id='days_week-".$n."' value='days_week-".$n."' ".(($program["is_interval"]) ? "" : "checked='checked'")."><label for='days_week-".$n."'>Weekly</label>";
  814. $list .= "<input data-mini='true' type='radio' name='rad_days-".$n."' id='days_n-".$n."' value='days_n-".$n."' ".(($program["is_interval"]) ? "checked='checked'" : "")."><label for='days_n-".$n."'>Interval</label>";
  815. $list .= "</fieldset><div id='input_days_week-".$n."' ".(($program["is_interval"]) ? "style='display:none'" : "").">";
  816. $list .= "<fieldset data-role='controlgroup' data-type='horizontal' style='text-align: center'><p style='margin:0'>Restrictions</p>";
  817. $list .= "<input data-mini='true' type='radio' name='rad_rst-".$n."' id='days_norst-".$n."' value='days_norst-".$n."' ".((!$program["is_even"] && !$program["is_odd"]) ? "checked='checked'" : "")."><label for='days_norst-".$n."'>None</label>";
  818. $list .= "<input data-mini='true' type='radio' name='rad_rst-".$n."' id='days_odd-".$n."' value='days_odd-".$n."' ".((!$program["is_even"] && $program["is_odd"]) ? "checked='checked'" : "")."><label for='days_odd-".$n."'>Odd Days</label>";
  819. $list .= "<input data-mini='true' type='radio' name='rad_rst-".$n."' id='days_even-".$n."' value='days_even-".$n."' ".((!$program["is_odd"] && $program["is_even"]) ? "checked='checked'" : "")."><label for='days_even-".$n."'>Even Days</label>";
  820. $list .= "</fieldset>";
  821. $list .= "<fieldset data-type='horizontal' data-role='controlgroup' style='text-align: center'><p style='margin:0'>Days of the Week</p>";
  822. $j = 0;
  823. foreach ($week as $day) {
  824. $list .= "<input data-mini='true' type='checkbox' ".((!$program["is_interval"] && $days[$j]) ? "checked='checked'" : "")." name='d".$j."-".$n."' id='d".$j."-".$n."'><label for='d".$j."-".$n."'>".$day."</label>";
  825. $j++;
  826. }
  827. $list .= "</fieldset></div>";
  828. $list .= "<div ".(($program["is_interval"]) ? "" : "style='display:none'")." id='input_days_n-".$n."' class='ui-grid-a'>";
  829. $list .= "<div class='ui-block-a'><label for='every-".$n."'>Interval (Days)</label><input data-mini='true' type='number' name='every-".$n."' pattern='[0-9]*' id='every-".$n."' value='".$days[0]."'></div>";
  830. $list .= "<div class='ui-block-b'><label for='starting-".$n."'>Starting In</label><input data-mini='true' type='number' name='starting-".$n."' pattern='[0-9]*' id='starting-".$n."' value='".$days[1]."'></div>";
  831. $list .= "</div>";
  832. $list .= "<fieldset data-role='controlgroup'><legend>Stations:</legend>";
  833. $j = 0;
  834. foreach ($stations as $station) {
  835. $list .= "<input data-mini='true' type='checkbox' ".((isset($set_stations) && $set_stations[$j]) ? "checked='checked'" : "")." name='station_".$j."-".$n."' id='station_".$j."-".$n."'><label for='station_".$j."-".$n."'>".$station."</label>";
  836. $j++;
  837. }
  838. $list .= "</fieldset>";
  839. $list .= "<fieldset data-role='controlgroup' data-type='horizontal' style='text-align: center'>";
  840. $list .= "<input data-mini='true' type='reset' name='s_checkall-".$n."' id='s_checkall-".$n."' value='Check All' />";
  841. $list .= "<input data-mini='true' type='reset' name='s_uncheckall-".$n."' id='s_uncheckall-".$n."' value='Uncheck All' />";
  842. $list .= "</fieldset>";
  843. $list .= "<div class='ui-grid-a'>";
  844. $list .= "<div class='ui-block-a'><label for='start-".$n."'>Start Time</label><input data-mini='true' type='time' name='start-".$n."' id='start-".$n."' value='".gmdate("H:i", $program["start"]*60)."'></div>";
  845. $list .= "<div class='ui-block-b'><label for='end-".$n."'>End Time</label><input data-mini='true' type='time' name='end-".$n."' id='end-".$n."' value='".gmdate("H:i", $program["end"]*60)."'></div>";
  846. $list .= "</div>";
  847. $list .= "<label for='duration-".$n."'>Duration (minutes)</label><input data-mini='true' type='number' data-highlight='true' data-type='range' name='duration-".$n."' min='0' max='300' id='duration-".$n."' value='".($program["duration"]/60)."'>";
  848. $list .= "<label for='interval-".$n."'>Interval (minutes)</label><input data-mini='true' type='number' data-highlight='true' data-type='range' name='interval-".$n."' min='0' max='1439' id='interval-".$n."' value='".($program["interval"])."'><br>";
  849. if ($n === "new") {
  850. $list .= "<input data-mini='true' type='submit' name='submit-".$n."' id='submit-".$n."' value='Save New Program'></fieldset>";
  851. } else {
  852. $list .= "<input data-mini='true' type='submit' name='submit-".$n."' id='submit-".$n."' value='Save Changes to Program ".($n + 1)."'>";
  853. $list .= "<input data-mini='true' data-theme='a' type='submit' name='delete-".$n."' id='delete-".$n."' value='Delete Program ".($n + 1)."'></fieldset>";
  854. }
  855. return $list;
  856. }
  857. #Make the manual list
  858. function make_list_manual() {
  859. $list = '<li data-role="list-divider" data-theme="a">Sprinkler Stations</li>';
  860. $vs = get_stations();
  861. $stations = $vs["stations"];
  862. $status = get_station_status();
  863. $i = 0;
  864. foreach ($stations as $station) {
  865. $list .= '<li data-icon="false"><a style="text-align:center" '.(($status[$i]) ? 'class="green" ' : '').'href="#" onclick="toggle(this);">'.$station.'</a></li>';
  866. $i++;
  867. }
  868. echo $list;
  869. }
  870. function current_status() {
  871. $settings = get_settings();
  872. $vs = get_stations();
  873. $stations = $vs["stations"];
  874. $status = get_station_status();
  875. $options = get_options();
  876. if (!$settings["en"]) {
  877. $line = "<p id='running-text' style='text-align:center'>System Disabled</p>";
  878. echo json_encode(array("color" => "red","line" => $line,"seconds" => 0,"sdelay" => $options[17]["val"])); return;
  879. }
  880. if ($settings["rd"]) {
  881. $line = "<p id='running-text' style='text-align:center'>Rain delay until ".gmdate("D, d M Y H:i:s",$settings["rdst"])."</p>";
  882. echo json_encode(array("color" => "red","line" => $line,"seconds" => 0,"sdelay" => $options[17]["val"])); return;
  883. }
  884. if ($settings["urs"] && $settings["rs"]) {
  885. $line = "<p id='running-text' style='text-align:center'>Rain detected</p>";
  886. echo json_encode(array("color" => "red","line" => $line,"seconds" => 0,"sdelay" => $options[17]["val"])); return;
  887. }
  888. $open = array_keys($status,true);
  889. if (count($open) >= 2) {
  890. $ptotal = 0;
  891. foreach ($open as $key => $value) {
  892. $tmp = $settings["ps"][$value][1];
  893. if ($tmp > $ptotal) $ptotal = $tmp;
  894. }
  895. $sample = $open[0];
  896. $pname = pidname($settings["ps"][$sample][0]);
  897. $line = "<img id='running-icon' width='11px' height='11px' src='img/running.png' /><p id='running-text'>";
  898. $line .= $pname." is running on ".count($open)." stations ";
  899. if ($pname != "Manual program") $line .= "<span id='countdown' class='nobr'>(".sec2hms($ptotal)." remaining)</span>";
  900. $line .= "</p>";
  901. echo json_encode(array("color" => "green","line" => $line,"seconds" => $ptotal,"sdelay" => $options[17]["val"]));
  902. return;
  903. }
  904. $i = 0;
  905. foreach ($stations as $station) {
  906. $info = "";
  907. if ($settings["ps"][$i][0] && $status[$i]) {
  908. $pname= pidname($settings["ps"][$i][0]);
  909. $line = "<img id='running-icon' width='11px' height='11px' src='img/running.png' /><p id='running-text'>";
  910. $line .= $pname." is running on station <span class='nobr'>".$station."</span> ";
  911. if ($pname != "Manual program") $line .= "<span id='countdown' class='nobr'>(".sec2hms($settings["ps"][$i][1])." remaining)</span>";
  912. $line .= "</p>";
  913. echo json_encode(array("color" => "green","line" => $line,"seconds" => $settings["ps"][$i][1],"sdelay" => $options[17]["val"]));
  914. return;
  915. }
  916. $i++;
  917. }
  918. if ($settings["mm"]) {
  919. $line = "<p id='running-text' style='text-align:center'>Manual mode enabled</p>";
  920. echo json_encode(array("color" => "red","line" => $line,"seconds" => 0,"sdelay" => $options[17]["val"])); return;
  921. }
  922. }
  923. #Generate status page
  924. function make_list_status() {
  925. $settings = get_settings();
  926. $vs = get_stations();
  927. $stations = $vs["stations"];
  928. $status = get_station_status();
  929. $options = get_options();
  930. $runningTotal = array();
  931. $allPnames = array();
  932. $list = "";$tz = $settings['tz']-48;
  933. $tz = (($tz>=0) ? "+" : "-").(abs($tz)/4>>0).":".((abs($tz)%4)*15/10>>0).((abs($tz)%4)*15%10);
  934. $header = "<span id='clock-s' class='nobr'>".gmdate("D, d M Y H:i:s",$settings["devt"])."</span> GMT ".$tz;
  935. $runningTotal["c"] = $settings["devt"];
  936. $i = 0;
  937. foreach ($stations as $station) {
  938. $info = "";
  939. if ($settings["ps"][$i][0]) {
  940. $rem=$settings["ps"][$i][1];
  941. $remm=$rem/60>>0;
  942. $rems=$rem%60;
  943. $pname= pidname($settings["ps"][$i][0]);
  944. if ($status[$i] && $pname != "Manual program") $runningTotal[$i] = $rem;
  945. $allPnames[$i] = $pname;
  946. $info = "<p class='rem'>".(($status[$i]) ? "Running" : "Scheduled" )." ".$pname;
  947. if ($pname != "Manual program") $info .= " <span id='countdown-".$i."' class='nobr'>(".($remm/10>>0).($remm%10).":".($rems/10>>0).($rems%10)." remaining)</span>";
  948. $info .= "</p>";
  949. }
  950. if ($settings["mas"] == $i+1) $station .= " (Master)";
  951. if ($status[$i]) {
  952. $color = "green";
  953. } else {
  954. $color = "red";
  955. }
  956. $list .= "<li class='".$color."'><p class='sname'>".$station."</p>".$info."</li>";
  957. $i++;
  958. }
  959. $footer = "";
  960. $lrdur = $settings["lrun"][2];
  961. if ($lrdur != 0) {
  962. $lrpid = $settings["lrun"][1];
  963. $pname= pidname($lrpid);
  964. $footer = '<p>'.$pname.' last ran station '.$stations[$settings["lrun"][0]].' for '.($lrdur/60>>0).'m '.($lrdur%60).'s on '.gmdate("D, d M Y H:i:s",$settings["lrun"][3]).'</p>';
  965. }
  966. $open = count(array_keys($status,true));
  967. $ptotal = 0;
  968. foreach ($settings["ps"] as $valve) {
  969. if ($valve[0]) {
  970. if ($open > 1) {
  971. $tmp = $valve[1];
  972. if ($tmp > $ptotal) $ptotal = $tmp;
  973. } else {
  974. $ptotal += $valve[1];
  975. }
  976. }
  977. }
  978. if ($ptotal) {
  979. $scheduled = count($allPnames);
  980. if (!$open && $scheduled) $runningTotal["d"] = $options[17]["val"];
  981. if ($open == 1) $ptotal += ($scheduled-1)*$options[17]["val"];
  982. $allPnames = array_unique($allPnames);
  983. $numProg = count($allPnames);
  984. $allPnames = strrev(preg_replace(strrev("/, /"),strrev(" and "),strrev(implode(", ", $allPnames)),1));
  985. $pinfo = $allPnames.(($numProg > 1) ? " are" : " is" )." running ";
  986. $pinfo .= "<span id='countdown-p' class='nobr'>(".sec2hms($ptotal)." remaining)</span>";
  987. $runningTotal["p"] = $ptotal;
  988. $header .= "<br>".$pinfo;
  989. }
  990. echo json_encode(array("list" => $list,"header" => $header,"footer" => $footer, "sdelay" => $options[17]["val"], "totals" => json_encode($runningTotal)));
  991. }
  992. #Generate settings page
  993. function make_settings_list() {
  994. $options = get_options();
  995. $settings = get_settings();
  996. $vs = get_stations();
  997. $stations = $vs["stations"];
  998. $list = "<li><div data-role='fieldcontain'><fieldset>";
  999. foreach ($options as $key => $data) {
  1000. if (!is_int($key)) continue;
  1001. switch ($key) {
  1002. case 1:
  1003. $timezones = array("-12:00","-11:30","-11:00","-10:00","-09:30","-09:00","-08:30","-08:00","-07:00","-06:00","-05:00","-04:30","-04:00","-03:30","-03:00","-02:30","-02:00","+00:00","+01:00","+02:00","+03:00","+03:30","+04:00","+04:30","+05:00","+05:30","+05:45","+06:00","+06:30","+07:00","+08:00","+08:45","+09:00","+09:30","+10:00","+10:30","+11:00","+11:30","+12:00","+12:45","+13:00","+13:45","+14:00");
  1004. $tz = $data["val"]-48;
  1005. $tz = (($tz>=0) ? "+" : "-").sprintf("%02d", strval(abs($tz)/4)).":".strval(((abs($tz)%4)*15/10).((abs($tz)%4)*15%10));
  1006. $list .= "<label for='o1' class='select'>Timezone</label><select data-mini='true' id='o1'>";
  1007. foreach ($timezones as $timezone) {
  1008. $list .= "<option ".(($timezone == $tz) ? "selected" : "")." value='".$timezone."'>".$timezone."</option>";
  1009. }
  1010. $list .= "</select>";
  1011. continue 2;
  1012. case 12:
  1013. # $http = $options[13]["val"]*256+$data["val"];
  1014. # $list .= "<label for='o12'>HTTP Port</label><input data-mini='true' type='number' pattern='[0-9]*' id='o12' value='".$http."' />";
  1015. continue 2;
  1016. case 15:
  1017. $list .= "<label for='o15'>Extension Boards</label><input data-highlight='true' data-mini='true' type='number' pattern='[0-9]*' data-type='range' min='0' max='5' id='o15' value='".$data["val"]."' />";
  1018. continue 2;
  1019. case 16:
  1020. $list .= "<input data-mini='true' id='o16' type='checkbox' ".(($data["val"] == "1") ? "checked='checked'" : "")." /><label for='o16'>Sequential</label>";
  1021. continue 2;
  1022. case 17:
  1023. $list .= "<label for='o17'>Station Delay (seconds)</label><input data-highlight='true' data-mini='true' type='number' pattern='[0-9]*' data-type='range' min='0' max='240' id='o17' value='".$data["val"]."' />";
  1024. continue 2;
  1025. case 18:
  1026. $list .= "<label for='o18' class='select'>Master Station</label><select data-mini='true' id='o18'><option value='0'>None</option>";
  1027. $i = 1;
  1028. foreach ($stations as $station) {
  1029. $list .= "<option ".(($i == $data["val"]) ? "selected" : "")." value='".$i."'>".$station."</option>";
  1030. if ($i == 8) break;
  1031. $i++;
  1032. }
  1033. $list .= "</select><label for='loc'>Location</label><input data-mini='true' type='text' id='loc' value='".$options["loc"]."' />";
  1034. continue 2;
  1035. case 19:
  1036. $list .= "<label for='o19'>Master On Delay</label><input data-highlight='true' data-mini='true' type='number' pattern='[0-9]*' data-type='range' min='0' max='60' id='o19' value='".$data["val"]."' />";
  1037. continue 2;
  1038. case 20:
  1039. $list .= "<label for='o20'>Master Off Delay</label><input data-highlight='true' data-mini='true' type='number' pattern='[0-9]*' data-type='range' min='-60' max='60' id='o20' value='".$data["val"]."' />";
  1040. continue 2;
  1041. case 21:
  1042. $list .= "<input data-mini='true' id='o21' type='checkbox' ".(($data["val"] == "1") ? "checked='checked'" : "")." /><label for='o21'>Use Rain Sensor</label>";
  1043. continue 2;
  1044. case 22:
  1045. $list .= "<input data-mini='true' id='o22' type='checkbox' ".(($data["val"] == "1") ? "checked='checked'" : "")." /><label for='o22'>Normally Open (Rain Sensor)</label>";
  1046. continue 2;
  1047. case 23:
  1048. $list .= "<label for='o23'>Water Level</label><input data-highlight='true' data-mini='true' type='number' pattern='[0-9]*' data-type='range' min='0' max='250' id='o23' value='".$data["val"]."' />";
  1049. continue 2;
  1050. case 25:
  1051. $list .= "<input data-mini='true' id='o25' type='checkbox' ".(($data["val"] == "1") ? "checked='checked'" : "")." /><label for='o25'>Ignore Password</label>";
  1052. continue 2;
  1053. }
  1054. }
  1055. $list .= "</fieldset></div></li>";
  1056. echo $list;
  1057. }
  1058. function make_stations_list() {
  1059. $settings = get_settings();
  1060. $vs = get_stations();
  1061. $stations = $vs["stations"];
  1062. $masop = $vs["masop"];
  1063. $list = "<li>";
  1064. if ($settings["mas"]) $list .= "<table><tr><th>Station Name</th><th>Activate Master?</th></tr>";
  1065. $i = 0;
  1066. foreach ($stations as $station) {
  1067. if ($settings["mas"]) $list .= "<tr><td>";
  1068. $list .= "<input data-mini='true' id='edit_station_".$i."' type='text' value='".$station."' />";
  1069. if ($settings["mas"]) {
  1070. if ($settings["mas"] == $i+1) {
  1071. $list .= "</td><td class='use_master'><p id='um_".$i."' style='text-align:center'>(Master)</p></td></tr>";
  1072. } else {
  1073. $list .= "</td><td class='use_master'><input id='um_".$i."' type='checkbox' "

Large files files are truncated, but you can click here to view the full file