You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1133 lines
30 KiB

8 years ago
#include <string.h>
#include <fstream>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <vector>
#include <map>
#include <time.h>
#include <netdb.h>
#include <sys/socket.h>
//#include <arpa/inet.h>
#include <unistd.h>
//#include "md5.h"
#include <openssl/md5.h>
#include "connect.h"
//#include "base64.h"
#define BASENAME "FCM"
#include <curl/curl.h>
class CurledClass
{
public:
static int writer(char *data, size_t size, size_t nmemb, string *buffer_in)
{
// Is there anything in the buffer?
if (buffer_in != NULL)
{
// Append the data to the buffer
buffer_in->append(data, size * nmemb);
// How much did we write?
return size * nmemb;
}
return 0;
}
};
CConnect* CConnect::getInstance()
{
static CConnect* instance = NULL;
if(!instance)
instance = new CConnect();
return instance;
}
CConnect::CConnect()
{
//sockfb=0;
}
CConnect::~CConnect()
{
//
}
#if 0
/******************************************************************************
* functions
******************************************************************************/
#endif
int CConnect::connect2Host(const char *adr, int port)
{
//IPv4 or IPv6
int sockfd, rv;
struct addrinfo hints, *servinfo, *p;
ostringstream s_port;
s_port << port;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC; // use AF_INET6 to force IPv6
hints.ai_socktype = SOCK_STREAM;
if ((rv = getaddrinfo(adr, s_port.str().c_str(), &hints, &servinfo)) != 0) {
fprintf(stderr, "[%s] - getaddrinfo: %s\n", BASENAME, gai_strerror(rv));
return(-1);
}
//loop through all the results and connect to the first we can
for(p = servinfo; p != NULL; p = p->ai_next)
{
if (debug)
printf("[%s] - Try to connect to %s on port %i\n", BASENAME, adr, port);
if ((sockfd = socket(p->ai_family, p->ai_socktype,p->ai_protocol)) == -1) {
perror("socket");
continue;
}
if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
close(sockfd);
perror("connect");
continue;
}
break; //if we get here, we must have connected successfully
}
if (p == NULL) {
//looped off the end of the list with no connection
fprintf(stderr, "[%s] - failed to connect\n", BASENAME);
return(-1);
}
freeaddrinfo(servinfo); //all done with this structure
return(sockfd);
}
string CConnect::post2fritz(const char* url, int port, const string data, const string curlOutFile)
{
CURL *curl;
CURLcode result;
// Create our curl handle
curl = curl_easy_init();
//errors
char errorBuffer[CURL_ERROR_SIZE];
// Write all expected data in here
string buffer;
if(!curl){
cerr << "Error init Curl!" << endl;
return string();
}
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorBuffer);
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_HEADER, 0);
curl_easy_setopt(curl, CURLOPT_USERAGENT, "Mozilla/5.0");
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(curl, CURLOPT_VERBOSE, debug?1:0);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
curl_easy_setopt(curl, CURLOPT_PORT, port);
if(!data.empty())
{
curl_easy_setopt(curl, CURLOPT_POST, 1);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data.c_str());
// print CURLOPT_POSTFIELDS
if(debug > 1 && !data.empty()) {cout << '[' << BASENAME << "] - CURLOPT_POSTFIELDS: " << data << endl;}
}
FILE *tmpFile = fopen(curlOutFile.c_str(), "w");
if (tmpFile) {
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, NULL);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, tmpFile);
} else {
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurledClass::writer);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
}
// Attempt to retrieve the remote page
result = curl_easy_perform(curl);
// Always cleanup
curl_easy_cleanup(curl);
if (tmpFile)
fclose(tmpFile);
if(debug > 1){
if(curlOutFile.empty())
cout << "DEBUG-OUT" << ">>" << buffer << "<<" << "DEBUG-OUT END" << endl;
else
cout << "DEBUG-OUT" << ">>" << curlOutFile << "<<" << "DEBUG-OUT END" << endl;
}
if(result == CURLE_OK)
return(buffer);
return string();
}
int CConnect::get2box(const char* host, int port, const char* msg, const char* upwd, const char* msgtype, int msgtimeout)
{
ostringstream url;
if(debug) {cout << '[' << BASENAME << "] - " << __FUNCTION__ << "()" << endl;}
url << host << "/control/message?" << msgtype << "=" << msg << "&timeout=" << msgtimeout;
string s = post2fritz(url.str().c_str(), port);
return(1);
}
int CConnect::get_challenge()
{
ostringstream url;
if(debug) {cout << '[' << BASENAME << "] - " << __FUNCTION__ << "()" << endl;}
//if(mysockfb <= 0){
// printf("[%s] - CConnect::get_challenge(): ERR connect2Host\n", BASENAME);
// return 0;
//}
//url << "/cgi-bin/webcm?getpage=../html/login_sid.xml"; // Firmwareversion xx.04.74
url << FritzAdr << "/login_sid.lua"; // OS 5.50
string s = post2fritz(url.str().c_str());
//search
string s1 = "<Challenge>";
string s2 = "</Challenge>";
string token;
size_t pos = 0;
if((pos = s.find(s1)) != string::npos)
{
s.erase(0, pos + s1.length());
pos = 0;
if((pos = s.find(s2)) != string::npos)
{
s.erase(pos, s.length());
if(!s.empty())
{
strncpy(challenge,s.c_str(),sizeof(challenge));
if(debug) {printf("[%s] - CHALLENGE %s \n", BASENAME, challenge);}
return 1;
}
}
}
printf("[%s] - failed to get CHALLENGE\n", BASENAME);
return 0;
}
int CConnect::get_md5(const char *challenge, char *fritzPW)
{
//convert to utf16
//http://www.avm.de/de/Extern/Technical_Note_Session_ID.pdf
unsigned int i;
int y = 0;
string utf8_str = (string) challenge + "-" + (string) UTF8toISO(fritzPW);
string utf16_str = ("");
if(debug > 1)
printf("[%s] - Challenge-Password = \"%s-%s\"\n",BASENAME, challenge, UTF8toISO(fritzPW));
if(debug)
printf("[%s] - Binary for hash = ", BASENAME);
for (i=0; i < utf8_str.length(); i++)
{
y = i*2;
// change UNICODE > 255 in 46 (".")
if (utf8_str[i] > 0xAD)
{
utf16_str += '\x2E';
utf16_str += '\x00';
}
else
{
utf16_str += utf8_str[i];
utf16_str += '\x00';
}
if (debug)
printf("%02x%02x",utf16_str[y],utf16_str[y+1]);
}
if (debug)
printf("\n");
//get md5sum from utf16 binary hash
MD5_CTX ctx;
//struct MD5Context ctx; /*md5.h"*/
MD5_Init(&ctx);
MD5_Update(&ctx, utf16_str.c_str(), strlen(utf8_str.c_str())*2)/*size*/;
MD5_Final(digest, &ctx);
strcpy((char *)md5sum,"");
for (i = 0; i < 16; i++) {
char fdigest[5];
sprintf(fdigest,"%02x", digest[i]);
strcat((char *)md5sum, fdigest);
}
if(debug)
cout << '[' << BASENAME << "] - MD5 hash = " << md5sum << " (" << strlen((char *)md5sum) << ')' << endl;
return(strlen((char *)md5sum));
}
int CConnect::get_sid(const char *challenge, const unsigned char *md5)
{
ostringstream command;
command << "login:command/response="
<< challenge << '-' << md5
<< "&getpage=../html/login_sid.xml";
if(debug) {cout << '[' << BASENAME << "] - " << __FUNCTION__ << "()" << endl;}
string s = post2fritz(FritzAdr,80, command.str());
if(debug) {cout << s << endl;}
//search
string s1 = "<SID>";
string s2 = "</SID>";
string token;
size_t pos = 0;
if((pos = s.find(s1)) != string::npos)
{
s.erase(0, pos + s1.length());
pos = 0;
if((pos = s.find(s2)) != string::npos)
{
s.erase(pos, s.length());
if(s != "0000000000000000" && !s.empty())
{
strncpy(sid,s.c_str(),sizeof(sid));
if(debug) {printf("[%s] - SID %s \n", BASENAME, sid);}
return 1;
}
}
}
printf("[%s] - failed to get SID\n", BASENAME);
return(0);
}
int CConnect::get_sid_LUA(const char *challenge, const unsigned char *md5)
{
ostringstream url, command;
url << FritzAdr << "/login_sid.lua";
command << "response="
<< challenge << '-' << md5;
if(debug) {cout << '[' << BASENAME << "] - " << __FUNCTION__ << "()" << endl;}
string s = post2fritz(url.str().c_str(),80, command.str());
//search
string s1 = "<SID>";
string s2 = "</SID>";
string token;
size_t pos = 0;
if((pos = s.find(s1)) != string::npos)
{
s.erase(0, pos + s1.length());
pos = 0;
if((pos = s.find(s2)) != string::npos)
{
s.erase(pos, s.length());
if(s != "0000000000000000" && !s.empty())
{
strncpy(sid,s.c_str(),sizeof(sid));
if(debug) {printf("[%s] - SID %s \n", BASENAME, sid);}
return 1;
}
}
}
/* //split into line
string delimiter = "\n";
string token;
size_t pos = 0;
while ((pos = s.find(delimiter)) != string::npos) {
i++;
token = s.substr(0, pos);
if(debug) {cout << "rec[" << i << "]" << token << endl;}
s.erase(0, pos + delimiter.length());
}
*/
printf("[%s] - failed to get SID\n", BASENAME);
return(0);
}
#if 0
/******************************************************************************
* tools
******************************************************************************/
#endif
char *CConnect::trim(char *txt)
{
register int l;
register char *p1, *p2;
if (*txt==' ')
{
for (p1=p2=txt;
(*p1==' ') || (*p1=='\t') || (*p1=='\n') || (*p1=='\r');
p1++);
while (*p1)
*p2++=*p1++;
*p2='\0';
}
if ((l=strlen(txt))>0)
for (p1=txt+l-1;
(*p1==' ') || (*p1=='\t') || (*p1=='\n') || (*p1=='\r');
*p1--='\0');
return(txt);
}
char *CConnect::UTF8toISO(char *txt)
{
//'ä','ö','ü','Ä','Ö','Ü','ß'
const char iso[7]={'\xe4','\xf6','\xfc','\xc4','\xd6','\xdc','\xdf'}, //ISO-8859-1 ö = 0xf6
utf[7]={'\xa4','\xb6','\xbc','\x84','\x96','\x9c','\x9f'}; //UTF-8 ö = 0xc3 0xb6
int i,found,quota=0;
char *rptr=txt,*tptr=txt;
while(*rptr != '\0')
{
if(*rptr=='\'')
{
quota^=1;
}
if (!quota && *rptr=='\xc3' && *(rptr+1))
{
found=0;
for(i=0; i<(int)sizeof(utf) && !found; i++)
{
if(*(rptr+1)==utf[i])
{
found=1;
*tptr=iso[i];
++rptr;
}
}
if(!found)
{
*tptr=*rptr;
}
}
else
{
*tptr=*rptr;
}
tptr++;
rptr++;
}
*tptr=0;
return(txt);
}
int CConnect::ExistFile(const char *fname)
{
FILE *efh;
if((efh=fopen(fname,"r"))==NULL)
{
return(0);
}
fclose(efh);
return(1);
}
int CConnect::TouchFile(const char *fname)
{
FILE *tfh;
if((tfh=fopen(fname,"w"))==NULL)
{
return(0);
}
fclose(tfh);
return(1);
}
string CConnect::timestamp()
{
ostringstream txt;
time_t timestamp;
tm *now;
timestamp = time(0);
now = localtime(&timestamp);
txt << '['
<< setfill('0') << setw (2) << static_cast<int>(now->tm_hour)
<< ':'
<< setfill('0') << setw (2) << static_cast<int>(now->tm_min)
<< ':'
<< setfill('0') << setw (2) << static_cast<int>(now->tm_sec)
<< ']';
return txt.str();
}
void CConnect::get_time(int *wday,int *hour,int *min)
{
time_t timestamp;
tm *now;
timestamp = time(0);
now = localtime(&timestamp);
*wday=now->tm_wday;
*hour=now->tm_hour;
*min=now->tm_min;
}
int CConnect::my_atoi(const string text)
{
//atoi c++ way
int val;
stringstream s(text);
s >> val;
return(val);
}
string CConnect::itoString (int& i)
{
stringstream temp;
temp << i;
return temp.str();
}
void CConnect::StringReplace(string &str, const string search, const string rstr)
{
stringstream f(search); // stringstream f("string1;string2;stringX");
string s;
while (getline(f, s, ';'))
{
string::size_type ptr = 0;
string::size_type pos = 0;
while((ptr = str.find(s,pos)) != string::npos)
{
str.replace(ptr,s.length(),rstr);
pos = ptr + rstr.length();
}
}
}
string CConnect::parseString(const char* var, string& string_to_serarch)
{
string res="";
size_t pos1, pos2;
if((pos1 = string_to_serarch.find(var)) != string::npos)
{
// "ver":"84.05.50"
pos1 += strlen(var)+3;
string tmp = string_to_serarch.substr(pos1);
if((pos2 = tmp.find('"')) != string::npos)
{
res = tmp.substr(0,pos2);
//cout << " result: " << var << " = " << res << endl;
}
}
else
cout << " no result for " << '"' << var << '"' << res << endl;
return(res);
}
string CConnect::parseString(string search1, string search2, string str)
{
string ret, search;
size_t pos_wildcard, pos_firstline, pos_search1, pos_search2;
pos_wildcard = pos_firstline = pos_search1 = pos_search2 = string::npos;
if((pos_wildcard = search1.find('*')) != string::npos)
{
search = search1.substr(0, pos_wildcard);
//cout << "wildcard detected" << '\t' << "= " << search << "[*]" << search1.substr(pos_wildcard+1) << endl;
}
else
search = search1;
//cout << "search1" << "\t\t\t" << "= " << '"' << search << '"' << endl;
if((pos_search1 = str.find(search)) != string::npos)
{
//cout << "search1 found" << "\t\t" << "= " << '"' << search << '"' << " at pos "<< (int)(pos_search1) << " => " << str << endl;
pos_search1 += search.length();
if(pos_wildcard != string::npos)
{
size_t pos_wildcard_ext;
string wildcard_ext = search1.substr(pos_wildcard+1);
//cout << "wildcard_ext" << "\t\t" << "= " << '"' << wildcard_ext << '"' << endl;
if((pos_wildcard_ext = str.find(wildcard_ext,pos_wildcard+1)) != string::npos)
{
//cout << "wildcard_ext found" << "\t" << "= " << '"' << wildcard_ext << '"' << " at pos "<< (int)(pos_wildcard_ext) << " => " << str << endl;
pos_search1 = pos_wildcard_ext + wildcard_ext.length();
}
else
{
//cout << "wildcard_ext not found in line " << acc << " - exit" << endl;
return("");
}
}
}
else
{
//cout << "search1 not found in line " << acc << " - exit" << endl;
return("");
}
if(pos_search1 != string::npos)
{
//cout << "search2 " << "\t\t" << "= " << '"' << search2 << '"' << endl;
if(search2 == "\n")
{
ret = str.substr(pos_search1, str.length() - pos_search1);
return(ret);
}
if((pos_search2 = str.find(search2, pos_search1)) != string::npos)
{
if(search2.empty())
pos_search2 = str.length();
//cout << "search2" << "\t\t\t" << "= " << '"' << search2 << '"' << " found at "<< (int)(pos_search2) << " => " << str << endl;
ret = str.substr(pos_search1, pos_search2 - pos_search1);
}
//else
//cout << "search2 not found in line " << acc << " - exit" << endl;
}
return(ret);
}
#if 0
/******************************************************************************
* get login to Fritz!Box
******************************************************************************/
#endif
int CConnect::get_login(const char* fritzPW)
{
if (!get_challenge()) {
printf("[%s] - ERROR get Challenge\n", BASENAME);
return(0);
}
get_md5(challenge,(char*)fritzPW);
if(!get_sid_LUA(challenge,md5sum)) //after 5.5x
{
printf("[%s] - login_sid.lua not found\n", BASENAME);
if(!get_sid(challenge,md5sum)) //before 5.5x
{
printf("[%s] - ERROR get SID\n", BASENAME);
return 0;
}
}
return(1);
}
#if 0
/******************************************************************************
* send logout to Fritz!Box
******************************************************************************/
#endif
int CConnect::send_logout(const char *sid)
{
ostringstream url, command;
url << FritzAdr << "/cgi-bin/webcm";
command << "sid=" << sid
<< "&security:command/logout=&getpage=../html/confirm_logout.htlm";
if(debug) {cout << '[' << BASENAME << "] - " << __FUNCTION__ << "()" << endl;}
//(w_fritz, "GET /home/home.lua?sid=%s&logout=1 HTTP/1.1\r\nHost: 192.168.99.254\r\n\r\n", sid);
string s = post2fritz(url.str().c_str(),80, command.str().c_str());
return(1);
}
#if 0
/******************************************************************************
* send query's to Fritz!Box
******************************************************************************/
#endif
int CConnect::send_refresh(const char *sid)
{
ostringstream url, command;
url << FritzAdr << "/cgi-bin/webcm";
command << "getpage=../html/query.txt"
<< "&var:n[0]=telcfg:settings/RefreshJournal"
<< "&var:n[1]=telcfg:settings/Journal/count"
<< "&sid=" << sid;
if(debug) {cout << '[' << BASENAME << "] - " << __FUNCTION__ << "()" << endl;}
string s = post2fritz(url.str().c_str(),80, command.str().c_str());;
return(0);
}
void CConnect::parseXML(const string text)
{
device d;
int tag=0, val=0;
string tagname, value;
char* t= (char*) text.c_str();
d.tist = -1;
d.tsoll = -1;
d.absenk = -1;
d.komfort = -1;
while (*t!=0)
{
if(*t=='<')
{
tag=1;
val=0;
if(!value.empty())
{
if(tagname=="name") d.name = value;
if(tagname=="mode") d.mode = value;
if(tagname=="present") d.present = my_atoi(value);
if(tagname=="state") d.state = my_atoi(value);
if(tagname=="lock") d.lock = my_atoi(value);
if(tagname=="power") d.power = my_atoi(value);
if(tagname=="energy") d.energy = my_atoi(value);
if(tagname=="celsius") d.celsius = my_atoi(value);
if(tagname=="offset") d.offset = my_atoi(value);
if(tagname=="tist") d.tist = my_atoi(value);
if(tagname=="tsoll") d.tsoll = my_atoi(value);
if(tagname=="absenk") d.absenk = my_atoi(value);
if(tagname=="komfort") d.komfort = my_atoi(value);
}
value="";
tagname="";
}
if(*t!='>' && *t!='<')
{
if(tag==1)
tagname += *t;
if(val==1)
value += *t;
}
if(*t=='>')
{
tag=0;
val=1;
if(strstr(tagname.c_str(),"identifier="))
{
string s = parseString("identifier=\"","\"",tagname);
StringReplace(s," ","");
d.identifier = s;
}
if(strstr(tagname.c_str(),"productname="))
{
string s = parseString("productname=\"","\"",tagname);
StringReplace(s," ","");
d.productname = s;
}
if(!strcmp(tagname.c_str(),"/device") || !strcmp(tagname.c_str(),"/group"))
devices.push_back(d);
}
t++;
}
}
void CConnect::send2actor(const unsigned int& inx, int& t_soll)
{
int state_soll = -1;
int temperature = 0;
if(devices[inx].productname=="FRITZ!DECT200")
{
cout << '[' << BASENAME << "]\t\tTemperature: Plan(" << t_soll << ")/Now(" << devices[inx].celsius << "); state: " << (devices[inx].state == 1 ? "ON":"OFF") << endl;
// convert special temperature
switch(t_soll) {
case 1: state_soll = 1; // switch on
break;
case 0: state_soll = 0; // switch off
break;
}
if(state_soll == -1) {
if(t_soll <= devices[inx].celsius)
{ //temperature okay
cout << '[' << BASENAME << "]\t\tTemperature okay"<< endl;
state_soll = 0;
}
else if(t_soll > devices[inx].celsius)
{ //temperature to low
cout << '[' << BASENAME << "]\t\tTemperature to low"<< endl;
state_soll = 1;
}
}
if(state_soll >= 0 && state_soll != devices[inx].state)
{
cout << '[' << BASENAME << "]\t\t" << "\033[0;32m" << "sending Deviceswitch "<<(state_soll == 0? "OFF":"ON") << "\033[0m" << endl;
if(state_soll == 0)
smartHome(sid, "setswitchoff", devices[inx].identifier);
else
smartHome(sid, "setswitchon", devices[inx].identifier);
}
else
cout << '[' << BASENAME << "]\t\t" << "\033[0;31m" << "send nothing to actor, state is equal" << "\033[0m" << endl;
// set flagfile
string flag="/var/etc/.device_" + devices[inx].identifier;
setFlag(flag.c_str(),state_soll);
}
else if(devices[inx].productname=="CometDECT" || devices[inx].productname=="FRITZ!DECT300")
{
cout << '[' << BASENAME << "]\t\tTemperature: Plan " << t_soll << " (" << (t_soll > 1 ? t_soll * 0.2 : t_soll) << "), tist(" << devices[inx].tist << "); tsoll(" << devices[inx].tsoll << ')' << endl;
// convert temperature
switch(t_soll) {
case -1: temperature = -1; // do nothing
break;
case 0: temperature = 253; // switch off
break;
default: temperature = t_soll * 0.2; // temperature step up to 0.5°, 43 = 21,5°
break;
}
if(devices[inx].tsoll != temperature) // check if plan temperature stored in actor
{
if(temperature == -1)
cout << '[' << BASENAME << "]\t\t" << "\033[0;31m" << "send nothing to actor while Plan value is (-1)" << "\033[0m" << endl;
else {
cout << '[' << BASENAME << "]\t\t" << "\033[0;32m" << "send new tsoll temperature (" << temperature << ") to actor" << "\033[0m" << endl;
string command = "sethkrtsoll&param=" + itoString(temperature);
smartHome(sid, command.c_str(), devices[inx].identifier);
}
}
else
cout << '[' << BASENAME << "]\t\t" << "\033[0;31m" << "send nothing to actor, storred tsoll temperature is equal" << "\033[0m" << endl;
}
else
cout << '[' << BASENAME << "]\t\t" << "\033[0;32m" << "productname \"" << devices[inx].productname << "\" not found" << "\033[0m" << endl;
}
int CConnect::checkdevice(map<string, vector<string> >& w, map<string, vector<string> >& t)
{
int wday,hour,min,ret=-1;
get_time(&wday,&hour,&min);
// for building device index
unsigned int dev_inx = 0;
for(vector<device>::iterator dev = devices.begin(); dev != devices.end(); ++dev, ++dev_inx)
{
// find cdw map key by device id
map<string, vector<string> >::iterator dev_search = w.find((*dev).identifier);
if(dev_search != w.end())
{
// check config table syntax
if(dev_search->second.size() != 7) {
cout << "[ERROR] - " << __FUNCTION__ << "(): WP table syntax error, we must have 7 values per line\n";
return(ret);
}
// get map value for weekday
string w_value = dev_search->second[wday];
cout << '[' << BASENAME << "] - " << __FUNCTION__ << "(): device[" << (*dev).identifier << "] weekday = " << wday << ", value = " << w_value << ", name = " << (*dev).name << endl;
// find cdt map key by cdw value
map<string, vector<string> >::iterator search = t.find(w_value);
if(search != t.end())
{
// check config table syntax
if( search->second.size() % 3 != 0 ) { // 3 because HH MM are 2 values
cout << '[' << BASENAME << "] - " << __FUNCTION__ << "(): DP table syntax error, we must have time and temperature pair (HH:MM,TTT)\n";
return(ret);
}
// read every time and temperature pair for cdt key
for (unsigned int i=0; i <search->second.size(); ++i)
{
// check time and temperature after reading 3 values (1=HH, 2=MM, 3=temperature)
unsigned int delim = 3;
if( (i+1) % delim == 0)
{
int now = hour *60 + min;
int ev = my_atoi(search->second[i-2]) * 60 + my_atoi(search->second[i-1]);
int next_ev = ev;
int temperature = my_atoi(search->second[i]);
// check for existing next time event
if( i+1 != search->second.size() )
next_ev = my_atoi(search->second[i+1]) * 60 + my_atoi(search->second[i+2]);
if((now >= ev && now <= next_ev) ||
(i+1 == search->second.size())) // last event was earlier than now
{
// time event
cout << '[' << BASENAME << "]\t\tTime event = " << ev/60.0 << " temperature = " << temperature << endl;
send2actor(dev_inx, temperature);
break;
}
}
}
}
else
cout << '[' << BASENAME << "]\t\tvalue not found in DP map" << endl;
}
else
cout << '[' << BASENAME << "] - " << __FUNCTION__ << ": device[" << (*dev).identifier << "] not found in table WP" << endl;
}
return(ret);
}
int CConnect::inTime(int index, vector<vector<string> >& week, vector<vector<string> >& day)
{
int wday,hour,min,ret=-1;
get_time(&wday,&hour,&min);
int pos = my_atoi(week[index][wday]);
cout<<'['<<BASENAME<<"] - "<< __FUNCTION__<< "() "<<"device index="<<index<<" wday="<<wday<<" hour="<<hour<<" min="<<min<<"; Weekplan ("<<pos<<") = ";
if(pos != 0)
{
pos--;
/*
for (unsigned int i=0; i<day[pos].size(); ++i)
{
cout << day[pos][i] << ' ';
}
cout<<endl;
*/
for (unsigned int i=0; i<day[pos].size(); ++i)
{
if(i % 4 == 0)
{
int now = hour *60 + min;
int from = my_atoi(day[pos][i]) *60 + my_atoi(day[pos][i+1]);
int to = my_atoi(day[pos][i+2]) *60 + my_atoi(day[pos][i+3]);
if(now >= from && now <= to)
{
cout<< day[pos][i]<<":"<<day[pos][i+1]<<"-"<<day[pos][i+2]<<":"<< day[pos][i+3]<<endl;
return(1);
}
cout<< day[pos][i]<<":"<<day[pos][i+1]<<"-"<<day[pos][i+2]<<":"<< day[pos][i+3]<<' ';
}
}
cout<<endl;
ret=0;
}
return(ret);
}
int CConnect::smartHome(const char *sid, const char *command, const string ain)
{
ostringstream url;
int ret=-1;
if(debug) {cout << '[' << BASENAME << "] - " << __FUNCTION__ << "()" << endl;}
url << FritzAdr << "/webservices/homeautoswitch.lua?switchcmd=" << command << (ain.empty()?"":"&ain=") << ain << "&sid=" << sid;
string s = post2fritz(url.str().c_str());
if(!strcmp(command,"getdevicelistinfos"))
{
//s = "<devicelist version=\"1\"><device identifier=\"08761 0831319\" id=\"16\" functionbitmask=\"1280\" fwversion=\"03.36\" manufacturer=\"AVM\" productname=\"FRITZ!DECT Repeater 100\"><present>1</present><name>Fritz!Dect Rep 100</name><temperature><celsius>200</celsius><offset>-24</offset></temperature></device><device identifier=\"08761 0021731\" id=\"17\" functionbitmask=\"896\" fwversion=\"03.36\" manufacturer=\"AVM\" productname=\"FRITZ!DECT 200\"><present>1</present><name>WZ Stehlampe</name><switch><state>0</state><mode>manuell</mode><lock>0</lock></switch><powermeter><power>0</power><energy>4282</energy></powermeter><temperature><celsius>190</celsius><offset>-27</offset></temperature></device><device identifier=\"08761 0068302\" id=\"18\" functionbitmask=\"896\" fwversion=\"03.36\" manufacturer=\"AVM\" productname=\"FRITZ!DECT 200\"><present>1</present><name>WZ Freiheitsstatue</name><switch><state>0</state><mode>auto</mode><lock>0</lock></switch><powermeter><power>0</power><energy>2167</energy></powermeter><temperature><celsius>190</celsius><offset>-17</offset></temperature></device><device identifier=\"08761 0069718\" id=\"19\" functionbitmask=\"896\" fwversion=\"03.36\" manufacturer=\"AVM\" productname=\"FRITZ!DECT 200\"><present>0</present><name>Bananen-Haus</name><switch><state></state><mode></mode><lock></lock></switch><powermeter><power></power><energy></energy></powermeter><temperature><celsius></celsius><offset></offset></temperature></device><device identifier=\"08761 0021736\" id=\"20\" functionbitmask=\"896\" fwversion=\"03.36\" manufacturer=\"AVM\" productname=\"FRITZ!DECT 200\"><present>1</present><name>RaspiServer</name><switch><state>1</state><mode>manuell</mode><lock>0</lock></switch><powermeter><power>4360</power><energy>53683</energy></powermeter><temperature><celsius>210</celsius><offset>-35</offset></temperature></device><device identifier=\"08761 0068647\" id=\"21\" functionbitmask=\"896\" fwversion=\"03.36\" manufacturer=\"AVM\" productname=\"FRITZ!DECT 200\"><present>1</present><name>Wohnmobil</name><switch><state>0</state><mode>manuell</mode><lock>0</lock></switch><powermeter><power>0</power><energy>12620</energy></powermeter><temperature><celsius>136</celsius><offset>-25</offset></temperature></device><group identifier=\"86:6D:75-900\" id=\"900\" functionbitmask=\"512\" fwversion=\"1.0\" manufacturer=\"AVM\" productname=\"\"><present>1</present><name>Testgruppe</name><switch><state>0</state><mode>manuell</mode><lock></lock></switch><groupinfo><masterdeviceid>0</masterdeviceid><members>17,21</members></groupinfo></group></devicelist>";
parseXML(s);
//cout <<"identifier;present;name;state;mode;lock;power;energy;celsius;offset;" <<endl;
unsigned int x=0;
for(vector<device>::iterator it = devices.begin(); it != devices.end(); ++it, ++x)
{
if(!ain.empty())
{
if((*it).identifier==ain)
{
cout<<'['<<BASENAME<<"] - " <<(*it).productname << ": "
<<(*it).identifier << ';'<<(*it).present << ';'<<(*it).name << ';'<<(*it).state << ';'<<(*it).mode << ';'
<<(*it).lock << ';'<<(*it).power << ';'<<(*it).energy << ';'<<(*it).celsius << ';'<<(*it).offset << ';'
<<(*it).tist << ';'<<(*it).tsoll << ';'<<(*it).absenk << ';'<<(*it).komfort << ';'<<endl;
return (x);
}
}
else
{
cout<<'['<<BASENAME<<"] - " <<(*it).productname << ": "
<<(*it).identifier << ';'<<(*it).present << ';'<<(*it).name << ';'<<(*it).state << ';'<<(*it).mode << ';'
<<(*it).lock << ';'<<(*it).power << ';'<<(*it).energy << ';'<<(*it).celsius << ';'<<(*it).offset << ';'
<<(*it).tist << ';'<<(*it).tsoll << ';'<<(*it).absenk << ';'<<(*it).komfort << ';'<<endl;
}
}
}
return (ret);
}
#if 0
/******************************************************************************
* FritzCallMonitor
******************************************************************************/
#endif
//new query
int CConnect::send_TAMquery(const char *flag, const char *sid, const char *searchstr)
{
ostringstream url;
if(debug) {cout << '[' << BASENAME << "] - " << __FUNCTION__ << "()" << endl;}
url << FritzAdr << "/query.lua?sid=" << sid << searchstr;
string s = post2fritz(url.str().c_str());
StringReplace(s," ","");
string res = parseString("var", s);
if(!res.empty())
{
setFlag(flag,my_atoi(res));
}
else {
printf("[%s] - %s ERROR\n", BASENAME, timestamp().c_str());
return 1;
}
return 0;
}
void CConnect::setFlag(const char *flag, const int& i)
{
if(i==0)
{
cout << '[' << BASENAME << ']' << " - " << timestamp() << " disable flag "<<flag<<endl;
remove(flag);
}
else {
cout << '[' << BASENAME << ']' << " - " << timestamp() << " enable flag "<<flag<<endl;
if(!TouchFile(flag))
cout << "ERROR writing flag " << flag << endl;
}
}
#if 0
//old query
int CConnect::send_query(const char *flag, const char *sid, const char *searchstr)
{
ostringstream command;
int i=0;
char *line;
ssize_t read;
size_t len;
command << "getpage=../html/query.txt"
<< searchstr
<< "&sid=" << sid;
if(debug) {cout << '[' << BASENAME << "] - " << __FUNCTION__ << "()" << endl;}
post2fritz(command.str().c_str());
line=NULL;
while ((read = getline(&line, &len, r_fritz)) != -1)
{
i++;
if(debug>1)
printf("line[%d]: %s", i, line);
if(i==7)
{
if(strlen(line)>10) {
printf("ERROR\n");
break;
}
else if(atoi(trim(line))==0) {
printf("res=%s =>disable flag\n",trim(line));
remove(flag);
break;
}
else {
printf("res=%s =>enable flag\n",trim(line));
if(!TouchFile(flag))
printf("ERROR writing flag %s\n",flag);
break;
}
}
}
if(line)
free(line);
quitfritz();
return(0);
}
#endif
int CConnect::get_callerlist(const char *sid, const char *file)
{
ostringstream url, command;
if(debug) {cout << '[' << BASENAME << "] - " << __FUNCTION__ << "()" << endl;}
url << FritzAdr << "/fon_num/foncalls_list.lua?csv=";
command << "refresh=&sid=" << sid;
string s = post2fritz(url.str().c_str(),80, command.str().c_str(), file);
return(0);
}