1 #if BOOST_VERSION < 104600 5 #include <boost/array.hpp> 7 #include <boost/property_tree/ptree.hpp> 8 #include <boost/property_tree/json_parser.hpp> 26 namespace ba = boost::asio;
27 namespace bs = boost::system;
28 namespace pt = boost::property_tree;
29 namespace dummy = ba::placeholders;
55 virtual void Update(
const vector<float> &)
64 Out() <<
"------------------------------------------------------" << endl;
65 Out() << fRdfData << endl;
66 Out() <<
"------------------------------------------------------" << endl;
69 const size_t p1 = fRdfData.find(
"\r\n\r\n");
72 Warn(
"HTTP header not found.");
77 fRdfData.erase(0, p1+4);
79 vector<float>
temp(3);
86 pt::read_json(ss, tree);
88 const pt::ptree sub2 = tree.get_child(
"sensor_values.").begin()->second;
89 const pt::ptree sub3 = sub2.get_child(
"values").begin()->second.begin()->second;
91 temp[0] = sub3.get_child(
"v").get_value<
float>();
93 auto sub = sub3.get_child(
"st.").begin();
95 temp[1] = sub++->second.get_value<
float>();
96 temp[2] = sub->second.get_value<
float>();
98 catch (std::exception
const& e)
100 Warn(
"Parsing of JSON failed: "+
string(e.what()));
113 msg <<
"T=" << temp[0] <<
"°C" 114 <<
" Tmin=" << temp[1] <<
"°C" 115 <<
" Tmax=" << temp[2] <<
"°C";
120 fLastReport =
Time();
124 void HandleRead(
const boost::system::error_code& err,
size_t bytes_received)
127 if (bytes_received==0 || err)
129 if (err==ba::error::eof)
131 if (!fRdfData.empty())
138 if (err && err!=ba::error::eof &&
139 err!=ba::error::basic_errors::not_connected &&
140 err!=ba::error::basic_errors::operation_aborted)
143 str <<
"Reading from " << URL() <<
": " << err.message() <<
" (" << err <<
")";
146 PostClose(err!=ba::error::basic_errors::operation_aborted);
152 fRdfData += string(fArray.data(), bytes_received);
155 const size_t p1 = fRdfData.find(
"\r\n\r\n");
156 if (p1!=string::npos)
159 const size_t p2 = fRdfData.find(
"\r\n\r\n", p1+4);
160 if (p2!=string::npos)
174 dummy::error, dummy::bytes_transferred));
182 if (error && error!=ba::error::basic_errors::operation_aborted)
185 str <<
"Write timeout of " << URL() <<
": " << error.message() <<
" (" << error <<
")";
204 if (fKeepAlive.expires_at() > ba::deadline_timer::traits_type::now())
224 fIsValid(false), fIsVerbose(true), fDebugRx(false), fLastReport(
Time::none),
258 string cmd =
"GET " + fSite;
260 if (!fNextCommand.empty())
261 cmd +=
"?" + fNextCommand;
263 cmd +=
" HTTP/1.1\r\n";
270 fKeepAlive.expires_from_now(boost::posix_time::seconds(fInterval));
272 this, dummy::error));
283 if (!fLastReport.
IsValid() ||
Time()>fLastReport+boost::posix_time::seconds(fInterval*3))
304 fDim(
"TEMPERATURE/DATA",
"F:1;F:1;F:1",
305 "Temperature readout from power switch" 306 "|T[degC]:Current temperature" 307 "|Tmin[degC]:24h minimum" 308 "|Tmax[degC]:24h maximum")
320 template <
class T,
class S>
333 msg << name <<
" - Received event has " << has <<
" bytes, but expected " << size <<
".";
340 if (!CheckEventSize(evt.
GetSize(),
"SetVerbosity", 1))
341 return T::kSM_FatalError;
343 fPower.SetVerbose(evt.
GetBool());
345 return T::GetCurrentState();
350 if (!CheckEventSize(evt.
GetSize(),
"SetDebugRx", 1))
351 return T::kSM_FatalError;
353 fPower.SetDebugRx(evt.
GetBool());
355 return T::GetCurrentState();
360 return fPower.GetState();
370 "No connection to web-server could be established recently");
373 "Connection established, but no valid data received");
376 "Connection established, received data valid");
379 T::AddEvent(
"SET_VERBOSE",
"B:1")
381 (
"Set verbosity state" 382 "|verbosity[bool]:disable or enable verbosity for interpreted data (yes/no)");
384 T::AddEvent(
"SET_DEBUG_RX",
"B:1")
386 (
"Set debux-rx state" 387 "|debug[bool]:dump received text and parsed text to console (yes/no)");
393 fPower.SetVerbose(!conf.
Get<
bool>(
"quiet"));
394 fPower.SetInterval(conf.
Get<uint16_t>(
"interval"));
395 fPower.SetDebugTx(conf.
Get<
bool>(
"debug-tx"));
396 fPower.SetDebugRx(conf.
Get<
bool>(
"debug-rx"));
397 fPower.SetSite(conf.
Get<
string>(
"url"));
398 fPower.SetEndpoint(conf.
Get<
string>(
"addr"));
399 fPower.StartConnect();
410 template<
class T,
class S,
class R>
413 return Main::execute<T, StateMachinePowerControl<S, R>>(conf);
418 po::options_description control(
"Lid control");
419 control.add_options()
420 (
"no-dim,d",
po_switch(),
"Disable dim services")
421 (
"addr,a", var<string>(
"10.0.100.234:80"),
"Network address of the lid controling Arduino including port")
422 (
"url,u", var<string>(
"/statusjsn.js?components=18179&_=1365876572736"),
"File name and path to load")
423 (
"quiet,q",
po_bool(
true),
"Disable printing contents of all received messages (except dynamic data) in clear text.")
424 (
"interval,i", var<uint16_t>(60),
"Interval between two updates on the server in seconds")
425 (
"debug-tx",
po_bool(),
"Enable debugging of ethernet transmission.")
426 (
"debug-rx",
po_bool(),
"Enable debugging for received data.")
444 "The temperature is an interface to readout the temperature from the power switch.\n" 446 "The default is that the program is started without user intercation. " 447 "All actions are supposed to arrive as DimCommands. Using the -c " 448 "option, a local shell can be initialized. With h or help a short " 449 "help message about the usuage can be brought to the screen.\n" 451 "Usage: temperature [-c type] [OPTIONS]\n" 452 " or: temperature [OPTIONS]\n";
478 int main(
int argc,
const char* argv[])
489 if (!conf.
Has(
"console"))
491 if (conf.
Get<
bool>(
"no-dim"))
492 return RunShell<LocalStream, StateMachine, ConnectionPowerSwitch>(conf);
494 return RunShell<LocalStream, StateMachineDim, ConnectionDimPowerSwitch>(conf);
497 if (conf.
Get<
bool>(
"no-dim"))
499 if (conf.
Get<
int>(
"console")==0)
500 return RunShell<LocalShell, StateMachine, ConnectionPowerSwitch>(conf);
502 return RunShell<LocalConsole, StateMachine, ConnectionPowerSwitch>(conf);
506 if (conf.
Get<
int>(
"console")==0)
507 return RunShell<LocalShell, StateMachineDim, ConnectionDimPowerSwitch>(conf);
509 return RunShell<LocalConsole, StateMachineDim, ConnectionDimPowerSwitch>(conf);
StateMachinePowerControl(ostream &out=cout)
boost::asio::streambuf fBuffer
int RunShell(Configuration &conf)
A general base-class describing events issues in a state machine.
void SetupConfiguration(Configuration &conf)
The base implementation of a distributed messaging system.
Adds some functionality to boost::posix_time::ptime for our needs.
void SetPrintUsage(const std::function< void(void)> &func)
T Get(const std::string &var)
po::typed_value< bool > * po_switch()
bool CheckEventSize(size_t has, const char *name, size_t size)
void HandleRequest(const bs::error_code &error)
bool Has(const std::string &var)
void SetSite(const string &site)
void Update(const vector< float > &temp)
void AddOptions(const po::options_description &opt, bool visible=true)
void SetInterval(uint16_t i)
void SetVerbose(bool b=true)
void SetupConfiguration(Configuration &conf)
Commandline parsing, resource file parsing and database access.
boost::array< char, 4096 > fArray
void Post(const string &post)
virtual void Update(const vector< float > &)
int EvalOptions(Configuration &conf)
po::typed_value< bool > * po_bool(bool def=false)
ConnectionDimPowerSwitch(ba::io_service &ioservice, MessageImp &imp)
void ConnectionEstablished()
int SetVerbosity(const EventImp &evt)
void HandleRead(const boost::system::error_code &err, size_t bytes_received)
Maintains an ansynchronous TCP/IP client connection.
boost::asio::deadline_timer fKeepAlive
int SetDebugRx(const EventImp &evt)
bool DoParse(int argc, const char **argv, const std::function< void()> &func=std::function< void()>())
int main(int argc, const char *argv[])
static const uint16_t kMaxAddr
ConnectionPowerSwitch(ba::io_service &ioservice, MessageImp &imp)
virtual size_t GetSize() const