Hardware components | ||||||
| × | 1 | ||||
| × | 1 |
This project uses a simple IR Transmitter (in this case I used a Max Power LED kit to extend the range but any IR LED would do) connected to a spark-core, to send IR commands to the Air conditioning unit over the internet.
The project includes:
- A client (Mobile, Web-browser, etc...)
- A web server (in this case Apache - PHP)
- Spark Core
- IR LED
- AC
The web server hosts a simple User Interface that displays typical AC options. Namely: Temperature, Mode, and Fan Speed. The user can then choose whether to send the command immediately, or to schedule a command (I use this to turn on the AC for a few minutes before I wake up, and similarly for a few minutes before i go to bed :) ).
The scheduling was implemented using cron jobs on the hosting server.
The spark core acts as an IP-2-IR bridge:
The commands passed from the client to the web server are forwarded to the Spark core, which in turn forwards the commands to the Air conditioning unit.
I will be uploading more information on the project soon :)
function setAC($tempFanMode){
$authKey =getAuthKey();
$devID = getDeviceID("ir2");
$url = "https://api.spark.io/v1/devices/" . $devID . "/daikin" ;
$fields_string = "";
$fields = array(
'access_token' => urlencode($authKey),
'args' => urlencode($tempFanMode)
);
foreach($fields as $key=>$value) { $fields_string .= $key.'='.$value.'&'; }
rtrim($fields_string, '&');
$ch = curl_init ( );
curl_setopt($ch,CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch,CURLOPT_POST, count($fields));
curl_setopt($ch,CURLOPT_POSTFIELDS, $fields_string);
$response1 = curl_exec ( $ch );
curl_close($ch);
}
// This #include statement was automatically added by the Spark IDE.
#include "IRremote.h"
int commadDevice(String args);
const int COMMAND_LENGTH = 27;
unsigned char daikin[COMMAND_LENGTH] = {
0x11,0xDA,0x27,0xF0,0x00,0x00,0x00,0x20,
//0 1 2 3 4 5 6 7
0x11,0xDA,0x27,0x00,0x00,0x41,0x1E,0x00,
//8 9 10 11 12 13 14 15
0xB0,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x00,0x00,0xE3 };
//16 17 18 19 20 21 22 23 24 25 26
/*
byte 13=mode
b7 = 0
b6+b5+b4 = Mode
b3 = 0
b2 = OFF timer set
b1 = ON timer set
b0 = Air Conditioner ON
Modes: b6+b5+b4
011 = Cool
100 = Heat (temp 23)
110 = FAN (temp not shown, but 25)
000 = Fully Automatic (temp 25)
010 = DRY (temp 0xc0 = 96 degrees c)
byte 14=temp*2
byte 16=Fan
FAN control
b7+b6+b5+b4 = Fan speed
b3+b2+b1+b0 = Swing control up/down
Fan: b7+b6+b5+b4
030 = 1 bar - 48
040 = 2 bar - 64
050 = 3 bar - 80
060 = 4 bar - 96
070 = 5 bar - 112
0xa0 = Auto - 160
0xb0 = Not auto, moon + tree - 176
Swing control up/down:
0000 = Swing up/down off
1111 = Swing up/down on
Swing control left/right:
0000 = Swing left/right off
1111 = Swing left/right on
*/
IRsend irsend(D3); // hardwired to pin 3; use a transistor to drive the IR LED for maximal range
#define IRSTATE_EEPROM_ADDR ((byte*) 0x100)
int incomingByte;
struct IRState {
byte mode;
byte temp;
byte fan;
byte aux;
byte state;
byte enabled;
byte sched;
byte hour;
byte minutes;
long lastused;
} irstate;
void setup()
{
pinMode(D7, OUTPUT);
Spark.function("daikin", commadDevice);
}
int commadDevice(String args)
{
/*int rawSize = sizeof(rawCodes)/sizeof(int); // In this example, rawSize would evaluate to 37
irsend.sendRaw(rawCodes, rawSize, 38);
return 1;
*/
/*
Fan: b7+b6+b5+b4
030 = 1 bar - 48
040 = 2 bar - 64
050 = 3 bar - 80
060 = 4 bar - 96
070 = 5 bar - 112
0xa0 = 0 Auto - 160*/
/*
Modes: b6+b5+b4
0 ------000 = Fully Automatic (temp 25)
2 ------ 010 = DRY (temp 0xc0 = 96 degrees c)
3 ------011 = Cool
4 ------100 = Heat (temp 23)
5 ------110 = FAN (temp not shown, but 25)
args = temp-fan-mode
*/
if(args=="off"){
airController_off();
irstate.aux=airController_getAux();
irstate.temp=airConroller_getTemp();
irstate.fan= airConroller_getFan();
irstate.mode=airConroller_getMode();
irsend.sendDaikin(daikin, 8,0);
delay(29);
irsend.sendDaikin(daikin, 19,8);
digitalWrite(D7, LOW);
}
else{
digitalWrite(D7, HIGH);
String temps = getValue(args, '-', 0);
String fans = getValue(args, '-', 1);
String modes = getValue(args, '-', 2);
int temp = temps.toInt();
int fan = 0;
int fanc = fans.toInt();
int mode = modes.toInt();
switch (fanc) {
case 1:
fan = 48;
break;
case 2:
fan = 64;
break;
case 3:
fan = 80;
break;
case 4:
fan = 96;
break;
case 5:
fan = 112;
break;
case 0:
fan = 160;
break;
default:;
break;
}
airController_on ();
airController_setTemp (temp);
airController_setFan (fan);
airController_setMode (mode);
airController_checksum ();
irsend.sendDaikin (daikin, 8,0);
delay (29);
irsend.sendDaikin (daikin, 19,8);
}
}
String getValue(String data, char separator, int index)
{
int found = 0;
int strIndex[] = {
0, -1 };
int maxIndex = data.length()-1;
for(int i=0; i<=maxIndex && found<=index; i++){
if(data.charAt(i)==separator || i==maxIndex){
found++;
strIndex[0] = strIndex[1]+1;
strIndex[1] = (i == maxIndex) ? i+1 : i;
}
}
return found>index ? data.substring(strIndex[0], strIndex[1]) : "";
}
uint8_t airController_checksum()
{
uint8_t sum = 0;
uint8_t i;
for(i = 0; i <= 6; i++){
sum += daikin[i];
}
daikin[7] = sum &0xFF;
sum=0;
for(i = 8; i <= 25; i++){
sum += daikin[i];
}
daikin[26] = sum &0xFF;
}
void airController_on(){
//state = ON;
daikin[13] |= 0x01;
airController_checksum();
}
void airController_off(){
//state = OFF;
daikin[13] &= 0xFE;
airController_checksum();
}
void airController_setAux(uint8_t aux){
daikin[21] = aux;
airController_checksum();
}
uint8_t airController_getAux(){
return daikin[21];
}
void airController_setTemp(uint8_t temp)
{
daikin[14] = (temp)*2;
airController_checksum();
}
void airController_setFan(uint8_t fan)
{
daikin[16] = fan;
airController_checksum();
}
uint8_t airConroller_getTemp()
{
return (daikin[14])/2;
}
uint8_t airConroller_getMode()
{
/*
Modes: b6+b5+b4
3 ------011 = Cool
4 ------100 = Heat (temp 23)
5 ------110 = FAN (temp not shown, but 25)
0 ------000 = Fully Automatic (temp 25)
2 ------ 010 = DRY (temp 0xc0 = 96 degrees c)
*/
return (daikin[13])>>4;
}
void airController_setMode(uint8_t mode)
{
daikin[13]=mode<<4 | airConroller_getState();
airController_checksum();
}
uint8_t airConroller_getState()
{
return (daikin[13])&0x01;
}
uint8_t airConroller_getFan()
{
return (daikin[16]);
}
void restartac () {
if(airConroller_getState()==1) {
airController_off();
irstate.aux=airController_getAux();
irstate.temp=airConroller_getTemp();
irstate.fan= airConroller_getFan();
irstate.mode=airConroller_getMode();
irsend.sendDaikin(daikin, 8,0);
delay(29);
irsend.sendDaikin(daikin, 19,8);
delay (10000);
airController_on();
airController_setAux(0);
airController_setTemp(irstate.temp);
airController_setFan(irstate.fan);
airController_setMode(irstate.mode);
irsend.sendDaikin(daikin, 8,0);
delay(29);
irsend.sendDaikin(daikin, 19,8);
}
}
file_10391.txt
C/C++/*
* IRremote
* Version 0.11 August, 2009
* Copyright 2009 Ken Shirriff
* For details, see http://arcfn.com/2009/08/multi-protocol-infrared-remote-library.html
*
* Modified by Paul Stoffregen <paul@pjrc.com> to support other boards and timers
* Modified by Mitra Ardron <mitra@mitra.biz>
* Added Sanyo and Mitsubishi controllers
* Modified Sony to spot the repeat codes that some Sony's send
* Modified by Gaspard van Koningsveld to trim out IRrecv, not using PWM anymore, allow setting of IR LED pin, and make it compatible with the Spark Core v1.0 (STM32F103CB based)
*
* Interrupt code based on NECIRrcv by Joe Knapp
* http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1210243556
* Also influenced by http://zovirl.com/2008/11/12/building-a-universal-remote-with-an-arduino/
*
* JVC and Panasonic protocol added by Kristian Lauszus (Thanks to zenwheel and other people at the original blog post)
*/
#include "IRremote.h"
#include "application.h"
IRsend::IRsend(int irPin) : irPin(irPin) {};
void IRsend::sendNEC(unsigned long data, int nbits)
{
enableIROut(38);
mark(NEC_HDR_MARK);
space(NEC_HDR_SPACE);
for (int i = 0; i < nbits; i++) {
if (data & TOPBIT) {
mark(NEC_BIT_MARK);
space(NEC_ONE_SPACE);
}
else {
mark(NEC_BIT_MARK);
space(NEC_ZERO_SPACE);
}
data <<= 1;
}
mark(NEC_BIT_MARK);
space(0);
}
void IRsend::sendSony(unsigned long data, int nbits) {
enableIROut(40);
mark(SONY_HDR_MARK);
space(SONY_HDR_SPACE);
data = data << (32 - nbits);
for (int i = 0; i < nbits; i++) {
if (data & TOPBIT) {
mark(SONY_ONE_MARK);
space(SONY_HDR_SPACE);
}
else {
mark(SONY_ZERO_MARK);
space(SONY_HDR_SPACE);
}
data <<= 1;
}
}
void IRsend::sendDaikin(unsigned char buf[], int len, int start) {
int data2;
enableIROut(38);
mark(DAIKIN_HDR_MARK);
space(DAIKIN_HDR_SPACE);
for (int i = start; i < start+len; i++) {
data2=buf[i];
for (int j = 0; j < 8; j++) {
if ((1 << j & data2)) {
mark(DAIKIN_ONE_MARK);
space(DAIKIN_ONE_SPACE);
}
else {
mark(DAIKIN_ZERO_MARK);
space(DAIKIN_ZERO_SPACE);
}
}
}
mark(DAIKIN_ONE_MARK);
space(DAIKIN_ZERO_SPACE);
}
void IRsend::sendRaw(unsigned int buf[], int len, int hz)
{
enableIROut(hz);
for (int i = 0; i < len; i++) {
if (i & 1) {
space(buf[i]);
}
else {
mark(buf[i]);
}
}
space(0); // Just to be sure
}
// Note: first bit must be a one (start bit)
void IRsend::sendRC5(unsigned long data, int nbits)
{
enableIROut(36);
data = data << (32 - nbits);
mark(RC5_T1); // First start bit
space(RC5_T1); // Second start bit
mark(RC5_T1); // Second start bit
for (int i = 0; i < nbits; i++) {
if (data & TOPBIT) {
space(RC5_T1); // 1 is space, then mark
mark(RC5_T1);
}
else {
mark(RC5_T1);
space(RC5_T1);
}
data <<= 1;
}
space(0); // Turn off at end
}
// Caller needs to take care of flipping the toggle bit
void IRsend::sendRC6(unsigned long data, int nbits)
{
enableIROut(36);
data = data << (32 - nbits);
mark(RC6_HDR_MARK);
space(RC6_HDR_SPACE);
mark(RC6_T1); // start bit
space(RC6_T1);
int t;
for (int i = 0; i < nbits; i++) {
if (i == 3) {
// double-wide trailer bit
t = 2 * RC6_T1;
}
else {
t = RC6_T1;
}
if (data & TOPBIT) {
mark(t);
space(t);
}
else {
space(t);
mark(t);
}
data <<= 1;
}
space(0); // Turn off at end
}
/* Sharp and DISH support by Todd Treece ( http://unionbridge.org/design/ircommand )
The Dish send function needs to be repeated 4 times, and the Sharp function
has the necessary repeat built in because of the need to invert the signal.
Sharp protocol documentation:
http://www.sbprojects.com/knowledge/ir/sharp.htm
Here are the LIRC files that I found that seem to match the remote codes
from the oscilloscope:
Sharp LCD TV:
http://lirc.sourceforge.net/remotes/sharp/GA538WJSA
DISH NETWORK (echostar 301):
http://lirc.sourceforge.net/remotes/echostar/301_501_3100_5100_58xx_59xx
For the DISH codes, only send the last for characters of the hex.
i.e. use 0x1C10 instead of 0x0000000000001C10 which is listed in the
linked LIRC file.
*/
void IRsend::sendSharp(unsigned long data, int nbits) {
unsigned long invertdata = data ^ SHARP_TOGGLE_MASK;
enableIROut(38);
for (int i = 0; i < nbits; i++) {
if (data & 0x4000) {
mark(SHARP_BIT_MARK);
space(SHARP_ONE_SPACE);
}
else {
mark(SHARP_BIT_MARK);
space(SHARP_ZERO_SPACE);
}
data <<= 1;
}
mark(SHARP_BIT_MARK);
space(SHARP_ZERO_SPACE);
delay(46);
for (int i = 0; i < nbits; i++) {
if (invertdata & 0x4000) {
mark(SHARP_BIT_MARK);
space(SHARP_ONE_SPACE);
}
else {
mark(SHARP_BIT_MARK);
space(SHARP_ZERO_SPACE);
}
invertdata <<= 1;
}
mark(SHARP_BIT_MARK);
space(SHARP_ZERO_SPACE);
delay(46);
}
void IRsend::sendDISH(unsigned long data, int nbits)
{
enableIROut(56);
mark(DISH_HDR_MARK);
space(DISH_HDR_SPACE);
for (int i = 0; i < nbits; i++) {
if (data & DISH_TOP_BIT) {
mark(DISH_BIT_MARK);
space(DISH_ONE_SPACE);
}
else {
mark(DISH_BIT_MARK);
space(DISH_ZERO_SPACE);
}
data <<= 1;
}
}
void IRsend::sendPanasonic(unsigned int address, unsigned long data) {
enableIROut(35);
mark(PANASONIC_HDR_MARK);
space(PANASONIC_HDR_SPACE);
for(int i=0;i<16;i++)
{
mark(PANASONIC_BIT_MARK);
if (address & 0x8000) {
space(PANASONIC_ONE_SPACE);
} else {
space(PANASONIC_ZERO_SPACE);
}
address <<= 1;
}
for (int i=0; i < 32; i++) {
mark(PANASONIC_BIT_MARK);
if (data & TOPBIT) {
space(PANASONIC_ONE_SPACE);
} else {
space(PANASONIC_ZERO_SPACE);
}
data <<= 1;
}
mark(PANASONIC_BIT_MARK);
space(0);
}
void IRsend::sendJVC(unsigned long data, int nbits, int repeat)
{
enableIROut(38);
data = data << (32 - nbits);
if (!repeat){
mark(JVC_HDR_MARK);
space(JVC_HDR_SPACE);
}
for (int i = 0; i < nbits; i++) {
if (data & TOPBIT) {
mark(JVC_BIT_MARK);
space(JVC_ONE_SPACE);
}
else {
mark(JVC_BIT_MARK);
space(JVC_ZERO_SPACE);
}
data <<= 1;
}
mark(JVC_BIT_MARK);
space(0);
}
void IRsend::mark(int time) {
// Sends an IR mark (frequency burst output) for the specified number of microseconds.
noInterrupts();
while (time > 0) {
digitalWrite(irPin, HIGH); // this takes about 3 microseconds to happen
delayMicroseconds(burstWait);
digitalWrite(irPin, LOW); // this also takes about 3 microseconds
delayMicroseconds(burstWait);
time -= burstLength;
}
interrupts();
}
void IRsend::space(int time) {
// Sends an IR space (no output) for the specified number of microseconds.
digitalWrite(irPin, LOW); // Takes about 3 microsecondes
if (time > 3) {
delayMicroseconds(time - 3);
}
}
void IRsend::enableIROut(int khz) {
// Enables IR output. The khz value controls the modulation frequency in kilohertz.
// MAX frequency is 166khz.
pinMode(irPin, OUTPUT);
digitalWrite(irPin, LOW);
// This is the time to wait with the IR LED on and off to make the frequency, in microseconds.
// The - 3.0 at the end is because digitalWrite() takes about 3 microseconds. Info from:
// https://github.com/eflynch/sparkcoreiremitter/blob/master/ir_emitter/ir_emitter.ino
burstWait = round(1.0 / khz * 1000.0 / 2.0 - 3.0);
// This is the total time of a period, in microseconds.
burstLength = round(1.0 / khz * 1000.0);
}
/*
* IRremote
* Version 0.1 July, 2009
* Copyright 2009 Ken Shirriff
* For details, see http://arcfn.com/2009/08/multi-protocol-infrared-remote-library.htm http://arcfn.com
* Edited by Mitra to add new controller SANYO
*
* Interrupt code based on NECIRrcv by Joe Knapp
* http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1210243556
* Also influenced by http://zovirl.com/2008/11/12/building-a-universal-remote-with-an-arduino/
*
* JVC and Panasonic protocol added by Kristian Lauszus (Thanks to zenwheel and other people at the original blog post)
*/
#ifndef IRremote_h
#define IRremote_h
class IRsend
{
const int irPin;
int burstWait;
int burstLength;
public:
IRsend(int irPin);
void sendNEC(unsigned long data, int nbits);
void sendSony(unsigned long data, int nbits);
// Neither Sanyo nor Mitsubishi send is implemented yet
// void sendSanyo(unsigned long data, int nbits);
// void sendMitsubishi(unsigned long data, int nbits);
void sendDaikin(unsigned char buf[], int len,int start);
void sendRaw(unsigned int buf[], int len, int hz);
void sendRC5(unsigned long data, int nbits);
void sendRC6(unsigned long data, int nbits);
void sendSharp(unsigned long data, int nbits);
void sendDISH(unsigned long data, int nbits);
void sendPanasonic(unsigned int address, unsigned long data);
void sendJVC(unsigned long data, int nbits, int repeat); // *Note instead of sending the REPEAT constant if you want the JVC repeat signal sent, send the original code value and change the repeat argument from 0 to 1. JVC protocol repeats by skipping the header NOT by sending a separate code value like NEC does.
private:
void enableIROut(int khz);
void mark(int usec);
void space(int usec);
}
;
#define DAIKIN_HDR_MARK 3650 //DAIKIN_ZERO_MARK*8
#define DAIKIN_HDR_SPACE 1623 //DAIKIN_ZERO_MARK*4
#define DAIKIN_ONE_SPACE 1280
#define DAIKIN_ONE_MARK 428
#define DAIKIN_ZERO_MARK 428
#define DAIKIN_ZERO_SPACE 428
// Constants for sending IR codes
#define NEC_HDR_MARK 9000
#define NEC_HDR_SPACE 4500
#define NEC_BIT_MARK 560
#define NEC_ONE_SPACE 1600
#define NEC_ZERO_SPACE 560
#define NEC_RPT_SPACE 2250
#define SONY_HDR_MARK 2400
#define SONY_HDR_SPACE 600
#define SONY_ONE_MARK 1200
#define SONY_ZERO_MARK 600
#define SONY_RPT_LENGTH 45000
#define SONY_DOUBLE_SPACE_USECS 500 // usually ssee 713 - not using ticks as get number wrapround
// SA 8650B
#define SANYO_HDR_MARK 3500 // seen range 3500
#define SANYO_HDR_SPACE 950 // seen 950
#define SANYO_ONE_MARK 2400 // seen 2400
#define SANYO_ZERO_MARK 700 // seen 700
#define SANYO_DOUBLE_SPACE_USECS 800 // usually ssee 713 - not using ticks as get number wrapround
#define SANYO_RPT_LENGTH 45000
// Mitsubishi RM 75501
// 14200 7 41 7 42 7 42 7 17 7 17 7 18 7 41 7 18 7 17 7 17 7 18 7 41 8 17 7 17 7 18 7 17 7
// #define MITSUBISHI_HDR_MARK 250 // seen range 3500
#define MITSUBISHI_HDR_SPACE 350 // 7*50+100
#define MITSUBISHI_ONE_MARK 1950 // 41*50-100
#define MITSUBISHI_ZERO_MARK 750 // 17*50-100
// #define MITSUBISHI_DOUBLE_SPACE_USECS 800 // usually ssee 713 - not using ticks as get number wrapround
// #define MITSUBISHI_RPT_LENGTH 45000
#define RC5_T1 889
#define RC5_RPT_LENGTH 46000
#define RC6_HDR_MARK 2666
#define RC6_HDR_SPACE 889
#define RC6_T1 444
#define RC6_RPT_LENGTH 46000
#define SHARP_BIT_MARK 245
#define SHARP_ONE_SPACE 1805
#define SHARP_ZERO_SPACE 795
#define SHARP_GAP 600000
#define SHARP_TOGGLE_MASK 0x3FF
#define SHARP_RPT_SPACE 3000
#define DISH_HDR_MARK 400
#define DISH_HDR_SPACE 6100
#define DISH_BIT_MARK 400
#define DISH_ONE_SPACE 1700
#define DISH_ZERO_SPACE 2800
#define DISH_RPT_SPACE 6200
#define DISH_TOP_BIT 0x8000
#define PANASONIC_HDR_MARK 3502
#define PANASONIC_HDR_SPACE 1750
#define PANASONIC_BIT_MARK 502
#define PANASONIC_ONE_SPACE 1244
#define PANASONIC_ZERO_SPACE 400
#define JVC_HDR_MARK 8000
#define JVC_HDR_SPACE 4000
#define JVC_BIT_MARK 600
#define JVC_ONE_SPACE 1600
#define JVC_ZERO_SPACE 550
#define JVC_RPT_LENGTH 60000
#define SHARP_BITS 15
#define DAIKIN_BITS 99
#define DISH_BITS 16
#define TOPBIT 0x80000000
#endif
<?php require_once('CronClass.php');
if (isset($_POST["cronSchedString"]) && isset($_POST["tempFanMode"])) {
$allcronjobs = getAllCronJobs();
$newcron = new CronClass('ac', $_POST["cronSchedString"], ["tempFanMode" => $_POST["tempFanMode"],]);
array_push($allcronjobs, $newcron);
writeToCronTab($allcronjobs);
echo showCronJobs($allcronjobs);
}
if (isset($_POST["getCrons"]) ) {
$allcronjobs = getAllCronJobs();
echo showCronJobs($allcronjobs);
}
if (isset($_POST["removeId"]) ) {
$allcronjobs = getAllCronJobs();
array_splice($allcronjobs,$_POST["removeId"],1);
writeToCronTab($allcronjobs);
$allcronjobs = getAllCronJobs();
echo showCronJobs($allcronjobs);
}
if (isset($_POST["modId"]) && isset($_POST["modcronSchedString"]) && isset($_POST["modtempFanMode"])) {
$allcronjobs = getAllCronJobs();
$modcron = new CronClass('ac', $_POST["modcronSchedString"], ["tempFanMode" => $_POST["modtempFanMode"],]);
unset($allcronjobs[$_POST["modId"]]);
$allcronjobs[$_POST["modId"]] = $modcron;
writeToCronTab($allcronjobs);
$allcronjobs = getAllCronJobs();
echo showCronJobs($allcronjobs);
}
function writeToCronTab($cronjobs){
$cronstring = '';
foreach ($cronjobs as $cron) {
if($cronstring != ''){
$cronstring = $cronstring .PHP_EOL;
}
$cronstring = $cronstring .$cron->getCronString() ;
}
$cronstring = $cronstring .PHP_EOL;
file_put_contents('/tmp/crontab.txt', $cronstring);
echo exec('crontab /tmp/crontab.txt');
}
function showCronJobs($cronjobs){
$json = array();
foreach ($cronjobs as $cronjob) {
$bus = array(
'script' => $cronjob->getPhpScript(),
'cron' => $cronjob->getCronSched(),
'tempfanmode' => $cronjob->getKeyValue("tempFanMode")
);
array_push($json, $bus);
}
$jsonstring = json_encode($json);
return $jsonstring;
}
function getAllCronJobs(){
$cronjobarr = array();
$output = shell_exec('crontab -l');
$cronjobs = explode("\n", $output);
foreach ($cronjobs as $cronjob) {
if(strlen($cronjob)>0){
$obj = getCronFromString($cronjob);
array_push($cronjobarr, $obj);
}
}
return $cronjobarr;
}
function getCronFromString($cronstring) {
$phpscript = get_string_between($cronstring, "/php/", ".php");
$cronschedule = substr($cronstring,0,strpos($cronstring, " /usr/", 1));
$vars = substr(strrchr($cronstring, "?"), 1);
$params = explode("&", $vars);
$kva = array();
foreach ($params as $param) {
$keyval = explode("=", $param);
$key = $keyval[0];
$val = $keyval[1];
$kva[$key] = $val;
}
return $rescron = new CronClass($phpscript, $cronschedule, $kva);
}
function get_string_between($string, $start, $end){
$string = " ".$string;
$ini = strpos($string,$start);
if ($ini == 0) return "";
$ini += strlen($start);
$len = strpos($string,$end,$ini) - $ini;
return substr($string,$ini,$len);
}
?>
Comments