Yonas Leguesse
Published

Spark-core Smart Air Conditioner

Dumb-To-Smart Air Conditioner

Work in progress7,540
Spark-core Smart Air Conditioner

Things used in this project

Hardware components

Spark Core
Particle Spark Core
×1
IR LED Kit
×1

Story

Read more

Code

file_10144.php

PHP
Part of the PHP code that sends commands to spark core
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);
}

file_10390.txt

C/C++
Spark Core IR Code
// 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.cpp based on:https://github.com/mharizanov/Daikin-AC-remote-control-over-the-Internetwhich is an Arduino IR library for the Daikin IR protocol. This library is based on:https://github.com/shirriff/Arduino-IRremoteWhich is a generic Arduino IR library.
/*
 * 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);
}

file_10392.txt

C/C++
IRremote.h
/*
 * 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

file_12241.php

PHP
scheduler.php
<?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);
}
?>

Credits

Yonas Leguesse

Yonas Leguesse

5 projects • 44 followers

Comments