Subversion Repositories HomeAutomation

Rev

Rev 2081 | 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.       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. bool Manager::ProgramNode(Node::Id node_id, bool is_bios, std::string filename)
  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 false;
  347.   }
  348.  
  349.   Code::Pointer code = Code::Pointer(new Code());
  350.   if (!code->LoadIntelHexFile(filename))
  351.   {
  352.     log::Error(log_module_, "Could not parse %s.", filename.c_str());
  353.     return false;
  354.   }
  355.  
  356.   if (is_bios)
  357.   {
  358.     log::Debug(log_module_, "is_bios true");
  359.     it->second->ProgramBios(code);
  360.   }
  361.   else
  362.   {
  363.     log::Debug(log_module_, "is_bios false");
  364.     it->second->ProgramApplication(code);
  365.   }
  366.  
  367.   LOG_DEBUG_EXIT;
  368.  
  369.   return true;
  370. }
  371.  
  372. /* Program node with hexdata as argument */
  373. bool Manager::ProgramNodeHex(Node::Id node_id, bool is_bios, std::string hex_data)
  374. {
  375.   LOG_DEBUG_ENTER;
  376.  
  377.   NodeList::iterator it = this->nodes_.find(node_id);
  378.  
  379.   if (it == this->nodes_.end())
  380.   {
  381.     log::Error(log_module_, "Could not find node %s.", node_id.c_str());
  382.     return false;
  383.   }
  384.  
  385.   Code::Pointer code = Code::Pointer(new Code());
  386.  
  387.   if (!code->ParseIntelHex(hex_data))
  388.   {
  389.     log::Error(log_module_, "Could not parse hexdata %s.", hex_data.c_str());
  390.     return false;
  391.   }
  392.  
  393.   if (is_bios)
  394.   {
  395.     log::Debug(log_module_, "is_bios true");
  396.     it->second->ProgramBios(code);
  397.   }
  398.   else
  399.   {
  400.     log::Debug(log_module_, "is_bios false");
  401.     it->second->ProgramApplication(code);
  402.   }
  403.  
  404.   LOG_DEBUG_EXIT;
  405.  
  406.   return true;
  407. }
  408.  
  409. Node::Information Manager::GetNodeInformation(Node::Id node_id)
  410. {
  411.   LOG_DEBUG_ENTER;
  412.  
  413.   NodeList::iterator it = this->nodes_.find(node_id);
  414.  
  415.   if (it == this->nodes_.end())
  416.   {
  417.     throw std::runtime_error("No such node exists, " + node_id);
  418.   }
  419.  
  420.   LOG_DEBUG_EXIT;
  421.  
  422.   return it->second->GetInformation();
  423. }
  424.  
  425. Node::Pointer Manager::GetNode(Node::Id node_id)
  426. {
  427.   LOG_DEBUG_ENTER;
  428.  
  429.   Node::Pointer node;
  430.   NodeList::iterator it = this->nodes_.find(node_id);
  431.  
  432.   if (it == this->nodes_.end())
  433.   {
  434.     node = Node::Pointer(new Node(node_id));
  435.     node->ConnectSlots(Node::SignalOnNewState::slot_type(&Manager::SlotOnNewState, this, _1, _2, _3).track(this->tracker_));
  436.     this->nodes_[node_id] = node;
  437.   }
  438.   else
  439.   {
  440.     node = it->second;
  441.   }
  442.  
  443.   LOG_DEBUG_EXIT;
  444.  
  445.   return node;
  446. }
  447.  
  448. Module::Pointer Manager::GetModule(Module::Id module_id, std::string module_name, std::string class_name)
  449. {
  450.   LOG_DEBUG_ENTER;
  451.  
  452.   Module::Pointer module;
  453.   ModuleList::iterator it = this->modules_.find(Module::MakeFullId(module_id, module_name));
  454.  
  455.   if (it == this->modules_.end())
  456.   {
  457.     module = Module::Pointer(new Module(module_id, module_name, class_name));
  458.     this->modules_[module->GetFullId()] = module;
  459.   }
  460.   else
  461.   {
  462.     module = it->second;
  463.   }
  464.  
  465.   LOG_DEBUG_EXIT;
  466.  
  467.   return module;
  468. }
  469.  
  470. void Manager::RemoveModules(Node::Id node_id)
  471. {
  472.   LOG_DEBUG_ENTER;
  473.  
  474.   for (ModuleList::iterator it = this->modules_.begin(); it != this->modules_.end(); it++)
  475.   {
  476.     if (it->second->GetNodeId() == node_id)
  477.     {
  478.       log::Info(log_module_, "Module %s is unavailable.", it->second->GetFullId().c_str());
  479.       this->signal_on_module_change_(it->second->GetFullId(), false);
  480.  
  481.       this->modules_.erase(it);
  482.       break;
  483.     }
  484.   }
  485.  
  486.   LOG_DEBUG_EXIT;
  487. }
  488.  
  489. unsigned int Manager::GetNumberOfModules(Node::Id node_id)
  490. {
  491.   LOG_DEBUG_ENTER;
  492.  
  493.   unsigned int number_of_modules = 0;
  494.  
  495.   for (ModuleList::iterator it = this->modules_.begin(); it != this->modules_.end(); it++)
  496.   {
  497.     if (it->second->GetNodeId() == node_id)
  498.     {
  499.       number_of_modules++;
  500.     }
  501.   }
  502.  
  503.   LOG_DEBUG_EXIT;
  504.  
  505.   return number_of_modules;
  506. }
  507.  
  508. }; // namespace control
  509. }; // namespace atom
  510.