Notice: This forum has been recovered from an old backup, so some content, links, and dates may be outdated. The forum is currently read-only while we restore sign-in and registration functionality. Details

If you find this forum valuable and would like to help keep it online, donations to help cover hosting and domain costs are greatly appreciated, but never expected. You can support the forum through Buy Me a Coffee or Ko-fi. Thank you for helping preserve the EventGhost community.

Qivivo thermostat with PHP Plug in

If you have a question or need help, this is the place to be.
Post Reply
azertyuiop
Posts: 4
Joined: Sat Jan 21, 2012 9:38 pm

Qivivo thermostat with PHP Plug in

Post by azertyuiop »

Good day,

I have a Qivivo thermostat that drives my home heating device and I would like to connect it with EventGhost.
Someone wrote a PHP plugin to access Qivivo thermostat data : https://github.com/WoodySlum/QivivoBridge.
Is it possible to 'load' this plugin into EG and then use it ? and if yes, how ?
It may also be possible to re-write this plugin in Python but it seems way beyond my programming skills for the time beeing...

Thanks in advance for any advice you may have,

Olivier
azertyuiop
Posts: 4
Joined: Sat Jan 21, 2012 9:38 pm

Re: Qivivo thermostat with PHP Plug in

Post by azertyuiop »

Well, I finalelly get what I wanted even if it's not the nicest way to do it I guess...

I installed XAMPP and ran the Apache server on a different port than the EventGhost webserver.

