Class: AutomateEm::System
- Inherits:
-
Object
- Object
- AutomateEm::System
- Defined in:
- lib/automate-em/core/system.rb,
lib/automate-em/interfaces/html5.rb
Constant Summary collapse
- @@controllers =
controller_id => system instance (0 is the system class)
{0 => self}
- @@logger =
nil
- @@communicator =
- TODO
-
remove the need for communicator.start
AutomateEm::Communicator.new(self)
- @@god_lock =
Mutex.new
- @@socket_server =
nil
Instance Attribute Summary collapse
-
#communicator ⇒ Object
readonly
Returns the value of attribute communicator.
-
#controller ⇒ Object
readonly
Returns the value of attribute controller.
-
#logger ⇒ Object
Returns the value of attribute logger.
-
#modules ⇒ Object
readonly
Returns the value of attribute modules.
Class Method Summary collapse
- .[](system) ⇒ Object
- .communicator ⇒ Object
-
.force_load_file(path) ⇒ Object
Allows for system updates on the fly Dangerous (Could be used to add on the fly interfaces).
-
.logger ⇒ Object
System Logger.
- .logger=(log) ⇒ Object
-
.reload(dep) ⇒ Object
Reloads a dependency live This is the re-load code function (live bug fixing - removing / adding / modifying functions).
-
.start(controller, log_level = Logger::INFO) ⇒ Object
Error thrown means: mark as offline, do not retry and email Return false means: retry and email if a second attempt fails Return true means: all is good! system running.
- .start_websockets ⇒ Object
- .stop(system) ⇒ Object
- .stop_websockets ⇒ Object
Instance Method Summary collapse
-
#[](mod) ⇒ Object
Module accessor.
-
#instance ⇒ Object
For access via communicator.
-
#load(dbSetting, theClass) ⇒ Object
Loads a module into a system.
-
#log_level(level) ⇒ Object
Log level changing on the fly.
-
#start ⇒ Object
The system is ready to go.
-
#stop ⇒ Object
Stops the current control system Loops through the module instances.
Instance Attribute Details
#communicator ⇒ Object (readonly)
Returns the value of attribute communicator.
247 248 249 |
# File 'lib/automate-em/core/system.rb', line 247 def communicator @communicator end |
#controller ⇒ Object (readonly)
Returns the value of attribute controller.
248 249 250 |
# File 'lib/automate-em/core/system.rb', line 248 def controller @controller end |
#logger ⇒ Object
Returns the value of attribute logger.
249 250 251 |
# File 'lib/automate-em/core/system.rb', line 249 def logger @logger end |
#modules ⇒ Object (readonly)
Returns the value of attribute modules.
246 247 248 |
# File 'lib/automate-em/core/system.rb', line 246 def modules @modules end |
Class Method Details
.[](system) ⇒ Object
211 212 213 214 215 216 217 218 219 220 221 222 223 224 |
# File 'lib/automate-em/core/system.rb', line 211 def self.[] (system) if system.is_a?(Symbol) || system.is_a?(String) id = ControlSystem.where('name = ?', system.to_s).pluck(:id).first if id.nil? && system.is_a?(String) system = system.to_i else system = id end end @@god_lock.synchronize { @@controllers[system] } end |
.communicator ⇒ Object
207 208 209 |
# File 'lib/automate-em/core/system.rb', line 207 def self.communicator @@communicator end |
.force_load_file(path) ⇒ Object
Allows for system updates on the fly Dangerous (Could be used to add on the fly interfaces)
186 187 188 189 190 191 192 193 |
# File 'lib/automate-em/core/system.rb', line 186 def self.force_load_file(path) load path if File.exists?(path) && File.extname(path) == '.rb' rescue LoadError => e # load error explicitly handled AutomateEm.print_error(System.logger, e, { :message => "force load of #{path} failed", :level => Logger::ERROR }) end |
.logger ⇒ Object
System Logger
199 200 201 |
# File 'lib/automate-em/core/system.rb', line 199 def self.logger @@logger end |
.logger=(log) ⇒ Object
203 204 205 |
# File 'lib/automate-em/core/system.rb', line 203 def self.logger=(log) @@logger = log end |
.reload(dep) ⇒ Object
Reloads a dependency live This is the re-load code function (live bug fixing - removing / adding / modifying functions)
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 |
# File 'lib/automate-em/core/system.rb', line 143 def self.reload(dep) System.logger.info "reloading dependency: #{dep}" dep = Dependency.find(dep) Modules.load_module(dep) updated = {} dep.devices.select('id').each do |dev| begin inst = DeviceModule.instance_of(dev.id) inst.on_update if (!!!updated[inst]) && inst.respond_to?(:on_update) ensure updated[inst] = true end end updated = {} dep.services.select('id').each do |ser| begin inst = ServiceModule.instance_of(ser.id) inst.on_update if (!!!updated[inst]) && inst.respond_to?(:on_update) ensure updated[inst] = true end end updated = {} dep.logics.select('id').each do |log| begin inst = LogicModule.instance_of(log.id) inst.on_update if (!!!updated[inst]) && inst.respond_to?(:on_update) ensure updated[inst] = true end end ActiveRecord::Base.clear_active_connections! # Clear any unused connections end |
.start(controller, log_level = Logger::INFO) ⇒ Object
Error thrown means: mark as offline, do not retry and email Return false means: retry and email if a second attempt fails Return true means: all is good! system running
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/automate-em/core/system.rb', line 16 def self.start(controller, log_level = Logger::INFO) begin # # Ensure we are dealing with a controller # if controller.is_a? Fixnum controller = ControlSystem.find(controller) elsif controller.is_a? String controller = ControlSystem.where('name = ?', controller).first end if not controller.is_a? ControlSystem raise 'invalid controller identifier' end # # Check if the system is already loaded or loading # @@god_lock.synchronize { if @@controllers[controller.id].present? return true end begin controller.reload(:lock => true) if controller.active return true else controller.active = true end ensure controller.save end } # # Create the system # system = System.new(controller, log_level) # # Load modules here (Producer) # proceed = Atomic.new(true) queue = Queue.new producer = Thread.new do # New thread here to prevent circular waits on the thread pool begin controller.devices.includes(:dependency).each do |device| theClass = Modules.lazy_load(device.dependency) raise "Load Error" if theClass == false queue.push([device, theClass]) end controller.services.includes(:dependency).each do |service| theClass = Modules.lazy_load(service.dependency) raise "Load Error" if theClass == false queue.push([service, theClass]) end controller.logics.includes(:dependency).each do |logic| theClass = Modules.lazy_load(logic.dependency) raise "Load Error" if theClass == false queue.push([logic, theClass]) end rescue proceed.value = false ensure ActiveRecord::Base.clear_active_connections! # Clear any unused connections queue.push(:done) end end # # Consume the newly loaded modules here (Consumer) # mod = queue.pop while mod.is_a?(Array) && proceed.value == true begin system.load(*mod) mod = queue.pop rescue => e AutomateEm.print_error(@@logger, e, { :message => "Error stopping system after problems starting..", :level => Logger::ERROR }) proceed.value = false end end # # Check if system modules loaded properly # if proceed.value == false # # Unload any loaded modules # system.stop return false end # # Setup the systems link # system.start # Start the systems communicator return true ensure ActiveRecord::Base.clear_active_connections! # Clear any unused connections end end |
.start_websockets ⇒ Object
249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 |
# File 'lib/automate-em/interfaces/html5.rb', line 249 def self.start_websockets EM.schedule do if @@socket_server.nil? @@socket_server = EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 81) do |socket| # , :debug => true socket.onopen { # # This socket represents a connected device # HTML5Monitor.register(socket) } socket. { |data| # # Attach socket here to system # then process commands # HTML5Monitor.receive(socket, data) } socket.onclose { HTML5Monitor.unregister(socket) } socket.onerror { |error| if !error.kind_of?(EM::WebSocket::WebSocketError) EM.defer do AutomateEm.print_error(AutomateEm::System.logger, error, { :message => "in html5.rb, onerror : issue with websocket data", :level => Logger::ERROR }) end else EM.defer do AutomateEm::System.logger.info "in html5.rb, onerror : invalid handshake received - #{error.inspect}" end end } end end end EM.defer do AutomateEm::System.logger.info 'running HTML5 socket server on port 81' end end |
.stop(system) ⇒ Object
134 135 136 |
# File 'lib/automate-em/core/system.rb', line 134 def self.stop(system) System[system].stop end |
.stop_websockets ⇒ Object
295 296 297 298 299 300 |
# File 'lib/automate-em/interfaces/html5.rb', line 295 def self.stop_websockets EM.schedule do EventMachine::stop_server(@@socket_server) unless @@socket_server.nil? @@socket_server = nil end end |
Instance Method Details
#[](mod) ⇒ Object
Module accessor
241 242 243 244 |
# File 'lib/automate-em/core/system.rb', line 241 def [] (mod) mod = mod.to_sym if mod.class == String @modules[mod].instance end |
#instance ⇒ Object
For access via communicator
231 232 233 |
# File 'lib/automate-em/core/system.rb', line 231 def instance self end |
#load(dbSetting, theClass) ⇒ Object
Loads a module into a system
255 256 257 258 259 260 261 262 263 |
# File 'lib/automate-em/core/system.rb', line 255 def load(dbSetting, theClass) if dbSetting.is_a?(ControllerDevice) load_hooks(dbSetting, DeviceModule.new(self, dbSetting, theClass)) elsif dbSetting.is_a?(ControllerHttpService) load_hooks(dbSetting, ServiceModule.new(self, dbSetting, theClass)) else # ControllerLogic load_hooks(dbSetting, LogicModule.new(self, dbSetting, theClass)) end end |
#log_level(level) ⇒ Object
Log level changing on the fly
314 315 316 317 318 319 320 321 |
# File 'lib/automate-em/core/system.rb', line 314 def log_level(level) @sys_lock.synchronize { @log_level = AutomateEm::get_log_level(level) if @controller.active @logger.level = @log_level end } end |
#start ⇒ Object
The system is ready to go
268 269 270 271 272 273 |
# File 'lib/automate-em/core/system.rb', line 268 def start @@god_lock.synchronize { @@controllers[@controller.id] = self } @communicator.start end |
#stop ⇒ Object
Stops the current control system Loops through the module instances.
279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 |
# File 'lib/automate-em/core/system.rb', line 279 def stop System.logger.info "stopping #{@controller.name}" @sys_lock.synchronize { if @controller.active @communicator.shutdown modules_unloaded = {} @modules.each_value do |mod| if modules_unloaded[mod] == nil modules_unloaded[mod] = :unloaded mod.unload end end @modules = {} # Modules no longer referenced. Cleanup time! @logger.close if Rails.env.production? @logger = nil end @@god_lock.synchronize { @@controllers.delete(@controller.id) begin @controller.reload(:lock => true) @controller.active = false ensure @controller.save end } } end |