Subversion Repositories HomeAutomation

Rev

Rev 1916 | Rev 2082 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | SVN | RSS feed

  1. /*
  2.  *
  3.  *  Copyright (C) 2010  Mattias Runge
  4.  *
  5.  *  This program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2 of the License, or
  8.  *  (at your option) any later version.
  9.  *
  10.  *  This program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  *  GNU General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU General Public License along
  16.  *  with this program; if not, write to the Free Software Foundation, Inc.,
  17.  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  18.  *
  19.  */
  20.  
  21. #include "Manager.h"
  22.  
  23. #include <boost/lexical_cast.hpp>
  24.  
  25. #include "broker/Manager.h"
  26. #include "broker/Message.h"
  27. #include "common/common.h"
  28. #include "timer/Manager.h"
  29. #include "storage/Manager.h"
  30. #include "common/log.h"
  31.  
  32. #include "can/Message.h"
  33.  
  34. namespace atom {
  35. namespace control {
  36.    
  37. Manager::Pointer Manager::instance_;
  38.  
  39. static const std::string log_module_ = "control::manager";
  40.  
  41. Manager::Manager() : broker::Subscriber(false)
  42. {
  43.   LOG_DEBUG_ENTER;
  44.  
  45.   Node::SetupStateMachine();
  46.  
  47.   this->active_programming_node_id_ = "";
  48.  
  49.   // Nyquist–Shannon sampling theorem state that we need to double the time, modules send every 10 seconds
  50.   this->timer_id_ = timer::Manager::Instance()->SetTimer(20000, true);
  51.  
  52.   LOG_DEBUG_EXIT;
  53. }
  54.  
  55. Manager::~Manager()
  56. {
  57.   LOG_DEBUG_ENTER;
  58.   LOG_DEBUG_EXIT;
  59. }
  60.  
  61. Manager::Pointer Manager::Instance()
  62. {
  63.   LOG_DEBUG_ENTER;
  64.   LOG_DEBUG_EXIT;
  65.  
  66.   return Manager::instance_;
  67. }
  68.  
  69. void Manager::Create()
  70. {
  71.   LOG_DEBUG_ENTER;
  72.  
  73.   Manager::instance_ = Manager::Pointer(new Manager());
  74.  
  75.   LOG_DEBUG_EXIT;
  76. }
  77.  
  78. void Manager::Delete()
  79. {
  80.   LOG_DEBUG_ENTER;
  81.  
  82.   Manager::instance_.reset();
  83.  
  84.   LOG_DEBUG_EXIT;
  85. }
  86.  
  87. void Manager::ConnectSlotNode(const SignalOnNodeChange::slot_type& signal_on_node_change_)
  88. {
  89.   LOG_DEBUG_ENTER;
  90.  
  91.   this->signal_on_node_change_.connect(signal_on_node_change_);
  92.  
  93.   LOG_DEBUG_EXIT;
  94. }
  95.  
  96. void Manager::ConnectSlotModule(const SignalOnModuleChange::slot_type& slot_on_module_change)
  97. {
  98.   LOG_DEBUG_ENTER;
  99.  
  100.   this->signal_on_module_change_.connect(slot_on_module_change);
  101.  
  102.   LOG_DEBUG_EXIT;
  103. }
  104.  
  105. void Manager::ConnectSlotModule(const SignalOnModuleMessage::slot_type& slot_on_module_message)
  106. {
  107.   LOG_DEBUG_ENTER;
  108.  
  109.   this->signal_on_module_message_.connect(slot_on_module_message);
  110.  
  111.   LOG_DEBUG_EXIT;
  112. }
  113.  
  114. void Manager::SlotOnTimeoutHandler(timer::TimerId timer_id, bool repeat)
  115. {
  116.   LOG_DEBUG_ENTER;
  117.  
  118.   if (timer_id != this->timer_id_)
  119.   {
  120.     return;
  121.   }
  122.  
  123.   for (NodeList::iterator it = this->nodes_.begin(); it != this->nodes_.end(); it++)
  124.   {
  125.     if (!it->second->CheckTimeout())
  126.     {
  127.       log::Info(log_module_, "Node %s has not sent anything in a long time, setting offline.", it->second->GetId().c_str());
  128.      
  129.       this->RemoveModules(it->second->GetId());
  130.      
  131.       storage::Manager::Instance()->FlushStore("NodeList");
  132.       storage::Manager::Instance()->FlushStore("ModuleList");
  133.     }
  134.   }
  135.  
  136.   LOG_DEBUG_EXIT;
  137. }
  138.  
  139. void Manager::SlotOnMessageHandler(broker::Message::Pointer message)
  140. {
  141.   LOG_DEBUG_ENTER;
  142.  
  143.   if (message->GetType() == broker::Message::CAN_MESSAGE)
  144.   {
  145.     //LOG.Debug("Message received");
  146.     can::Message* payload = static_cast<can::Message*>(message->GetPayload().get());
  147.     Node::Pointer node;
  148.    
  149.     if (payload->GetClassName() == "nmt")
  150.     {
  151.       if (payload->GetCommandName() == "Bios_Start")
  152.       {
  153.         node = this->GetNode(common::ToHex(boost::lexical_cast<unsigned int>(payload->GetVariables()["HardwareId"])));
  154.         node->Trigger(Node::EVENT_BIOS_START, payload->GetVariables());
  155.       }
  156.       else if (payload->GetCommandName() == "App_Start")
  157.       {
  158.         node = this->GetNode(common::ToHex(boost::lexical_cast<unsigned int>(payload->GetVariables()["HardwareId"])));
  159.         node->Trigger(Node::EVENT_APP_START, payload->GetVariables());
  160.       }
  161.       else if (payload->GetCommandName() == "Heartbeat")
  162.       {
  163.         node = this->GetNode(common::ToHex(boost::lexical_cast<unsigned int>(payload->GetVariables()["HardwareId"])));
  164.         node->Trigger(Node::EVENT_HEARTBEAT, payload->GetVariables());
  165.       }
  166.       else if (payload->GetCommandName() == "Pgm_Ack")
  167.       {
  168.         node = this->GetNode(this->active_programming_node_id_);
  169.         node->Trigger(Node::EVENT_PGM_ACK, payload->GetVariables());
  170.       }
  171.       else if (payload->GetCommandName() == "Pgm_Nack")
  172.       {
  173.         node = this->GetNode(this->active_programming_node_id_);
  174.         node->Trigger(Node::EVENT_PGM_NACK, payload->GetVariables());
  175.       }
  176.     }
  177.     else if (payload->GetDirectionName() == "From_Owner")
  178.     {
  179.       Module::Pointer module = this->GetModule(boost::lexical_cast<unsigned int>(payload->GetId()), payload->GetModuleName(), payload->GetClassName());
  180.      
  181.       if (payload->GetCommandName() == "List")
  182.       {
  183.         node = this->GetNode(common::ToHex(boost::lexical_cast<unsigned int>(payload->GetVariables()["HardwareId"])));
  184.         node->ResetTimeout();
  185.        
  186.         module->SetNodeId(node->GetId());
  187.        
  188.         if (this->GetNumberOfModules(node->GetId()) == boost::lexical_cast<unsigned int>(payload->GetVariables()["NumberOfModules"]))
  189.         {
  190.           node->Trigger(Node::EVENT_LIST_DONE, payload->GetVariables());
  191.         }
  192.        
  193.         log::Info(log_module_, "Module %s is available on node %s.", module->GetFullId().c_str(), node->GetId().c_str());
  194.         this->signal_on_module_change_(module->GetFullId(), true);
  195.       }
  196.       else if (module->GetNodeId() != "")
  197.       {
  198.         node = this->GetNode(module->GetNodeId());
  199.         node->ResetTimeout();
  200.        
  201.         this->signal_on_module_message_(module->GetFullId(), payload->GetCommandName(), payload->GetVariables());
  202.       }
  203.     }
  204.   }
  205.  
  206.   LOG_DEBUG_EXIT;
  207. }
  208.  
  209. void Manager::SlotOnNewState(Node::Id node_id, Node::State current_state, Node::State target_state)
  210. {
  211.   LOG_DEBUG_ENTER;
  212.  
  213.   if (target_state != Node::STATE_NORM_INITIALIZED)
  214.   {
  215.     this->RemoveModules(node_id);
  216.   }
  217.  
  218.   if (current_state != target_state)
  219.   {
  220.     this->signal_on_node_change_(node_id, (target_state == Node::STATE_NORM_INITIALIZED || target_state == Node::STATE_NORM_LIST || target_state == Node::STATE_NORM_ONLINE));
  221.   }
  222.  
  223.   if (target_state == Node::STATE_BPGM_OFFLINE || target_state == Node::STATE_APGM_OFFLINE)
  224.   {
  225.     this->active_programming_node_id_ = node_id;
  226.   }
  227.   else if (target_state == Node::STATE_NORM_OFFLINE)
  228.   {
  229.     this->active_programming_node_id_ = "";
  230.   }
  231.    
  232.   LOG_DEBUG_EXIT;
  233. }
  234.  
  235. void Manager::SendMessageHandler(std::string full_id, std::string command, common::StringMap variables)
  236. {
  237.   LOG_DEBUG_ENTER;
  238.  
  239.   ModuleList::iterator it = this->modules_.find(full_id);
  240.  
  241.   if (it == this->modules_.end())
  242.   {
  243.     log::Warning(log_module_, "Can not send message to %s , it is not available.", full_id.c_str());
  244.     return;
  245.   }
  246.  
  247.   try
  248.   {
  249.     can::Message* payload = new can::Message(it->second->GetClassName(), "To_Owner", it->second->GetName(), it->second->GetId(), command);
  250.     payload->SetVariables(variables);
  251.    
  252.     broker::Manager::Instance()->Post(broker::Message::Pointer(new broker::Message(broker::Message::CAN_MESSAGE, broker::Message::PayloadPointer(payload), this)));
  253.     //LOG.Debug("Command " + command + " sent to " + it->second->GetName());
  254.   }
  255.   catch (std::runtime_error& e)
  256.   {
  257.     log::Error(log_module_, "Failed to send message, %s", e.what());
  258.   }
  259.  
  260.   LOG_DEBUG_EXIT;
  261. }
  262.  
  263. void Manager::SendMessage(std::string full_id, std::string command, common::StringMap variables)
  264. {
  265.   LOG_DEBUG_ENTER;
  266.  
  267.   this->io_service_.post(boost::bind(&Manager::SendMessageHandler, this, full_id, command, variables));
  268.  
  269.   LOG_DEBUG_EXIT;
  270. }
  271.  
  272. common::StringList Manager::GetAvailableModules()
  273. {
  274.   LOG_DEBUG_ENTER;
  275.  
  276.   common::StringList available_modules;
  277.  
  278.   for (ModuleList::iterator it = this->modules_.begin(); it != this->modules_.end(); it++)
  279.   {
  280.     available_modules.push_back(it->first);
  281.   }
  282.  
  283.   LOG_DEBUG_EXIT;
  284.  
  285.   return available_modules;
  286. }
  287.  
  288. common::StringList Manager::GetAvailableNodes()
  289. {
  290.   LOG_DEBUG_ENTER;
  291.  
  292.   common::StringList available_nodes;
  293.  
  294.   for (NodeList::iterator it = this->nodes_.begin(); it != this->nodes_.end(); it++)
  295.   {
  296.     std::string node = it->first;
  297.  
  298.     for (ModuleList::iterator it2 = this->modules_.begin(); it2 != this->modules_.end(); it2++)
  299.     {
  300.       if (it2->second->GetNodeId() == it->first)
  301.       {
  302.         node += "," + it2->first;
  303.       }
  304.     }
  305.    
  306.     available_nodes.push_back(node);
  307.   }
  308.  
  309.   LOG_DEBUG_EXIT;
  310.  
  311.   return available_nodes;
  312. }
  313.  
  314. bool Manager::ResetNode(Node::Id node_id)
  315. {
  316.   LOG_DEBUG_ENTER;
  317.  
  318.   NodeList::iterator it = this->nodes_.find(node_id);
  319.  
  320.   if (it == this->nodes_.end())
  321.   {
  322.       log::Error(log_module_, "Could not find node %s.", node_id.c_str());
  323.       return false;
  324.   }
  325.  
  326.   it->second->Reset();
  327.  
  328.   LOG_DEBUG_EXIT;
  329.  
  330.   return true;
  331. }
  332.  
  333. bool Manager::ProgramNode(Node::Id node_id, bool is_bios, std::string filename)
  334. {
  335.   LOG_DEBUG_ENTER;
  336.  
  337.   NodeList::iterator it = this->nodes_.find(node_id);
  338.  
  339.   if (it == this->nodes_.end())
  340.   {
  341.     log::Error(log_module_, "Could not find node %s.", node_id.c_str());
  342.     return false;
  343.   }
  344.  
  345.   Code::Pointer code = Code::Pointer(new Code());
  346.   if (!code->LoadIntelHexFile(filename))
  347.   {
  348.     log::Error(log_module_, "Could not parse %s.", filename.c_str());
  349.     return false;
  350.   }
  351.  
  352.   if (is_bios)
  353.   {
  354.     log::Debug(log_module_, "is_bios true");
  355.     it->second->ProgramBios(code);
  356.   }
  357.   else
  358.   {
  359.     log::Debug(log_module_, "is_bios false");
  360.     it->second->ProgramApplication(code);
  361.   }
  362.  
  363.   LOG_DEBUG_EXIT;
  364.  
  365.   return true;
  366. }
  367.  
  368. /* Program node with hexdata as argument */
  369. bool Manager::ProgramNodeHex(Node::Id node_id, bool is_bios, std::string hex_data)
  370. {
  371.   LOG_DEBUG_ENTER;
  372.  
  373.   NodeList::iterator it = this->nodes_.find(node_id);
  374.  
  375.   if (it == this->nodes_.end())
  376.   {
  377.     log::Error(log_module_, "Could not find node %s.", node_id.c_str());
  378.     return false;
  379.   }
  380.  
  381.   Code::Pointer code = Code::Pointer(new Code());
  382.  
  383.   if (!code->ParseIntelHex(hex_data))
  384.   {
  385.     log::Error(log_module_, "Could not parse hexdata %s.", hex_data.c_str());
  386.     return false;
  387.   }
  388.  
  389.   if (is_bios)
  390.   {
  391.     log::Debug(log_module_, "is_bios true");
  392.     it->second->ProgramBios(code);
  393.   }
  394.   else
  395.   {
  396.     log::Debug(log_module_, "is_bios false");
  397.     it->second->ProgramApplication(code);
  398.   }
  399.  
  400.   LOG_DEBUG_EXIT;
  401.  
  402.   return true;
  403. }
  404.  
  405. Node::Information Manager::GetNodeInformation(Node::Id node_id)
  406. {
  407.   LOG_DEBUG_ENTER;
  408.  
  409.   NodeList::iterator it = this->nodes_.find(node_id);
  410.  
  411.   if (it == this->nodes_.end())
  412.   {
  413.     throw std::runtime_error("No such node exists, " + node_id);
  414.   }
  415.  
  416.   LOG_DEBUG_EXIT;
  417.  
  418.   return it->second->GetInformation();
  419. }
  420.  
  421. Node::Pointer Manager::GetNode(Node::Id node_id)
  422. {
  423.   LOG_DEBUG_ENTER;
  424.  
  425.   Node::Pointer node;
  426.   NodeList::iterator it = this->nodes_.find(node_id);
  427.  
  428.   if (it == this->nodes_.end())
  429.   {
  430.     node = Node::Pointer(new Node(node_id));
  431.     node->ConnectSlots(Node::SignalOnNewState::slot_type(&Manager::SlotOnNewState, this, _1, _2, _3).track(this->tracker_));
  432.     this->nodes_[node_id] = node;
  433.   }
  434.   else
  435.   {
  436.     node = it->second;
  437.   }
  438.  
  439.   LOG_DEBUG_EXIT;
  440.  
  441.   return node;
  442. }
  443.  
  444. Module::Pointer Manager::GetModule(Module::Id module_id, std::string module_name, std::string class_name)
  445. {
  446.   LOG_DEBUG_ENTER;
  447.  
  448.   Module::Pointer module;
  449.   ModuleList::iterator it = this->modules_.find(Module::MakeFullId(module_id, module_name));
  450.  
  451.   if (it == this->modules_.end())
  452.   {
  453.     module = Module::Pointer(new Module(module_id, module_name, class_name));
  454.     this->modules_[module->GetFullId()] = module;
  455.   }
  456.   else
  457.   {
  458.     module = it->second;
  459.   }
  460.  
  461.   LOG_DEBUG_EXIT;
  462.  
  463.   return module;
  464. }
  465.  
  466. void Manager::RemoveModules(Node::Id node_id)
  467. {
  468.   LOG_DEBUG_ENTER;
  469.  
  470.   for (ModuleList::iterator it = this->modules_.begin(); it != this->modules_.end(); it++)
  471.   {
  472.     if (it->second->GetNodeId() == node_id)
  473.     {
  474.       log::Info(log_module_, "Module %s is unavailable.", it->second->GetFullId().c_str());
  475.       this->signal_on_module_change_(it->second->GetFullId(), false);
  476.      
  477.       this->modules_.erase(it);
  478.       break;
  479.     }
  480.   }
  481.    
  482.   LOG_DEBUG_EXIT;
  483. }
  484.  
  485. unsigned int Manager::GetNumberOfModules(Node::Id node_id)
  486. {
  487.   LOG_DEBUG_ENTER;
  488.  
  489.   unsigned int number_of_modules = 0;
  490.  
  491.   for (ModuleList::iterator it = this->modules_.begin(); it != this->modules_.end(); it++)
  492.   {
  493.     if (it->second->GetNodeId() == node_id)
  494.     {
  495.       number_of_modules++;
  496.     }
  497.   }
  498.  
  499.   LOG_DEBUG_EXIT;
  500.  
  501.   return number_of_modules;
  502. }
  503.  
  504. }; // namespace control
  505. }; // namespace atom
  506.