Subversion Repositories HomeAutomation

Rev

Rev 1633 | Rev 1644 | 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.  
  31. #include "can/Message.h"
  32.  
  33. namespace atom {
  34. namespace control {
  35.    
  36. Manager::Pointer Manager::instance_;
  37.  
  38. Manager::Manager() : broker::Subscriber(false), LOG("control::Manager")
  39. {
  40.     Node::SetupStateMachine();
  41.    
  42.     this->active_programming_node_id_ = 0;
  43.    
  44.     // Nyquist–Shannon sampling theorem state that we need to double the time, modules send every 10 seconds
  45.     this->timer_id_ = timer::Manager::Instance()->Set(20000, true);
  46. }
  47.  
  48. Manager::~Manager()
  49. {
  50. }
  51.  
  52. Manager::Pointer Manager::Instance()
  53. {
  54.     return Manager::instance_;
  55. }
  56.  
  57. void Manager::Create()
  58. {
  59.     Manager::instance_ = Manager::Pointer(new Manager());
  60. }
  61.  
  62. void Manager::Delete()
  63. {
  64.     Manager::instance_.reset();
  65. }
  66.  
  67. void Manager::ConnectSlots(const SignalOnNodeChange::slot_type& signal_on_node_change_, const SignalOnModuleChange::slot_type& slot_on_module_change, const SignalOnModuleMessage::slot_type& slot_on_module_message)
  68. {
  69.     this->signal_on_node_change_.connect(signal_on_node_change_);
  70.     this->signal_on_module_change_.connect(slot_on_module_change);
  71.     this->signal_on_module_message_.connect(slot_on_module_message);
  72. }
  73.  
  74. void Manager::SlotOnTimeoutHandler(timer::TimerId timer_id, bool repeat)
  75. {
  76.     if (timer_id != this->timer_id_)
  77.     {
  78.         return;
  79.     }
  80.    
  81.     for (NodeList::iterator it = this->nodes_.begin(); it != this->nodes_.end(); it++)
  82.     {
  83.         if (!it->second->CheckTimeout())
  84.         {
  85.             LOG.Info("Node " + common::ToHex(it->second->GetId()) + " has not sent anything in a long time, setting offline.");
  86.             this->RemoveModules(it->second->GetId());
  87.            
  88.             storage::Manager::Instance()->FlushStore("NodeList");
  89.             storage::Manager::Instance()->FlushStore("ModuleList");
  90.         }
  91.     }
  92. }
  93.  
  94. void Manager::SlotOnMessageHandler(broker::Message::Pointer message)
  95. {
  96.     if (message->GetType() == broker::Message::CAN_MESSAGE)
  97.     {
  98.         //LOG.Debug("Message received");
  99.         can::Message* payload = static_cast<can::Message*>(message->GetPayload().get());
  100.         Node::Pointer node;
  101.        
  102.         if (payload->GetClassName() == "nmt")
  103.         {
  104.             if (payload->GetCommandName() == "Bios_Start")
  105.             {
  106.                 node = this->GetNode(boost::lexical_cast<unsigned int>(payload->GetVariables()["HardwareId"]));
  107.                 node->Trigger(Node::EVENT_BIOS_START, payload->GetVariables());
  108.             }
  109.             else if (payload->GetCommandName() == "App_Start")
  110.             {
  111.                 node = this->GetNode(boost::lexical_cast<unsigned int>(payload->GetVariables()["HardwareId"]));
  112.                 node->Trigger(Node::EVENT_APP_START, payload->GetVariables());
  113.             }
  114.             else if (payload->GetCommandName() == "Heartbeat")
  115.             {
  116.                 node = this->GetNode(boost::lexical_cast<unsigned int>(payload->GetVariables()["HardwareId"]));
  117.                 node->Trigger(Node::EVENT_HEARTBEAT, payload->GetVariables());
  118.             }
  119.             else if (payload->GetCommandName() == "Pgm_Ack")
  120.             {
  121.                 node = this->GetNode(this->active_programming_node_id_);
  122.                 node->Trigger(Node::EVENT_PGM_ACK, payload->GetVariables());
  123.             }
  124.             else if (payload->GetCommandName() == "Pgm_Nack")
  125.             {
  126.                 node = this->GetNode(this->active_programming_node_id_);
  127.                 node->Trigger(Node::EVENT_PGM_NACK, payload->GetVariables());
  128.             }
  129.         }
  130.         else if (payload->GetDirectionName() == "From_Owner")
  131.         {
  132.             Module::Pointer module = this->GetModule(boost::lexical_cast<unsigned int>(payload->GetId()), payload->GetModuleName(), payload->GetClassName());
  133.            
  134.             if (payload->GetCommandName() == "List")
  135.             {
  136.                 node = this->GetNode(boost::lexical_cast<unsigned int>(payload->GetVariables()["HardwareId"]));
  137.                 node->ResetTimeout();
  138.                
  139.                 module->SetNodeId(node->GetId());
  140.                
  141.                 if (this->GetNumberOfModules(node->GetId()) == boost::lexical_cast<unsigned int>(payload->GetVariables()["NumberOfModules"]))
  142.                 {
  143.                     node->Trigger(Node::EVENT_LIST_DONE, payload->GetVariables());
  144.                 }
  145.                
  146.                 LOG.Info("Module " + module->GetFullId() + " is available on node " + common::ToHex(node->GetId()) + ".");
  147.                 this->signal_on_module_change_(module->GetFullId(), true);
  148.             }
  149.             else
  150.             {
  151.                 node = this->GetNode(module->GetNodeId());
  152.                 node->ResetTimeout();
  153.                
  154.                 this->signal_on_module_message_(module->GetFullId(), payload->GetCommandName(), payload->GetVariables());
  155.             }
  156.         }
  157.     }
  158. }
  159.  
  160. void Manager::SlotOnNewState(Node::Id node_id, Node::State current_state, Node::State target_state)
  161. {
  162.     if (target_state != Node::STATE_NORM_INITIALIZED)
  163.     {
  164.         this->RemoveModules(node_id);
  165.     }
  166.    
  167.     if (target_state == Node::STATE_BPGM_OFFLINE || target_state == Node::STATE_APGM_OFFLINE)
  168.     {
  169.         this->active_programming_node_id_ = node_id;
  170.     }
  171.     else if (target_state == Node::STATE_NORM_OFFLINE)
  172.     {
  173.         this->active_programming_node_id_ = 0;
  174.     }
  175. }
  176.  
  177. void Manager::SendMessageHandler(std::string full_id, std::string command, common::StringMap variables)
  178. {
  179.     ModuleList::iterator it = this->modules_.find(full_id);
  180.    
  181.     if (it == this->modules_.end())
  182.     {
  183.         LOG.Warning("Can not send message to " + full_id + ", it is not available");
  184.         return;
  185.     }
  186.    
  187.     try
  188.     {
  189.         can::Message* payload = new can::Message(it->second->GetClassName(), "To_Owner", it->second->GetName(), it->second->GetId(), command);
  190.         payload->SetVariables(variables);
  191.        
  192.         broker::Manager::Instance()->Post(broker::Message::Pointer(new broker::Message(broker::Message::CAN_MESSAGE, broker::Message::PayloadPointer(payload), this)));
  193.         //LOG.Debug("Command " + command + " sent to " + it->second->GetName());
  194.     }
  195.     catch (std::runtime_error& e)
  196.     {
  197.         LOG.Error("Failed to send message, " + std::string(e.what()));
  198.     }
  199. }
  200.  
  201. void Manager::SendMessage(std::string full_id, std::string command, common::StringMap variables)
  202. {
  203.     this->io_service_.post(boost::bind(&Manager::SendMessageHandler, this, full_id, command, variables));
  204. }
  205.  
  206. bool Manager::IsModuleAvailable(std::string full_id)
  207. {
  208.     return this->modules_.find(full_id) != this->modules_.end();
  209. }
  210.  
  211. bool Manager::ProgramNode(Node::Id node_id, bool is_bios, std::string filename)
  212. {
  213.     NodeList::iterator it = this->nodes_.find(node_id);
  214.    
  215.     if (it == this->nodes_.end())
  216.     {
  217.         LOG.Error("Could not find node " +  common::ToHex(node_id));
  218.         return false;
  219.     }
  220.    
  221.     Code::Pointer code = Code::Pointer(new Code());
  222.     if (!code->LoadIntelHexFile(filename))
  223.     {
  224.         LOG.Error("Failed to parse " + filename);
  225.         return false;
  226.     }
  227.    
  228.     if (is_bios)
  229.     {
  230.         LOG.Debug("is_bios true");
  231.         it->second->ProgramBios(code);
  232.     }
  233.     else
  234.     {
  235.         LOG.Debug("is_bios false");
  236.         it->second->ProgramApplication(code);
  237.     }
  238.    
  239.     return true;
  240. }
  241.  
  242. Node::Pointer Manager::GetNode(Node::Id node_id)
  243. {
  244.     Node::Pointer node;
  245.     NodeList::iterator it = this->nodes_.find(node_id);
  246.    
  247.     if (it == this->nodes_.end())
  248.     {
  249.         node = Node::Pointer(new Node(node_id));
  250.         node->ConnectSlots(Node::SignalOnNewState::slot_type(&Manager::SlotOnNewState, this, _1, _2, _3).track(this->tracker_));
  251.         this->nodes_[node_id] = node;
  252.     }
  253.     else
  254.     {
  255.         node = it->second;
  256.     }
  257.    
  258.     return node;
  259. }
  260.  
  261. Module::Pointer Manager::GetModule(Module::Id module_id, std::string module_name, std::string class_name)
  262. {
  263.     Module::Pointer module;
  264.     ModuleList::iterator it = this->modules_.find(Module::MakeFullId(module_id, module_name));
  265.    
  266.     if (it == this->modules_.end())
  267.     {
  268.         module = Module::Pointer(new Module(module_id, module_name, class_name));
  269.         this->modules_[module->GetFullId()] = module;
  270.     }
  271.     else
  272.     {
  273.         module = it->second;
  274.     }
  275.    
  276.     return module;
  277. }
  278.  
  279. void Manager::RemoveModules(Node::Id node_id)
  280. {
  281.     for (ModuleList::iterator it = this->modules_.begin(); it != this->modules_.end(); it++)
  282.     {
  283.         if (it->second->GetNodeId() == node_id)
  284.         {
  285.             LOG.Info("Module " + it->second->GetFullId() + " is unavailable.");
  286.             this->signal_on_module_change_(it->second->GetFullId(), false);
  287.            
  288.             this->modules_.erase(it);
  289.         }
  290.     }
  291. }
  292.  
  293. unsigned int Manager::GetNumberOfModules(Node::Id node_id)
  294. {
  295.     unsigned int number_of_modules = 0;
  296.    
  297.     for (ModuleList::iterator it = this->modules_.begin(); it != this->modules_.end(); it++)
  298.     {
  299.         if (it->second->GetNodeId() == node_id)
  300.         {
  301.             number_of_modules++;
  302.         }
  303.     }
  304.    
  305.     return number_of_modules;
  306. }
  307.  
  308. }; // namespace control
  309. }; // namespace atom
  310.