Subversion Repositories HomeAutomation

Rev

Rev 2082 | 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.       else
  204.       {
  205.         log::Info(log_module_, "Nothing found, id=%d, modulename=%s, classname=%s", payload->GetId(), payload->GetModuleName().data(), payload->GetClassName().data());
  206.       }
  207.     }
  208.   }
  209.  
  210.   LOG_DEBUG_EXIT;
  211. }
  212.  
  213. void Manager::SlotOnNewState(Node::Id node_id, Node::State current_state, Node::State target_state)
  214. {
  215.   LOG_DEBUG_ENTER;
  216.  
  217.   if (target_state != Node::STATE_NORM_INITIALIZED)
  218.   {
  219.     this->RemoveModules(node_id);
  220.   }
  221.  
  222.   if (current_state != target_state)
  223.   {
  224.     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));
  225.   }
  226.  
  227.   if (target_state == Node::STATE_BPGM_OFFLINE || target_state == Node::STATE_APGM_OFFLINE)
  228.   {
  229.     this->active_programming_node_id_ = node_id;
  230.   }
  231.   else if (target_state == Node::STATE_NORM_OFFLINE)
  232.   {
  233.     this->active_programming_node_id_ = "";
  234.   }
  235.  
  236.   LOG_DEBUG_EXIT;
  237. }
  238.  
  239. void Manager::SendMessageHandler(std::string full_id, std::string command, common::StringMap variables)
  240. {
  241.   LOG_DEBUG_ENTER;
  242.  
  243.   ModuleList::iterator it = this->modules_.find(full_id);
  244.  
  245.   if (it == this->modules_.end())
  246.   {
  247.     log::Warning(log_module_, "Can not send message to %s , it is not available.", full_id.c_str());
  248.     return;
  249.   }
  250.  
  251.   try
  252.   {
  253.     can::Message* payload = new can::Message(it->second->GetClassName(), "To_Owner", it->second->GetName(), it->second->GetId(), command);
  254.     payload->SetVariables(variables);
  255.  
  256.     broker::Manager::Instance()->Post(broker::Message::Pointer(new broker::Message(broker::Message::CAN_MESSAGE, broker::Message::PayloadPointer(payload), this)));
  257.     //LOG.Debug("Command " + command + " sent to " + it->second->GetName());
  258.   }
  259.   catch (std::runtime_error& e)
  260.   {
  261.     log::Error(log_module_, "Failed to send message, %s", e.what());
  262.   }
  263.  
  264.   LOG_DEBUG_EXIT;
  265. }
  266.  
  267. void Manager::SendMessage(std::string full_id, std::string command, common::StringMap variables)
  268. {
  269.   LOG_DEBUG_ENTER;
  270.  
  271.   this->io_service_.post(boost::bind(&Manager::SendMessageHandler, this, full_id, command, variables));
  272.  
  273.   LOG_DEBUG_EXIT;
  274. }
  275.  
  276. common::StringList Manager::GetAvailableModules()
  277. {
  278.   LOG_DEBUG_ENTER;
  279.  
  280.   common::StringList available_modules;
  281.  
  282.   for (ModuleList::iterator it = this->modules_.begin(); it != this->modules_.end(); it++)
  283.   {
  284.     available_modules.push_back(it->first);
  285.   }
  286.  
  287.   LOG_DEBUG_EXIT;
  288.  
  289.   return available_modules;
  290. }
  291.  
  292. common::StringList Manager::GetAvailableNodes()
  293. {
  294.   LOG_DEBUG_ENTER;
  295.  
  296.   common::StringList available_nodes;
  297.  
  298.   for (NodeList::iterator it = this->nodes_.begin(); it != this->nodes_.end(); it++)
  299.   {
  300.     std::string node = it->first;
  301.  
  302.     for (ModuleList::iterator it2 = this->modules_.begin(); it2 != this->modules_.end(); it2++)
  303.     {
  304.       if (it2->second->GetNodeId() == it->first)
  305.       {
  306.         node += "," + it2->first;
  307.       }
  308.     }
  309.  
  310.     available_nodes.push_back(node);
  311.   }
  312.  
  313.   LOG_DEBUG_EXIT;
  314.  
  315.   return available_nodes;
  316. }
  317.  
  318. bool Manager::ResetNode(Node::Id node_id)
  319. {
  320.   LOG_DEBUG_ENTER;
  321.  
  322.   NodeList::iterator it = this->nodes_.find(node_id);
  323.  
  324.   if (it == this->nodes_.end())
  325.   {
  326.       log::Error(log_module_, "Could not find node %s.", node_id.c_str());
  327.       return false;
  328.   }
  329.  
  330.   it->second->Reset();
  331.  
  332.   LOG_DEBUG_EXIT;
  333.  
  334.   return true;
  335. }
  336.  
  337. unsigned int Manager::GetProgramProgress(Node::Id node_id)
  338. {
  339.   LOG_DEBUG_ENTER;
  340.  
  341.   NodeList::iterator it = this->nodes_.find(node_id);
  342.  
  343.   if (it == this->nodes_.end())
  344.   {
  345.     log::Error(log_module_, "Could not find node %s.", node_id.c_str());
  346.     return 0;
  347.   }
  348.  
  349.   return it->second->GetProgramProgress();
  350.  
  351.   LOG_DEBUG_EXIT;
  352. }
  353.  
  354. bool Manager::ProgramNode(Node::Id node_id, bool is_bios, std::string filename)
  355. {
  356.   LOG_DEBUG_ENTER;
  357.  
  358.   NodeList::iterator it = this->nodes_.find(node_id);
  359.  
  360.   if (it == this->nodes_.end())
  361.   {
  362.     log::Error(log_module_, "Could not find node %s.", node_id.c_str());
  363.     return false;
  364.   }
  365.  
  366.   Code::Pointer code = Code::Pointer(new Code());
  367.   if (!code->LoadIntelHexFile(filename))
  368.   {
  369.     log::Error(log_module_, "Could not parse %s.", filename.c_str());
  370.     return false;
  371.   }
  372.  
  373.   if (is_bios)
  374.   {
  375.     log::Debug(log_module_, "is_bios true");
  376.     it->second->ProgramBios(code);
  377.   }
  378.   else
  379.   {
  380.     log::Debug(log_module_, "is_bios false");
  381.     it->second->ProgramApplication(code);
  382.   }
  383.  
  384.   LOG_DEBUG_EXIT;
  385.  
  386.   return true;
  387. }
  388.  
  389. /* Program node with hexdata as argument */
  390. bool Manager::ProgramNodeHex(Node::Id node_id, bool is_bios, std::string hex_data)
  391. {
  392.   LOG_DEBUG_ENTER;
  393.  
  394.   NodeList::iterator it = this->nodes_.find(node_id);
  395.  
  396.   if (it == this->nodes_.end())
  397.   {
  398.     log::Error(log_module_, "Could not find node %s.", node_id.c_str());
  399.     return false;
  400.   }
  401.  
  402.   Code::Pointer code = Code::Pointer(new Code());
  403.  
  404.   if (!code->ParseIntelHex(hex_data))
  405.   {
  406.     log::Error(log_module_, "Could not parse hexdata %s.", hex_data.c_str());
  407.     return false;
  408.   }
  409.  
  410.   if (is_bios)
  411.   {
  412.     log::Debug(log_module_, "is_bios true");
  413.     it->second->ProgramBios(code);
  414.   }
  415.   else
  416.   {
  417.     log::Debug(log_module_, "is_bios false");
  418.     it->second->ProgramApplication(code);
  419.   }
  420.  
  421.   LOG_DEBUG_EXIT;
  422.  
  423.   return true;
  424. }
  425.  
  426. Node::Information Manager::GetNodeInformation(Node::Id node_id)
  427. {
  428.   LOG_DEBUG_ENTER;
  429.  
  430.   NodeList::iterator it = this->nodes_.find(node_id);
  431.  
  432.   if (it == this->nodes_.end())
  433.   {
  434.     throw std::runtime_error("No such node exists, " + node_id);
  435.   }
  436.  
  437.   LOG_DEBUG_EXIT;
  438.  
  439.   return it->second->GetInformation();
  440. }
  441.  
  442. Node::Pointer Manager::GetNode(Node::Id node_id)
  443. {
  444.   LOG_DEBUG_ENTER;
  445.  
  446.   Node::Pointer node;
  447.   NodeList::iterator it = this->nodes_.find(node_id);
  448.  
  449.   if (it == this->nodes_.end())
  450.   {
  451.     node = Node::Pointer(new Node(node_id));
  452.     node->ConnectSlots(Node::SignalOnNewState::slot_type(&Manager::SlotOnNewState, this, _1, _2, _3).track(this->tracker_));
  453.     this->nodes_[node_id] = node;
  454.   }
  455.   else
  456.   {
  457.     node = it->second;
  458.   }
  459.  
  460.   LOG_DEBUG_EXIT;
  461.  
  462.   return node;
  463. }
  464.  
  465. Module::Pointer Manager::GetModule(Module::Id module_id, std::string module_name, std::string class_name)
  466. {
  467.   LOG_DEBUG_ENTER;
  468.  
  469.   Module::Pointer module;
  470.   ModuleList::iterator it = this->modules_.find(Module::MakeFullId(module_id, module_name));
  471.  
  472.   if (it == this->modules_.end())
  473.   {
  474.     module = Module::Pointer(new Module(module_id, module_name, class_name));
  475.     this->modules_[module->GetFullId()] = module;
  476.   }
  477.   else
  478.   {
  479.     module = it->second;
  480.   }
  481.  
  482.   LOG_DEBUG_EXIT;
  483.  
  484.   return module;
  485. }
  486.  
  487. void Manager::RemoveModules(Node::Id node_id)
  488. {
  489.   LOG_DEBUG_ENTER;
  490.  
  491.   for (ModuleList::iterator it = this->modules_.begin(); it != this->modules_.end(); it++)
  492.   {
  493.     if (it->second->GetNodeId() == node_id)
  494.     {
  495.       log::Info(log_module_, "Module %s is unavailable.", it->second->GetFullId().c_str());
  496.       this->signal_on_module_change_(it->second->GetFullId(), false);
  497.  
  498.       this->modules_.erase(it);
  499.       break;
  500.     }
  501.   }
  502.  
  503.   LOG_DEBUG_EXIT;
  504. }
  505.  
  506. unsigned int Manager::GetNumberOfModules(Node::Id node_id)
  507. {
  508.   LOG_DEBUG_ENTER;
  509.  
  510.   unsigned int number_of_modules = 0;
  511.  
  512.   for (ModuleList::iterator it = this->modules_.begin(); it != this->modules_.end(); it++)
  513.   {
  514.     if (it->second->GetNodeId() == node_id)
  515.     {
  516.       number_of_modules++;
  517.     }
  518.   }
  519.  
  520.   LOG_DEBUG_EXIT;
  521.  
  522.   return number_of_modules;
  523. }
  524.  
  525. }; // namespace control
  526. }; // namespace atom
  527.