I created GetThermostatStatus.php file in the C:\xampp\htdocs directory, based on code of here above link (copy/paste I'd rather say).

Code: Select all

<?php
class Qivivo {
	private $qivivoLogin = "[email protected]";
	private $qivivoPassword = "my_password";
	private $credentials = NULL;
	private $thermostatStatus = NULL;
	private $urlGetLogin = "http://www.qivivo.com/login";
	private $urlLogin = "http://www.qivivo.com/login_check";
	private $urlThermostatStatus = "http://www.qivivo.com/myQivivo/updateRealTime";
	private $urlThermostatSetTemperature = "http://www.qivivo.com/myQivivo/temps-reel/setTemperature";
	private $urlAccount = "http://www.qivivo.com/mon-compte/mes-produits";
	private $dailyUsage = "http://www.qivivo.com/myQivivo/synthese/day";
	private $singlePageAuth = false;
	private $enableLog = false;
	
	function __construct($login, $password) {
		$this->qivivoLogin = $login;
		$this->qivivoPassword = $password;
		if ($this->qivivoLogin == "") {
			$this->error(703, "No username param");
		}
		if ($this->qivivoPassword == "") {
			$this->error(704, "No password param");
		}
	}
	function __destruct() {
		
	}
	private function error($code, $message) {
		die("[".$code."] ".$message.PHP_EOL);
	}
	private function log($log, $level) {
		if ($level < 5 && $this->enableLog) {
			echo $log.PHP_EOL;
		}
	}
	function getAccountInfo() {
		$this->connect();
		$ch = curl_init($this->urlAccount);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
		curl_setopt($ch,CURLOPT_POSTFIELDS, $fields_string);
		curl_setopt($ch, CURLOPT_HTTPHEADER, array("Cookie: ".$this->buildCookie(), "Host: www.qivivo.com"));
		curl_setopt($ch, CURLOPT_REFERER, "http://www.qivivo.com/myQivivo/");
		$result = curl_exec($ch);
		
		preg_match_all("/(<li>Niveau des piles : )(.*)(%<\/li>)/m", $result, $battery);
		
		$infos = new StdClass();
		if (count($battery) == 4) {
			if ($battery[2][0] != "") {
				$infos->battery = intval($battery[2][0]);
			}
		}
		preg_match_all("/(<li>Num├®ro de s├®rie : )(.*)(<\/li>)/m", $result, $serial);
		
		if (count($serial) == 4) {
			$infos->serial = $serial[2][0];
		}
		preg_match_all("/(<li>Version Firmware : )(.*)(<\/li>)/m", $result, $firmware);
		
		if (count($firmware) == 4) {
			$infos->firmware = $firmware[2][0];
		}
		preg_match_all("/(<li>Dernière transmission : )(.*)(<\/li>)/m", $result, $lastTransmission);
		
		if (count($lastTransmission) == 4) {
			$infos->lastTransmission = $lastTransmission[2][0];
		}
		return $infos;
		
	}
	private function connect() {
		if ($this->credentials == NULL) {
			$this->getCredentials();
		}
		if ($this->thermostatStatus == NULL) {
			$this->getThermostatInfo();
		}
	}
	private function getCredentials() {
		
		$this->log("Getting credentials", 4);
		$bCookie = "qivivo=abc";
		if (!$this->singlePageAuth) {
			$ch = curl_init($this->urlGetLogin);
			curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
			curl_setopt($ch, CURLOPT_HEADER, 1);
			$result = curl_exec($ch);
			preg_match_all('/^Set-Cookie:\s*([^;]*)/mi', $result, $baseCookie);
			$bCookie = "";
			if (count($baseCookie) > 1) {
				for ($i = 1 ; $i < count($baseCookie) ; $i++) {
					$bCookie .= $baseCookie[$i][0].";";
				}
			}
			$bCookie = rtrim($bCookie, ";");
		}
		
		// Retrieve csrf token
		preg_match_all("/( name=\"_csrf_token\" value=\")(.*)(\")/m", $result, $csrfData);
		if (count($csrfData) == 4) {
			if ($csrfData[2][0] != "") {
				$csrf = $csrfData[2][0];
			}
		}
		$this->log("Qivivo csrf token : ".$csrf, 3);
		$ch = curl_init($this->urlLogin);
		$fields = array(
			'_csrf_token' => urlencode($csrf),
			'_username' => urlencode($this->qivivoLogin),
			'_password' => urlencode($this->qivivoPassword)
		);
		$fields_string = "";
		foreach($fields as $key=>$value) { $fields_string .= $key.'='.$value.'&'; }
		$fields_string = rtrim($fields_string, '&');
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
		// curl_setopt($ch,CURLOPT_USERAGENT,'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.13) Gecko/20080311 Firefox/2.0.0.13');
		curl_setopt($ch,CURLOPT_HTTPHEADER,array('Origin: http://www.qivivo.com', 
			'Referer: http://www.qivivo.com/login', 
			'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 
			'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.86 Safari/537.36', 
			'Upgrade-Insecure-Requests: 1',
			'Accept-Encoding: gzip, deflate',
			'Accept-Language: fr,en-US;q=0.8,en;q=0.6,fr-FR;q=0.4',
			'Cookie: '.$bCookie
		));
		//'Cookie: compatEnergy=gaz; compatTHMarque=delta-dore; cookieCompatibility=true; __utma=; __utmc=; __utmz=utmccn=utmcmd=referral|utmcct=/; _gat=1; PHPSESSID=; PRUM_EPISODES=s=&r=http%3A//www.qivivo.com/login'
		$this->log(str_replace(">", "]", str_replace("<", "[", @$result)), 5);
		// get headers too with this line
		curl_setopt($ch, CURLOPT_HEADER, 1);
		curl_setopt($ch,CURLOPT_POST, count($fields));
		curl_setopt($ch,CURLOPT_POSTFIELDS, $fields_string);
		$result = curl_exec($ch);
		// get cookie
		// multi-cookie variant contributed by @Combuster in comments
		preg_match_all('/^Set-Cookie:\s*([^;]*)/mi', $result, $matches);
		// var_dump($result);die;
		$this->credentials = array();
		foreach($matches[1] as $item) {
		    parse_str($item, $cookie);
		    $this->credentials = array_merge($this->credentials, $cookie);
		}
		$this->log("Credentials retrieved : ".implode(" / ", $this->credentials), 5);
		if (count($this->credentials) == 0) {
			$this->error(701, "Could not load credentials", false);
		}
		$this->log(str_replace(">", "]", str_replace("<", "[", $result)), 5);
	}
	private function buildCookie() {
		$ret = "";
		foreach ($this->credentials as $key => $value) {
			$ret .= $key."=".$value.";";
		}
		$ret = rtrim($ret, ";");
		return $ret;
	}
	private function getThermostatInfo() {
		$this->log("Retrieve thermostat info", 4);
		$ch = curl_init($this->urlThermostatStatus);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
		curl_setopt($ch, CURLOPT_HTTPHEADER, array("Cookie: ".$this->buildCookie()));
		$result = curl_exec($ch);
		
		if (!$result) {
			$this->error(702, "Could not retrieve thermostat data");
		}
		$this->log(str_replace(">", "]", str_replace("<", "[", $result)), 4);
		$this->thermostatStatus = json_decode($result);
	}
	function getInsideTemperature() {
		$this->connect();
		$this->log("Retrieve thermostat inside value : ".@$this->thermostatStatus->getData->temperatureIn, 4);
		return @$this->thermostatStatus->getData->temperatureIn;
	}
	function getOutsideTemperature() {
		$this->connect();
		$this->log("Retrieve thermostat outside value : ".@$this->thermostatStatus->getData->temperatureOut, 4);
		return @$this->thermostatStatus->getData->temperatureOut;
	}
	function getRequestedTemperature() {
		$this->connect();
		$this->log("Retrieve thermostat requested value : ".@$this->thermostatStatus->getData->tcons, 4);
		return @$this->thermostatStatus->getData->tcons;
	}
	function getThermostatStatus() {
		$this->connect();
		$this->log("Thermostat status : ".@$this->thermostatStatus->getData->getAllData->heating_status, 4);
		return $this->thermostatStatus->getData->getAllData->heating_status;
	}
	function setTemperature($value) {
		$this->connect();
		$this->log("Trying to set temperature : ".$value, 1);
		$value = str_replace(",", ".", $value);
		if (!is_numeric($value)) {
			$this->error(705, "Param error in set temperature");
		}
		$this->log("Set temperature : ".$value, 1);
		$fields = array(
			't_ideal' => urlencode($value)
		);
		$fields_string = "";
		foreach($fields as $key=>$value) { $fields_string .= $key.'='.$value.'&'; }
		$fields_string = rtrim($fields_string, '&');
		$ch = curl_init($this->urlThermostatSetTemperature);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
		curl_setopt($ch,CURLOPT_POSTFIELDS, $fields_string);
		curl_setopt($ch, CURLOPT_HTTPHEADER, array("Cookie: ".$this->buildCookie()));
		$result = curl_exec($ch);
		$res = json_decode($result);
		if ($res->success->state != "success") {
			$this->error(706, "Could not set temperature");
		} else {
			$this->getThermostatInfo();
		}
		return $this->thermostatStatus->getData->getAllData->info_message;
	}
	function getMode() {
		$this->connect();
		$plannings = json_decode($this->thermostatStatus->getData->plannings);
		$currentPlanning = @$plannings->current_planning;
		$ret = "unknown";
		foreach (@$plannings->plannings as $planning) {
			if ($planning->id == $currentPlanning) {
				$ret = $planning->name;
				break;
			}
		}
		return $ret;
	}
}
?>

<html>
<head></head>
<body>
<?php 
$thermostat = new Qivivo("[email protected]", "my_password");
//<br/>
?>LivingRoomTempe:<?php 
$inTemperature = $thermostat->getInsideTemperature();
//var_dump($inTemperature);
echo $inTemperature;
?>,
TargetTemperature:<?php 
$reqTemperature = $thermostat->getRequestedTemperature();
echo $reqTemperature;
?>,
OutsideTemperature:<?php 
$outTemperature = $thermostat->getOutsideTemperature();
echo $outTemperature;
?>,
ThermostatStatus:<?php 
$status = $thermostat->getThermostatStatus();
echo $status;
?>,
ThermostatMode:<?php 
$mode = $thermostat->getMode();
echo $mode;
?>,
<?php 
//AccountInfo : 
//$aInfos = $thermostat->getAccountInfo();
//echo $aInfos;
?>
</body>
</html>
I installed WGET for Win32 from http://gnuwin32.sourceforge.net/packages/wget.htm

Then in EG, I created a macro based on Pako code from viewtopic.php?f=2&t=5046 (yeah, also a copy/paste : I'm good at that ;-))

Code: Select all

eg.result = None

from subprocess import Popen, PIPE, STDOUT, SW_HIDE

def popen(cmd):
    proc = Popen(cmd.split(),stdout = PIPE,stderr = STDOUT,creationflags = SW_HIDE, shell = True)
    data = proc.communicate()[0]
    return (proc.returncode, data)
ret, data = popen("call chcp") #DOS console codepage

if not ret:
    cp = "cp" + data.split()[-1]
    ret, data = popen("C:\\Progra~1\\GnuWin32\\bin\\wget.exe -q -O - '$@' localhost:7301/Test.php")
    if not ret:
        result = data.decode(cp)
        result = result.split(',')
        eg.globals.tempe_in_thermostat = result[0].rsplit(':')[1]
        eg.globals.tempe_tgt_thermostat = result[1].rsplit(':')[1]
        eg.globals.tempe_out_thermostat = result[2].rsplit(':')[1]
        eg.globals.status_thermostat = result[3].rsplit(':')[1]
        eg.globals.mode_thermostat = result[4].rsplit(':')[1]

        eg.Print("LivingRoomTempe = " + str (eg.globals.tempe_in_thermostat) )
        eg.Print("TargetTemperature = " + str (eg.globals.tempe_tgt_thermostat) )
        eg.Print("OutsideTemperature = " + str (eg.globals.tempe_out_thermostat) )
        eg.Print("ThermostatStatus = " + str (eg.globals.status_thermostat) )
        eg.Print("ThermostatMode =  " + str (eg.globals.mode_thermostat) )

and now, I can display these data in my HTML home page, ran on EG Web Server.

OK, I hear you, why don't I run my HTML page with XAMPP in the first place?

Well, first because I have to re write my entire page (plus, I need these data in EG),
and also because I don't know how to retreive eg.globals from there...

Do you have any suggestion for the latest?
Post Reply