battery_diagnostics.cpp
Go to the documentation of this file.
00001 #include "ros/ros.h"
00002 #include "ros/time.h"
00003 #include <vector>
00004 #include "std_msgs/Header.h"
00005 #include "std_msgs/Float32.h"
00006 #include "diagnostic_msgs/DiagnosticStatus.h"
00007 #include "diagnostic_msgs/DiagnosticArray.h"
00008 #include "diagnostic_msgs/KeyValue.h"
00009 #include "smart_battery_msgs/SmartBatteryStatus.h"
00010 #include <stdio.h>
00011 #include <stdlib.h>
00012 #include <unistd.h>
00013 #include <boost/thread.hpp>
00014 #include <boost/lexical_cast.hpp>
00015 
00016 float voltage;
00017 bool sentMail = false;
00018 void voltageCallback(const smart_battery_msgs::SmartBatteryStatus::ConstPtr& msg){
00019   voltage = (msg->voltage);
00020   //todo: add voltage profiler logic - write profile rates in /config
00021 }
00022 
00023 int sendMail(std::string outboundList, std::string sender){
00024   char msg[] = "Hello,\nJust so you know, there is a robot whose battery is low. Please seek this robot and bring it to the lab for charging.\nBest,\nBuilding Wide Intelligence\n\nPS: Please don't email me!";
00025   int retval = -1;
00026   FILE *mailpipe = popen("/usr/lib/sendmail -t", "w");
00027   if(mailpipe != NULL){
00028     std::string to = "To: " + outboundList + "\n";
00029     std::string from = "From: " + sender + "\n";
00030     fputs(to.c_str(), mailpipe);
00031     fputs(from.c_str(), mailpipe);
00032     fputs("Subject: Segbot Low Battery Alert\n", mailpipe);
00033     fwrite(msg, 1, strlen(msg), mailpipe);
00034     fwrite(".\n", 1, 2, mailpipe);
00035     pclose(mailpipe);
00036     retval = 0;
00037   }else {
00038     perror("Failed to invoke sendmail");
00039   }
00040   return retval;
00041 }
00042 
00043 int main(int argc, char **argv){
00044   ros::init(argc, argv, "battery_estimator");
00045   ros::NodeHandle n;
00046   ros::Publisher battery_life_pub = n.advertise<diagnostic_msgs::DiagnosticArray>("diagnostics", 10);
00047   ros::Subscriber voltage_sub = n.subscribe("/battery0", 10, voltageCallback);
00048   ros::Rate loop_rate(1); //1hz
00049   diagnostic_msgs::DiagnosticStatus voltages;
00050   diagnostic_msgs::DiagnosticStatus status;
00051   diagnostic_msgs::DiagnosticArray diagAr;
00052   diagnostic_msgs::KeyValue status_val;
00053   diagnostic_msgs::KeyValue voltages_val;
00054   voltages.hardware_id = "005";
00055   voltages.name = "voltage";
00056   voltages_val.value = voltage;
00057   voltages_val.key = "Current voltage: ";
00058   status.hardware_id = "005";
00059   status.name = "battery_estimator"; //must match what the aggregator config file expects
00060   status_val.key = "battery_value";
00061   status_val.value = "183.0"; //dummy value
00062   std::ostringstream ss;
00063 
00064   while (ros::ok()){
00065     voltages_val.value = boost::lexical_cast<std::string>(voltage);
00066     diagAr.header.stamp = ros::Time::now();
00067     diagAr.header.frame_id = 1;
00068 
00069     if(voltage > 11.0){
00070       status.message = "Battery in good health";
00071       status.level = 0; // 0 = OK
00072       voltages.level = 0;
00073       voltages.message = "Voltage level OK";
00074     }else if(voltage > 10 && voltage < 11){
00075       status.message = "Battery low, return to lab.";
00076       status.level = 1; // WARN
00077       voltages.level = 1;
00078       voltages.message = "Voltage dropping";
00079       if(!sentMail){
00080         //To maintain steady diag readings, run sendmail on thread
00081         bool paramSuccess;
00082         std::string outbound;
00083         paramSuccess = n.getParam("email_alert_outbound", outbound);
00084         std::string send;
00085         paramSuccess &= n.getParam("email_alert_sender", send);
00086         if(!paramSuccess){
00087           std::cout << "Error reading send mail parameters. Check launchfile. Emails not sent." << std::endl;
00088         }else{
00089           boost::thread mailThread(sendMail, outbound, send);
00090         }
00091       }
00092       sentMail = true;
00093     }else if(!voltage){
00094       voltages.message = "No voltage data";
00095       voltages.level = 2;
00096       status.message = "Cannot extrapolate battery charge. No voltage data.";
00097       status.level = 2;
00098     }else{
00099       status.message = "Battery CRITICALLY low, or voltmeter data is inaccurate (or missing). Ensure the volt sensor is connected properly and its publisher relaying data.";
00100       status.level = 2; // CRITICAL
00101       voltages.level = 2;
00102       voltages.message = "ERROR: Ensure accurate volt readings!";
00103     }
00104     //Clearing messages reduces memory overhead, but limits the perception of changes in state in the diagnostics viewer.
00105     status.values.clear();
00106     status.values.push_back(status_val);
00107     voltages.values.clear();
00108     voltages.values.push_back(voltages_val);
00109     diagAr.status.clear();
00110     diagAr.status.push_back(status);
00111     diagAr.status.push_back(voltages);
00112     battery_life_pub.publish(diagAr);
00113     ros::spinOnce();
00114     loop_rate.sleep();
00115   }
00116   return 0;
00117 }


segbot_sensors
Author(s): Piyush Khandelwal
autogenerated on Fri Aug 28 2015 13:03:00