def __init__(self, envPath): self.logger = log.PythonLoggingObserver( "dobozweb.core.components.environments.environmentManager") self.path = EnvironmentManager.envPath self.idCounter = EnvironmentManager.idCounter self._signal_channel = "environment_manager" self.signalHandler = SignalHander(self._signal_channel)
def __init__(self, parentEnvironment): self.logger = log.PythonLoggingObserver( "dobozweb.core.components.nodes.nodeManager") self.parentEnvironment = parentEnvironment self.nodes = {} self.lastNodeId = 0 self._signal_channel = "node_manager" self.signalHandler = SignalHander(self._signal_channel) self.signal_channel_prefix = "environment_" + str( self.parentEnvironment.id)
def __init__(self,envPath): self.logger=log.PythonLoggingObserver("dobozweb.core.components.environments.environmentManager") self.path=EnvironmentManager.envPath self.idCounter=EnvironmentManager.idCounter self._signal_channel="environment_manager" self.signalHandler=SignalHander(self._signal_channel)
def __init__(self,type="node",name="base_node",description="base node",options={},*args,**kwargs): DBObject.__init__(self,**kwargs) self.logger=log.PythonLoggingObserver("dobozweb.core.components.nodes.node") self.name=name self.type=type self.description=description self.extra_params=options self.status=NodeStatus() self.driver=None ################# self.variables=[] self.elements=[] self.tools=[] """this is to ensure no 'asynch clash' occurs when replacing the current driver""" self.driverLock=defer.DeferredSemaphore(1) #self.rootElement=NodeComponent("root") self.testElement=None self.variable_test() #self.link_componentToEndpoint() #self.linkedElements=[] """this is for internal comms handling""" self.signal_channel_prefix=str(self.id) self._signal_channel="node"+self.signal_channel_prefix+"."+self.name self.signalHandler=SignalHander(self._signal_channel) self.signalHandler.add_handler(handler=self.variable_get,signal="get") self.signalHandler.add_handler(handler=self.variable_set,signal="set")
def __init__(self,parentEnvironment): self.logger=log.PythonLoggingObserver("dobozweb.core.components.nodes.nodeManager") self.parentEnvironment=parentEnvironment self.nodes={} self.lastNodeId=0 self._signal_channel="node_manager" self.signalHandler=SignalHander(self._signal_channel) self.signal_channel_prefix="environment_"+str(self.parentEnvironment.id)
def __init__(self, rootUri="http://localhost"): DefaultRestHandler.__init__(self, rootUri) self.valid_contentTypes.append("application/pollapli.eventList+json") self.validGetParams.append('altTimeStamp') self._signal_channel = "global_event_listener" self.signalHandler = SignalHander(self._signal_channel) self.signalHandler.add_handler(channel="driver_manager", handler=self._signal_Handler) self.signalHandler.add_handler(channel="update_manager", handler=self._signal_Handler) self.signalHandler.add_handler(channel="environment_manager", handler=self._signal_Handler) self.signalHandler.add_handler(channel="node_manager", handler=self._signal_Handler) self.lastSignal = DispatchableEvent() self.clientHandler = ClientHandler()
class GlobalEventsHandler(DefaultRestHandler): isLeaf = True def __init__(self, rootUri="http://localhost"): DefaultRestHandler.__init__(self, rootUri) self.valid_contentTypes.append("application/pollapli.eventList+json") self.validGetParams.append('altTimeStamp') self._signal_channel = "global_event_listener" self.signalHandler = SignalHander(self._signal_channel) self.signalHandler.add_handler(channel="driver_manager", handler=self._signal_Handler) self.signalHandler.add_handler(channel="update_manager", handler=self._signal_Handler) self.signalHandler.add_handler(channel="environment_manager", handler=self._signal_Handler) self.signalHandler.add_handler(channel="node_manager", handler=self._signal_Handler) self.lastSignal = DispatchableEvent() self.clientHandler = ClientHandler() def _signal_Handler(self, signal=None, sender=None, realsender=None, data=None, time=None, *args, **kwargs): # log.msg("In rest event handler ", " recieved ",signal," from ",sender, "with data" ,data," addtional ",args,kwargs,logLevel=logging.CRITICAL) self.clientHandler.add_event( DispatchableEvent(signal, sender, data, realsender, time)) def render_GET(self, request): """ Handler for GET requests of events """ r = ResponseGenerator( request, status=200, contentType="application/pollapli.eventList+json", resource="events", rootUri=self.rootUri) d = RequestParser(request, "events", self.valid_contentTypes, self.validGetParams).ValidateAndParseParams() d.addCallbacks(self.clientHandler.add_delegate, callbackArgs=[d, request], errback=r._build_response) request._call = reactor.callLater(0, d.callback, None) return NOT_DONE_YET
def __init__(self, type="node", name="base_node", description="base node", options={}, *args, **kwargs): DBObject.__init__(self, **kwargs) self.logger = log.PythonLoggingObserver( "dobozweb.core.components.nodes.node") self.name = name self.type = type self.description = description self.extra_params = options self.status = NodeStatus() self.driver = None ################# self.variables = [] self.elements = [] self.tools = [] """this is to ensure no 'asynch clash' occurs when replacing the current driver""" self.driverLock = defer.DeferredSemaphore(1) #self.rootElement=NodeComponent("root") self.testElement = None self.variable_test() #self.link_componentToEndpoint() #self.linkedElements=[] """this is for internal comms handling""" self.signal_channel_prefix = str(self.id) self._signal_channel = "node" + self.signal_channel_prefix + "." + self.name self.signalHandler = SignalHander(self._signal_channel) self.signalHandler.add_handler(handler=self.variable_get, signal="get") self.signalHandler.add_handler(handler=self.variable_set, signal="set")
def __init__(self,rootUri="http://localhost"): DefaultRestHandler.__init__(self,rootUri) self.valid_contentTypes.append("application/pollapli.eventList+json") self.validGetParams.append('altTimeStamp') self._signal_channel="global_event_listener" self.signalHandler=SignalHander(self._signal_channel) self.signalHandler.add_handler(channel="driver_manager",handler=self._signal_Handler) self.signalHandler.add_handler(channel="update_manager",handler=self._signal_Handler) self.signalHandler.add_handler(channel="environment_manager",handler=self._signal_Handler) self.signalHandler.add_handler(channel="node_manager",handler=self._signal_Handler) self.lastSignal=DispatchableEvent() self.clientHandler=ClientHandler()
class GlobalEventsHandler(DefaultRestHandler): isLeaf=True def __init__(self,rootUri="http://localhost"): DefaultRestHandler.__init__(self,rootUri) self.valid_contentTypes.append("application/pollapli.eventList+json") self.validGetParams.append('altTimeStamp') self._signal_channel="global_event_listener" self.signalHandler=SignalHander(self._signal_channel) self.signalHandler.add_handler(channel="driver_manager",handler=self._signal_Handler) self.signalHandler.add_handler(channel="update_manager",handler=self._signal_Handler) self.signalHandler.add_handler(channel="environment_manager",handler=self._signal_Handler) self.signalHandler.add_handler(channel="node_manager",handler=self._signal_Handler) self.lastSignal=DispatchableEvent() self.clientHandler=ClientHandler() def _signal_Handler(self,signal=None,sender=None,realsender=None,data=None,time=None,*args,**kwargs): # log.msg("In rest event handler ", " recieved ",signal," from ",sender, "with data" ,data," addtional ",args,kwargs,logLevel=logging.CRITICAL) self.clientHandler.add_event(DispatchableEvent(signal,sender,data,realsender,time)) def render_GET(self, request): """ Handler for GET requests of events """ r=ResponseGenerator(request,status=200,contentType="application/pollapli.eventList+json",resource="events",rootUri=self.rootUri) d=RequestParser(request,"events",self.valid_contentTypes,self.validGetParams).ValidateAndParseParams() d.addCallbacks(self.clientHandler.add_delegate,callbackArgs=[d,request],errback=r._build_response) request._call=reactor.callLater(0,d.callback,None) return NOT_DONE_YET
class TaskManager(object): def __init__(self,parentEnvironment): self.tasks={} self.parentEnvironment=parentEnvironment self._signal_channel="task_manager" self.signalHandler=SignalHander(self._signal_channel) @defer.inlineCallbacks def setup(self): yield self.load(self.parentEnvironment) self.signal_channel_prefix="environment_"+str(self.parentEnvironment.id) defer.returnValue(self) def _send_signal(self,signal="",data=None): prefix=self.signal_channel_prefix+"." self.signalHandler.send_message(prefix+signal,self,data) """ #################################################################################### The following are the "CRUD" (Create, read, update,delete) methods for the general handling of tasks """ @defer.inlineCallbacks def load(self,parentEnvironment=None,taskId=None,taskType=None,*args,**kwargs): if taskId is not None: """For retrieval of single task""" task=yield Task.find(where=['environment_id = ? and task_id=?', parentEnvironment.id,taskId]) defer.returnValue(task) else: tasks=yield Task.find(where=['environment_id = ?', parentEnvironment.id]) # for task in tasks: # task.environment.set(parentEnvironment) # yield task.setup() # #temp hack # actions=yield PrintAction.find(where=['task_id = ?', task.id]) # action=actions[0] # # actionParams=ast.literal_eval(action.params) # action.setup(actionParams) # # action.task.set(task) # action.parentTask=task # task.set_action(action) # #print("action info ptask",action.parentTask,"filename",action.printFileName) # self.tasks[task.id]=task defer.returnValue(tasks) @defer.inlineCallbacks def add_task(self,nodeId=None,nodeElement=None,name="task",description="",taskType=None,params={},*args,**kwargs): """ Add a new task to the list of task of the current environment Params: name: the name of the task Desciption: short description of task type: the type of the task : very important , as it will be used to instanciate the correct class instance Connector:the connector to use for this taks """ """JUST FOR TESTING !!!! The finding of nodes and target variables should be done using the normal element.get_subelement(params) API """ targetNode= yield self.parentEnvironment.get_node(1) targetVariable=targetNode.testElement print("zerzer",targetVariable) task=yield Task(taskType=taskType,extra_params=None).save() log.msg("Added task ",name, logLevel=logging.CRITICAL) task.add_action(UpdateAndGetVariable_action(targetNode,targetVariable)) print("Added test action") task.start() # task= yield Task(name,description,type,params).save() # task.environment.set(self.parentEnvironment) # yield task.setup() # # action=yield PrintAction(parentTask=task,**params).save() # action.task.set(task) # task.set_action(action) # self.tasks[task.id]=task # task.start() # # print("tasks",self.tasks) ## capability= yield NodeManager.environmentTypes[type](name,description).save() ## capability.environment.set(self.parentEnv) ## capability.environment.set(environment) ## environment.capability=capability # #task.events.OnExited+=self._on_task_exited # log.msg("Added task ",name," of type ",type," with id set to ",str(task.id), logLevel=logging.CRITICAL) # defer.returnValue(task) def get_tasks(self,filter=None): """ Returns the list of tasks, filtered by the filter param the filter is a dictionary of list, with each key beeing an attribute to check, and the values in the list , values of that param to check against """ d=defer.Deferred() def filter_check(task,filter): for key in filter.keys(): if not getattr(task, key) in filter[key]: return False return True def get(filter,tasksList): print("taskList",tasksList) if filter: return WrapperList(data=[task for task in environmentsList if filter_check(task,filter)],rootType="tasks") else: return WrapperList(data=tasksList,rootType="tasks") d.addCallback(get,self.tasks.values()) reactor.callLater(0.5,d.callback,filter) return d def remove_task(self,id,forceStop=False): """Removes the task with id==id Shuts down the task before removing it If forcestop is true, shutdown the task even if it is running """ if forceStop: if self.tasks[id].isRunning: self.tasks[id].shutdown() del self.tasks[id] self.logger.critical ("Task %s Removed ",id) def clear_tasks(self,forceStop=False): """Clears the task list completely Params: forceStop: if set to true, the current running task gets stopped and removed aswell """ [self.remove_task(task.id, forceStop) for task in self.tasks] def get_task(self,id): """ returns the task with given id """ return self.tasks[id] def start_task(self,id): """Starts the task in line""" try: self.logger.critical ("Starting task with id %d",id) self.tasks[id].connect(self.connector) self.tasks[id].start() except Exception as inst: self.logger.critical ("Error while starting task %s",str(inst)) def stop_task(self,id): """Forcefully Stops the task with the given id """ if self.tasks[id].isRunning: self.tasks[id].shutdown() def _on_task_exited(self,args,kargs): """Handles the event when the task exited (whether force stopped or because it was finished """ self._task_shutdown() self.logger.critical ("Task Finished ,%g remaining tasks",len(self.tasks)) def _task_shutdown(self): """helper function for cleaning up after a task ended """ self.currentTask.disconnect() self.currentTask.events.OnExited-=self._on_task_exited self.currentTask=None del self.tasks[0]
class NodeManager(object): """ Class for managing nodes: works as a container, a handler and a central management point for the list of available nodes (for future plugin based system) the signal signature for node manager events is as follows: -for example environment_id.node_created : this is for coherence, signal names use underscores, while hierarchy is represented by dots) """ nodeTypes = {} #nodeTypes["reprap"]=ReprapCapability def __init__(self, parentEnvironment): self.logger = log.PythonLoggingObserver( "dobozweb.core.components.nodes.nodeManager") self.parentEnvironment = parentEnvironment self.nodes = {} self.lastNodeId = 0 self._signal_channel = "node_manager" self.signalHandler = SignalHander(self._signal_channel) self.signal_channel_prefix = "environment_" + str( self.parentEnvironment.id) @defer.inlineCallbacks def setup(self): @defer.inlineCallbacks def addNode(nodes): for node in nodes: node.environment.set(self.parentEnvironment) self.nodes[node.id] = node yield node.setup() yield Node.all().addCallback(addNode) defer.returnValue(None) def _send_signal(self, signal="", data=None): prefix = self.signal_channel_prefix + "." self.signalHandler.send_message(prefix + signal, self, data) """ #################################################################################### The following are the "CRUD" (Create, read, update,delete) methods for the general handling of nodes """ @defer.inlineCallbacks def add_node(self, name="node", description="", type=None, *args, **kwargs): """ Add a new node to the list of nodes of the current environment Params: name: the name of the node Desciption: short description of node type: the type of the node : very important , as it will be used to instanciate the correct class instance Connector:the connector to use for this node Driver: the driver to use for this node's connector """ node = yield Node(name=name, description=description, type=type).save() node.environment.set(self.parentEnvironment) self.nodes[node.id] = node log.msg("Added node ", name, " with id set to ", str(node.id), logLevel=logging.CRITICAL) self._send_signal("node_created", node) defer.returnValue(node) def get_nodes(self, filter=None): """ Returns the list of nodes, filtered by the filter param the filter is a dictionary of list, with each key beeing an attribute to check, and the values in the list , values of that param to check against """ d = defer.Deferred() def filter_check(node, filter): for key in filter.keys(): if not getattr(node, key) in filter[key]: return False return True def get(filter, nodesList): if filter: return WrapperList(data=[ node for node in nodesList if filter_check(node, filter) ], rootType="nodes") else: return WrapperList(data=nodesList, rootType="nodes") d.addCallback(get, self.nodes.values()) reactor.callLater(0.5, d.callback, filter) return d def get_node(self, id): if not id in self.nodes.keys(): raise NodeNotFound() return self.nodes[id] def update_node(self, id, name=None, description=None, *args, **kwargs): """Method for node update""" node = self.nodes[id] @defer.inlineCallbacks def _update(): node.name = name node.description = description yield node.save() self._send_signal("node_updated", node) log.msg("updating node ", id, "newname", name, "newdescrption", description, logLevel=logging.CRITICAL) _update() defer.succeed(node) #self.nodes[id].update() def delete_node(self, id): """ Remove a node : this needs a whole set of checks, as it would delete an node completely Params: id: the id of the node """ @defer.inlineCallbacks def _remove(id): """ little "trick" for node deletion : to keep the objects id alive (as it gets removed normally before the event has a chance to be dispatched), the id + data of a node to be deleted gets saved, then the event is dispatched using this "fake node"'s data """ nodeName = self.nodes[id].name tmpNode = self.nodes[id] tmpId = tmpNode.id yield self.nodes[id].delete() del self.nodes[id] tmpNode.id = tmpId self._send_signal("node_deleted", tmpNode) log.msg("Removed node ", nodeName, "with id ", id, logLevel=logging.CRITICAL) if not id in self.nodes.keys(): raise NodeNotFound() _remove(id) defer.succeed(True) def clear_nodes(self): """ Removes & deletes ALL the nodes, should be used with care """ @defer.inlineCallbacks def _clear(): for node in self.nodes.values(): yield self.delete_node(node.id) self._send_signal("nodes_cleared", self.nodes) _clear() defer.succeed(True) """ #################################################################################### Helper Methods """ def set_driver(self, nodeId, **kwargs): """Method to set a nodes connector's driver Params: nodeId: the id of the node WARNING: cheap hack for now, always defaults to serial connector """ #real clumsy, will be switched with better dynamic driver instanciation driver = None if kwargs["type"] == "teacup": del kwargs["type"] driver = TeacupDriver(**kwargs) elif kwargs["type"] == "fived": del kwargs["type"] driver = FiveDDriver(**kwargs) if driver: self.nodes[nodeId].connector.set_driver(driver) self.logger.critical( "Set driver for connector of node %d with params %s", nodeId, str(kwargs)) else: raise Exception("unknown driver ") def start_node(self, nodeId, **kwargs): self.nodes[nodeId].start(**kwargs) def stop_node(self, nodeId): self.nodes[nodeId].stop()
class TaskManager(object): def __init__(self, parentEnvironment): self.tasks = {} self.parentEnvironment = parentEnvironment self._signal_channel = "task_manager" self.signalHandler = SignalHander(self._signal_channel) @defer.inlineCallbacks def setup(self): yield self.load(self.parentEnvironment) self.signal_channel_prefix = "environment_" + str( self.parentEnvironment.id) defer.returnValue(self) def _send_signal(self, signal="", data=None): prefix = self.signal_channel_prefix + "." self.signalHandler.send_message(prefix + signal, self, data) """ #################################################################################### The following are the "CRUD" (Create, read, update,delete) methods for the general handling of tasks """ @defer.inlineCallbacks def load(self, parentEnvironment=None, taskId=None, taskType=None, *args, **kwargs): if taskId is not None: """For retrieval of single task""" task = yield Task.find(where=[ 'environment_id = ? and task_id=?', parentEnvironment.id, taskId ]) defer.returnValue(task) else: tasks = yield Task.find( where=['environment_id = ?', parentEnvironment.id]) # for task in tasks: # task.environment.set(parentEnvironment) # yield task.setup() # #temp hack # actions=yield PrintAction.find(where=['task_id = ?', task.id]) # action=actions[0] # # actionParams=ast.literal_eval(action.params) # action.setup(actionParams) # # action.task.set(task) # action.parentTask=task # task.set_action(action) # #print("action info ptask",action.parentTask,"filename",action.printFileName) # self.tasks[task.id]=task defer.returnValue(tasks) @defer.inlineCallbacks def add_task(self, nodeId=None, nodeElement=None, name="task", description="", taskType=None, params={}, *args, **kwargs): """ Add a new task to the list of task of the current environment Params: name: the name of the task Desciption: short description of task type: the type of the task : very important , as it will be used to instanciate the correct class instance Connector:the connector to use for this taks """ """JUST FOR TESTING !!!! The finding of nodes and target variables should be done using the normal element.get_subelement(params) API """ targetNode = yield self.parentEnvironment.get_node(1) targetVariable = targetNode.testElement print("zerzer", targetVariable) task = yield Task(taskType=taskType, extra_params=None).save() log.msg("Added task ", name, logLevel=logging.CRITICAL) task.add_action(UpdateAndGetVariable_action(targetNode, targetVariable)) print("Added test action") task.start() # task= yield Task(name,description,type,params).save() # task.environment.set(self.parentEnvironment) # yield task.setup() # # action=yield PrintAction(parentTask=task,**params).save() # action.task.set(task) # task.set_action(action) # self.tasks[task.id]=task # task.start() # # print("tasks",self.tasks) ## capability= yield NodeManager.environmentTypes[type](name,description).save() ## capability.environment.set(self.parentEnv) ## capability.environment.set(environment) ## environment.capability=capability # #task.events.OnExited+=self._on_task_exited # log.msg("Added task ",name," of type ",type," with id set to ",str(task.id), logLevel=logging.CRITICAL) # defer.returnValue(task) def get_tasks(self, filter=None): """ Returns the list of tasks, filtered by the filter param the filter is a dictionary of list, with each key beeing an attribute to check, and the values in the list , values of that param to check against """ d = defer.Deferred() def filter_check(task, filter): for key in filter.keys(): if not getattr(task, key) in filter[key]: return False return True def get(filter, tasksList): print("taskList", tasksList) if filter: return WrapperList(data=[ task for task in environmentsList if filter_check(task, filter) ], rootType="tasks") else: return WrapperList(data=tasksList, rootType="tasks") d.addCallback(get, self.tasks.values()) reactor.callLater(0.5, d.callback, filter) return d def remove_task(self, id, forceStop=False): """Removes the task with id==id Shuts down the task before removing it If forcestop is true, shutdown the task even if it is running """ if forceStop: if self.tasks[id].isRunning: self.tasks[id].shutdown() del self.tasks[id] self.logger.critical("Task %s Removed ", id) def clear_tasks(self, forceStop=False): """Clears the task list completely Params: forceStop: if set to true, the current running task gets stopped and removed aswell """ [self.remove_task(task.id, forceStop) for task in self.tasks] def get_task(self, id): """ returns the task with given id """ return self.tasks[id] def start_task(self, id): """Starts the task in line""" try: self.logger.critical("Starting task with id %d", id) self.tasks[id].connect(self.connector) self.tasks[id].start() except Exception as inst: self.logger.critical("Error while starting task %s", str(inst)) def stop_task(self, id): """Forcefully Stops the task with the given id """ if self.tasks[id].isRunning: self.tasks[id].shutdown() def _on_task_exited(self, args, kargs): """Handles the event when the task exited (whether force stopped or because it was finished """ self._task_shutdown() self.logger.critical("Task Finished ,%g remaining tasks", len(self.tasks)) def _task_shutdown(self): """helper function for cleaning up after a task ended """ self.currentTask.disconnect() self.currentTask.events.OnExited -= self._on_task_exited self.currentTask = None del self.tasks[0]
def __init__(self, parentEnvironment): self.tasks = {} self.parentEnvironment = parentEnvironment self._signal_channel = "task_manager" self.signalHandler = SignalHander(self._signal_channel)
class NodeManager(object): """ Class for managing nodes: works as a container, a handler and a central management point for the list of available nodes (for future plugin based system) the signal signature for node manager events is as follows: -for example environment_id.node_created : this is for coherence, signal names use underscores, while hierarchy is represented by dots) """ nodeTypes={} #nodeTypes["reprap"]=ReprapCapability def __init__(self,parentEnvironment): self.logger=log.PythonLoggingObserver("dobozweb.core.components.nodes.nodeManager") self.parentEnvironment=parentEnvironment self.nodes={} self.lastNodeId=0 self._signal_channel="node_manager" self.signalHandler=SignalHander(self._signal_channel) self.signal_channel_prefix="environment_"+str(self.parentEnvironment.id) @defer.inlineCallbacks def setup(self): @defer.inlineCallbacks def addNode(nodes): for node in nodes: node.environment.set(self.parentEnvironment) self.nodes[node.id]=node yield node.setup() yield Node.all().addCallback(addNode) defer.returnValue(None) def _send_signal(self,signal="",data=None): prefix=self.signal_channel_prefix+"." self.signalHandler.send_message(prefix+signal,self,data) """ #################################################################################### The following are the "CRUD" (Create, read, update,delete) methods for the general handling of nodes """ @defer.inlineCallbacks def add_node(self,name="node",description="",type=None,*args,**kwargs): """ Add a new node to the list of nodes of the current environment Params: name: the name of the node Desciption: short description of node type: the type of the node : very important , as it will be used to instanciate the correct class instance Connector:the connector to use for this node Driver: the driver to use for this node's connector """ node= yield Node(name=name,description=description,type=type).save() node.environment.set(self.parentEnvironment) self.nodes[node.id]=node log.msg("Added node ",name," with id set to ",str(node.id), logLevel=logging.CRITICAL) self._send_signal("node_created", node) defer.returnValue(node) def get_nodes(self,filter=None): """ Returns the list of nodes, filtered by the filter param the filter is a dictionary of list, with each key beeing an attribute to check, and the values in the list , values of that param to check against """ d=defer.Deferred() def filter_check(node,filter): for key in filter.keys(): if not getattr(node, key) in filter[key]: return False return True def get(filter,nodesList): if filter: return WrapperList(data=[node for node in nodesList if filter_check(node,filter)],rootType="nodes") else: return WrapperList(data=nodesList,rootType="nodes") d.addCallback(get,self.nodes.values()) reactor.callLater(0.5,d.callback,filter) return d def get_node(self,id): if not id in self.nodes.keys(): raise NodeNotFound() return self.nodes[id] def update_node(self,id,name=None,description=None,*args,**kwargs): """Method for node update""" node=self.nodes[id] @defer.inlineCallbacks def _update(): node.name=name node.description=description yield node.save() self._send_signal("node_updated", node) log.msg("updating node ",id,"newname",name,"newdescrption",description,logLevel=logging.CRITICAL) _update() defer.succeed(node) #self.nodes[id].update() def delete_node(self,id): """ Remove a node : this needs a whole set of checks, as it would delete an node completely Params: id: the id of the node """ @defer.inlineCallbacks def _remove(id): """ little "trick" for node deletion : to keep the objects id alive (as it gets removed normally before the event has a chance to be dispatched), the id + data of a node to be deleted gets saved, then the event is dispatched using this "fake node"'s data """ nodeName=self.nodes[id].name tmpNode=self.nodes[id] tmpId=tmpNode.id yield self.nodes[id].delete() del self.nodes[id] tmpNode.id=tmpId self._send_signal("node_deleted", tmpNode) log.msg("Removed node ",nodeName,"with id ",id,logLevel=logging.CRITICAL) if not id in self.nodes.keys(): raise NodeNotFound() _remove(id) defer.succeed(True) def clear_nodes(self): """ Removes & deletes ALL the nodes, should be used with care """ @defer.inlineCallbacks def _clear(): for node in self.nodes.values(): yield self.delete_node(node.id) self._send_signal("nodes_cleared", self.nodes) _clear(); defer.succeed(True) """ #################################################################################### Helper Methods """ def set_driver(self,nodeId,**kwargs): """Method to set a nodes connector's driver Params: nodeId: the id of the node WARNING: cheap hack for now, always defaults to serial connector """ #real clumsy, will be switched with better dynamic driver instanciation driver=None if kwargs["type"]== "teacup": del kwargs["type"] driver=TeacupDriver(**kwargs) elif kwargs["type"]=="fived": del kwargs["type"] driver=FiveDDriver(**kwargs) if driver: self.nodes[nodeId].connector.set_driver(driver) self.logger.critical("Set driver for connector of node %d with params %s",nodeId,str(kwargs)) else: raise Exception("unknown driver ") def start_node(self,nodeId,**kwargs): self.nodes[nodeId].start(**kwargs) def stop_node(self,nodeId): self.nodes[nodeId].stop()
class EnvironmentManager(object): """ Class acting as a central access point for all the functionality of environments """ envPath=None environments={} idCounter=1 def __init__(self,envPath): self.logger=log.PythonLoggingObserver("dobozweb.core.components.environments.environmentManager") self.path=EnvironmentManager.envPath self.idCounter=EnvironmentManager.idCounter self._signal_channel="environment_manager" self.signalHandler=SignalHander(self._signal_channel) @classmethod @defer.inlineCallbacks def setup(cls,*args,**kwargs): """Retrieve all existing environments from disk""" maxFoundId=1 for fileDir in os.listdir(EnvironmentManager.envPath): if os.path.isdir(os.path.join(EnvironmentManager.envPath,fileDir)): envName= fileDir envPath=os.path.join(EnvironmentManager.envPath,envName) dbPath=os.path.join(envPath,envName)+".db" if os.path.exists(dbPath): Registry.DBPOOL = adbapi.ConnectionPool("sqlite3",database=dbPath,check_same_thread=False) @defer.inlineCallbacks def addEnv(env,maxFoundId): EnvironmentManager.environments[env[0].id]=env[0] yield env[0].setup() if env[0].id>maxFoundId: maxFoundId=env[0].id defer.returnValue(maxFoundId) maxFoundId=yield Environment.find().addCallback(addEnv,maxFoundId) EnvironmentManager.idCounter=maxFoundId+1 #temporary: this should be recalled from db from within the environments ? log.msg("Environment manager setup correctly", system="environement manager", logLevel=logging.CRITICAL) def __getattr__(self, attr_name): for env in self.environments.values(): if hasattr(env, attr_name): return getattr(env, attr_name) raise AttributeError(attr_name) def stop(self): """ Shuts down the environment manager and everything associated with it : ie EVERYTHING !! Should not be called in most cases """ pass """ #################################################################################### The following are the "CRUD" (Create, read, update,delete) methods for the general handling of environements """ @defer.inlineCallbacks def add_environment(self,name="home_test",description="Add Description here",status="frozen"): """ Add an environment to the list of managed environements : Automatically creates a new folder and launches the new environement auto creation Params: EnvName: the name of the environment description:a short description of the environment status: either frozen or live : whether the environment is active or not """ envPath=os.path.join(self.path,name) dbpath=os.path.join(envPath,name)+".db" #if such an environment does not exist, add it doCreate=True if name in os.listdir(self.path): if os.path.exists(os.path.join(self.path,name,dbpath)): doCreate=False else: os.mkdir(envPath) if doCreate: Registry.DBPOOL = adbapi.ConnectionPool("sqlite3",database=dbpath,check_same_thread=False) env=Environment(path=envPath,name=name,description=description,status=status) yield self._generateDatabase() yield env.save() """rather horrid hack of sorts, required to have different, sequential id in the different dbs""" self.force_id(self.idCounter) Registry.DBPOOL.close() Registry.DBPOOL = adbapi.ConnectionPool("sqlite3",database=dbpath,check_same_thread=False) def addEnv(env): self.environments[env[0].id]=env[0] self.idCounter+=1 yield Environment.find().addCallback(addEnv) env=self.environments[self.idCounter-1] self.signalHandler.send_message("environment.created",self,env) log.msg("Adding environment named:",name ," description:",description,"with id",env.id, system="environment manager", logLevel=logging.CRITICAL) defer.returnValue(env) else: raise EnvironmentAlreadyExists() defer.returnValue(None) def get_environments(self,filter=None): """ Returns the list of environments, filtered by the filter param the filter is a dictionary of list, with each key beeing an attribute to check, and the values in the list , values of that param to check against """ d=defer.Deferred() def filter_check(env,filter): for key in filter.keys(): if not getattr(env, key) in filter[key]: return False return True def get(filter,envsList): if filter: #return [env for env in self.environments if getattr(env, "id") in filter["id"]] #return [env for env in self.environments if [True for key in filter.keys() if getattr(env, key)in filter[key]]] return WrapperList(data=[env for env in envsList if filter_check(env,filter)],rootType="environments") else: return WrapperList(data=envsList,rootType="environments") d.addCallback(get,self.environments.values()) reactor.callLater(0.5,d.callback,filter) return d def get_environment(self,envId): env=self.environments.get(envId) if env is None: raise EnvironmentNotFound() return env def update_environment(self,id,name,description,status): #print("updating env",id,name,description,status) return self.environments[id].update(name,description,status) def remove_environment(self,id): """ Remove an environment : this needs a whole set of checks, as it would delete an environment completely (very dangerous) Params: name: the name of the environment """ d=defer.Deferred() def remove(id,envs,path): try: Registry.DBPOOL.close() envName=envs[id].name envPath=os.path.join(path,envName) #self.environments[envName].shutdown() del envs[id] if os.path.isdir(envPath): shutil.rmtree(envPath) #self.logger.critical("Removed and deleted envrionment: '%s' at : '%s'",envName,envPath) log.msg("Removed environment ",envName,"with id ",id, system="environment manager",logLevel=logging.CRITICAL) except: pass #should raise specific exception #raise Exception("failed to delete env") d.addCallback(remove,self.environments,self.path) reactor.callLater(0,d.callback,id) return d @defer.inlineCallbacks def clear_environments(self): """ Removes & deletes ALL the environments, should be used with care """ print(self.environments) for env in self.environments.values(): yield self.remove_environment(env.id) defer.returnValue(None) """ #################################################################################### Helper Methods """ @defer.inlineCallbacks def force_id(self,id): query= '''UPDATE environments SET id ='''+str(id)+''' where id=1''' yield Registry.DBPOOL.runQuery(query) defer.returnValue(None) @defer.inlineCallbacks def _generateMasterDatabase(self): yield Registry.DBPOOL.runQuery('''CREATE TABLE environments( id INTEGER PRIMARY KEY , name TEXT, status TEXT NOT NULL DEFAULT "Live", description TEXT )''') @defer.inlineCallbacks def _generateDatabase(self): yield Registry.DBPOOL.runQuery('''CREATE TABLE addons( id INTEGER PRIMARY KEY, name TEXT, description TEXT, active boolean NOT NULL default true )''') yield Registry.DBPOOL.runQuery('''CREATE TABLE environments( id INTEGER PRIMARY KEY, name TEXT, description TEXT, status TEXT NOT NULL DEFAULT "Live" )''') yield Registry.DBPOOL.runQuery('''CREATE TABLE nodes( id INTEGER PRIMARY KEY AUTOINCREMENT, environment_id INTEGER NOT NULL, type TEXT NOT NULL , name TEXT, description TEXT, recipe TEXT, FOREIGN KEY(environment_id) REFERENCES environments(id) )''') #FOREIGN KEY(node_id) REFERENCES nodes(id) yield Registry.DBPOOL.runQuery('''CREATE TABLE drivers( id INTEGER PRIMARY KEY AUTOINCREMENT, node_id INTEGER NOT NULL, driverType TEXT NOT NULL, deviceType TEXT NOT NULL , deviceId TEXT, options BLOB , FOREIGN KEY(node_id) REFERENCES nodes(id) )''') yield Registry.DBPOOL.runQuery('''CREATE TABLE tasks( id INTEGER PRIMARY KEY AUTOINCREMENT, environment_id INTEGER NOT NULL, name TEXT, description TEXT, type TEXT, params TEXT, FOREIGN KEY(environment_id) REFERENCES environments(id) )''') yield Registry.DBPOOL.runQuery('''CREATE TABLE actions( id INTEGER PRIMARY KEY AUTOINCREMENT, task_id INTEGER NOT NULL, actionType TEXT, params TEXT, FOREIGN KEY(task_id) REFERENCES tasks(id) )''') yield Registry.DBPOOL.runQuery('''CREATE TABLE conditions( id INTEGER PRIMARY KEY AUTOINCREMENT, task_id INTEGER NOT NULL, name TEXT, description TEXT, FOREIGN KEY(task_id) REFERENCES tasks(id) )''') yield Registry.DBPOOL.runQuery('''CREATE TABLE sensors( id INTEGER PRIMARY KEY AUTOINCREMENT, node_id INTEGER NOT NULL, captureType TEXT NOT NULL, captureMode TEXT NOT NULL DEFAULT "Analog", type TEXT NOT NULL , realName TEXT NOT NULL, name TEXT, description TEXT, FOREIGN KEY(node_id) REFERENCES nodes(id) )''') yield Registry.DBPOOL.runQuery('''CREATE TABLE readings( id INTEGER PRIMARY KEY AUTOINCREMENT, node_id INTEGER NOT NULL, sensor_id INTEGER NOT NULL, data INTEGER NOT NULL, dateTime TEXT NOT NULL, FOREIGN KEY(node_id) REFERENCES nodes(id), FOREIGN KEY(sensor_id) REFERENCES sensors(id) )''') """this should be in the master db, but will have to do for now (only support for one environment, because of the limitations of twistar: one db )""" yield Registry.DBPOOL.runQuery('''CREATE TABLE updates( id INTEGER PRIMARY KEY AUTOINCREMENT, type TEXT NOT NULL, name TEXT NOT NULL, description TEXT, version TEXT NOT NULL, downloadUrl TEXT NOT NULL, tags TEXT NOT NULL, img TEXT NOT NULL, file TEXT NOT NULL, fileHash TEXT NOT NULL, downloaded TEXT NOT NULL, installed TEXT NOT NULL, enabled TEXT NOT NULL )''') defer.returnValue(None)
class Node(DBObject): """ Base class for all nodes: a hardware node is a software component handling either a physical device such as a webcam, reprap , arduino etc or some software node (pachube etc) """ BELONGSTO = ['environment'] EXPOSE=["name","description","id","type","status","driver"] def __init__(self,type="node",name="base_node",description="base node",options={},*args,**kwargs): DBObject.__init__(self,**kwargs) self.logger=log.PythonLoggingObserver("dobozweb.core.components.nodes.node") self.name=name self.type=type self.description=description self.extra_params=options self.status=NodeStatus() self.driver=None ################# self.variables=[] self.elements=[] self.tools=[] """this is to ensure no 'asynch clash' occurs when replacing the current driver""" self.driverLock=defer.DeferredSemaphore(1) #self.rootElement=NodeComponent("root") self.testElement=None self.variable_test() #self.link_componentToEndpoint() #self.linkedElements=[] """this is for internal comms handling""" self.signal_channel_prefix=str(self.id) self._signal_channel="node"+self.signal_channel_prefix+"."+self.name self.signalHandler=SignalHander(self._signal_channel) self.signalHandler.add_handler(handler=self.variable_get,signal="get") self.signalHandler.add_handler(handler=self.variable_set,signal="set") @defer.inlineCallbacks def setup(self): self.driver=yield DriverManager.load(parentNode=self) env= (yield self.environment.get()) self.signal_channel_prefix="environment_"+str(env.id)+".node_"+str(self.id) log.msg("Node with id",self.id, "setup successfully",system="Node", logLevel=logging.CRITICAL) self.elementsandVarsTest() defer.returnValue(None) def add_command(self,command): log.msg("Node with id",self.id, "recieved command",command,system="Node", logLevel=logging.CRITICAL) def link_componentToEndpoint(self): self.tempSensor.set_endPoint(self.driver.endpoints[0]) self.linkedElements.append(self.tempSensor) def query_driver(self,sender=None): #f sender in self.linkedElements: if isinstance(sender,Variable): sender.attachedSensors["root"].driverEndpoint.get() def variable_set(self,sender,varName,*args,**kwargs): self.variables[varName].set(*args,**kwargs) def variable_get(self,sender,varName,*args,**kwargs): self.variables[varName].set(*args,**kwargs) def variable_test(self): temp=Variable(self,"temperature",0,float,"celcius",0,"db") tempSensor=Sensor(type="Sensor",name="temperature sensor",tool="testTool") temp.attach_sensor(tempSensor) self.tempSensor=tempSensor self.testElement=temp def elementsandVarsTest(self): """test method, for experimental composition of nodes: this creates all the elements for a basic reprap type node""" """CARTESIAN BOT DEFINITION""" """3d Position""" pos=Variable(self,"position",Vector(['x','y','z']),"vector","mm",None,"memory",3,True,['x','y','z']) """all the motors/actors controlling the 3d Position""" mot1=Actor(type="StepperMotor",name="x_motor",tool="cartesianBot",boundVariable=pos,variableChannel='x') mot2=Actor(type="StepperMotor",name="y_motor",tool="cartesianBot",boundVariable=pos,variableChannel='y') mot3=Actor(type="StepperMotor",name="z_motor",tool="cartesianBot",boundVariable=pos,variableChannel='z') """all the sensors giving feedback on the 3d Position""" endStop1=Sensor(type="end_sensor",name="x_startSensor",tool="cartesianBot",boundVariable=pos,variableChannel='x') endStop2=Sensor(type="end_sensor",name="x_endSensor",tool="cartesianBot",boundVariable=pos,variableChannel='x') endStop3=Sensor(type="end_sensor",name="y_startSensor",tool="cartesianBot",boundVariable=pos,variableChannel='y') endStop4=Sensor(type="end_sensor",name="y_endSensor",tool="cartesianBot",boundVariable=pos,variableChannel='y') endStop5=Sensor(type="end_sensor",name="z_startSensor",tool="cartesianBot",boundVariable=pos,variableChannel='z') endStop6=Sensor(type="end_sensor",name="z_endSensor",tool="cartesianBot",boundVariable=pos,variableChannel='z') """add all these to the current node""" self.add_variable(pos) self.add_elements([mot1,mot2,mot3,endStop1,endStop2,endStop3,endStop4,endStop5,endStop6]) pos.attach_sensors([(endStop1,endStop1.channel),(endStop2,endStop2.channel),(endStop3,endStop3.channel), (endStop4,endStop4.channel),(endStop5,endStop5.channel),(endStop6,endStop6.channel)]) pos.attach_actors([(mot1,mot1.channel),(mot2,mot2.channel),(mot3,mot3.channel)]) """EXTRUDER 1 DEFINITION""" """two variables""" head_temp=Variable(self,"head_temp",0,"temperature","celcius") extrudate_lng=Variable(self,"filament_extrudate",Vector(['e']),"vector","mm") """all the actors controlling the extrusion of this print head""" extrudMot=Actor(type="StepperMotor",name="e_motor1",tool="PrintHead",boundVariable=extrudate_lng,variableChannel='e') head_heater=Actor(type="Heater",name="extruder1_heater",tool="PrintHead",boundVariable=head_temp) """all the sensors giving feedback on the extrusion of this print head""" head_tempSensor=Sensor(type="temperature_sensor",name="extruder1_temp_sensor",tool="PrintHead",boundVariable=head_temp) extrudate_lng.attach_actor(extrudMot,'e') head_temp.attach_both([(head_heater,None)],[(head_tempSensor,None)]) def elementsandVarsTest2(self): """test method, for experimental composition of nodes: this creates all the elements for a basic reprap type node""" """CARTESIAN BOT DEFINITION""" cartesianBot=NodeComponent("cartesian_bot",self.rootElement) """3d Position""" pos=Variable(self,"3d_position",Vector(['x','y','z']),"vector","mm",None,"memory",3,True,None,None,['x','y','z']) """all the motors/actors controlling the 3d Position""" mot1=Actor(type="StepperMotor",name="x_motor",tool="cartesianBot",boundVariable=pos,variableChannel='x') mot2=Actor(type="StepperMotor",name="y_motor",tool="cartesianBot",boundVariable=pos,variableChannel='y') mot3=Actor(type="StepperMotor",name="z_motor",tool="cartesianBot",boundVariable=pos,variableChannel='z') """all the sensors giving feedback on the 3d Position""" endStop1=Sensor(type="end_sensor",name="x_startSensor",tool="cartesianBot",boundVariable=pos,variableChannel='x') endStop2=Sensor(type="end_sensor",name="x_endSensor",tool="cartesianBot",boundVariable=pos,variableChannel='x') endStop3=Sensor(type="end_sensor",name="y_startSensor",tool="cartesianBot",boundVariable=pos,variableChannel='y') endStop4=Sensor(type="end_sensor",name="y_endSensor",tool="cartesianBot",boundVariable=pos,variableChannel='y') endStop5=Sensor(type="end_sensor",name="z_startSensor",tool="cartesianBot",boundVariable=pos,variableChannel='z') endStop6=Sensor(type="end_sensor",name="z_endSensor",tool="cartesianBot",boundVariable=pos,variableChannel='z') """add all these to the current tool""" cartesianBot.add_child(pos) cartesianBot.add_children([mot1,mot2,mot3,endStop1,endStop2,endStop3,endStop4,endStop5,endStop6]) """EXTRUDER 1 DEFINITION""" """two variables""" extruder1=Tool("extruder1") head_temp=Variable(self,"head_temp",0,"temperature","celcius") extrudate_lng=Variable(self,"filament_extrudate",Vector(['e']),"vector","mm") """all the actors controlling the extrusion of this print head""" extrudMot=Actor(type="StepperMotor",name="e_motor1",tool="PrintHead",boundVariable=extrudate_lng,variableChannel='e') head_heater=Actor(type="Heater",name="extruder1_heater",tool="PrintHead",boundVariable=head_temp) """all the sensors giving feedback on the extrusion of this print head""" head_tempSensor=Sensor(type="temperature_sensor",name="extruder1_temp_sensor",tool="PrintHead",boundVariable=head_temp) extrudate_lng.attach_actor(extrudMot,'e') head_temp.attach_both([(head_heater,None)],[(head_tempSensor,None)]) """EXTRUDER 2 DEFINITION""" """two variables""" extruder2=Tool("extruder2") head_temp2=Variable(self,"head_temp",0,"temperature","celcius") extrudate_lng2=Variable(self,"filament_extrudate",Vector(['e']),"vector","mm") """all the actors controlling the extrusion of this print head""" extrudMot2=Actor(type="StepperMotor",name="e_motor1",tool="PrintHead",boundVariable=extrudate_lng2,variableChannel='e') head_heater2=Actor(type="Heater",name="extruder1_heater",tool="PrintHead",boundVariable=head_temp2) """all the sensors giving feedback on the extrusion of this print head""" head_tempSensor=Sensor(type="temperature_sensor",name="extruder1_temp_sensor",tool="PrintHead",boundVariable=head_temp2) extrudate_lng2.attach_actor(extrudMot2,'e') head_temp2.attach_both([(head_heater2,None)],[(head_tempSensor2,None)]) """""""""""""""""""""""""""""""" cartesianBot.add_child(extruder1) cartesianBot.add_child(extruder2) def _toDict(self): return {"node":{"id":self.id,"name":self.name,"description":self.description,"type":self.type,"driver":{"status":{"connected":True},"type":None,"driver":None},"link":{"rel":"node"}}} @defer.inlineCallbacks def set_driver(self,params={},*args,**kwargs): """ Method to set this node's connector Params: returns : a driver instance connector """ @defer.inlineCallbacks def update(): yield self.delete_driver() self.driver=yield DriverManager.create(parentNode=self,**kwargs) log.msg("Set driver of node",self.id," with params ", kwargs,system="Node") defer.returnValue(None) yield self.driverLock.run(update) defer.returnValue(self.driver) def get_driver(self): if self.driver: return self.driver else: raise NoDriverSet() @defer.inlineCallbacks def delete_driver(self): if self.driver: self.driver.disconnect() DriverManager._unregister_driver(self.driver) yield self.driver.delete() self.driver=None log.msg("Disconnected and removed driver", logLevel=logging.CRITICAL,system="Node") defer.returnValue(None) def start(self): """ start this node """ pass def stop(self): """stop this node """ def add_variable(self,variable,*args,**kwarg): self.variables.append(variable) def remove_variable(self,variable,*args,**kwargs): self.variables.remove(variable) def add_element(self,element,*args,**kwargs): self.elements.append(element) def add_elements(self,elements,*args,**kwargs): for element in elements: self.elements.append(element) def remove_element(self,element,*args,**kwargs): self.elements.remove(elment) def connect(self,*args,**kwargs): d=defer.Deferred() def doConnect(driver): driver.connect(*args,**kwargs) return driver d.addCallback(doConnect) reactor.callLater(0,d.callback,self.driver) return d def disconnect(self): d=defer.Deferred() def doDisconnect(driver): driver.disconnect() return driver d.addCallback(doDisconnect) reactor.callLater(0,d.callback,self.driver) return d
class Node(DBObject): """ Base class for all nodes: a hardware node is a software component handling either a physical device such as a webcam, reprap , arduino etc or some software node (pachube etc) """ BELONGSTO = ['environment'] EXPOSE = ["name", "description", "id", "type", "status", "driver"] def __init__(self, type="node", name="base_node", description="base node", options={}, *args, **kwargs): DBObject.__init__(self, **kwargs) self.logger = log.PythonLoggingObserver( "dobozweb.core.components.nodes.node") self.name = name self.type = type self.description = description self.extra_params = options self.status = NodeStatus() self.driver = None ################# self.variables = [] self.elements = [] self.tools = [] """this is to ensure no 'asynch clash' occurs when replacing the current driver""" self.driverLock = defer.DeferredSemaphore(1) #self.rootElement=NodeComponent("root") self.testElement = None self.variable_test() #self.link_componentToEndpoint() #self.linkedElements=[] """this is for internal comms handling""" self.signal_channel_prefix = str(self.id) self._signal_channel = "node" + self.signal_channel_prefix + "." + self.name self.signalHandler = SignalHander(self._signal_channel) self.signalHandler.add_handler(handler=self.variable_get, signal="get") self.signalHandler.add_handler(handler=self.variable_set, signal="set") @defer.inlineCallbacks def setup(self): self.driver = yield DriverManager.load(parentNode=self) env = (yield self.environment.get()) self.signal_channel_prefix = "environment_" + str( env.id) + ".node_" + str(self.id) log.msg("Node with id", self.id, "setup successfully", system="Node", logLevel=logging.CRITICAL) self.elementsandVarsTest() defer.returnValue(None) def add_command(self, command): log.msg("Node with id", self.id, "recieved command", command, system="Node", logLevel=logging.CRITICAL) def link_componentToEndpoint(self): self.tempSensor.set_endPoint(self.driver.endpoints[0]) self.linkedElements.append(self.tempSensor) def query_driver(self, sender=None): #f sender in self.linkedElements: if isinstance(sender, Variable): sender.attachedSensors["root"].driverEndpoint.get() def variable_set(self, sender, varName, *args, **kwargs): self.variables[varName].set(*args, **kwargs) def variable_get(self, sender, varName, *args, **kwargs): self.variables[varName].set(*args, **kwargs) def variable_test(self): temp = Variable(self, "temperature", 0, float, "celcius", 0, "db") tempSensor = Sensor(type="Sensor", name="temperature sensor", tool="testTool") temp.attach_sensor(tempSensor) self.tempSensor = tempSensor self.testElement = temp def elementsandVarsTest(self): """test method, for experimental composition of nodes: this creates all the elements for a basic reprap type node""" """CARTESIAN BOT DEFINITION""" """3d Position""" pos = Variable(self, "position", Vector(['x', 'y', 'z']), "vector", "mm", None, "memory", 3, True, ['x', 'y', 'z']) """all the motors/actors controlling the 3d Position""" mot1 = Actor(type="StepperMotor", name="x_motor", tool="cartesianBot", boundVariable=pos, variableChannel='x') mot2 = Actor(type="StepperMotor", name="y_motor", tool="cartesianBot", boundVariable=pos, variableChannel='y') mot3 = Actor(type="StepperMotor", name="z_motor", tool="cartesianBot", boundVariable=pos, variableChannel='z') """all the sensors giving feedback on the 3d Position""" endStop1 = Sensor(type="end_sensor", name="x_startSensor", tool="cartesianBot", boundVariable=pos, variableChannel='x') endStop2 = Sensor(type="end_sensor", name="x_endSensor", tool="cartesianBot", boundVariable=pos, variableChannel='x') endStop3 = Sensor(type="end_sensor", name="y_startSensor", tool="cartesianBot", boundVariable=pos, variableChannel='y') endStop4 = Sensor(type="end_sensor", name="y_endSensor", tool="cartesianBot", boundVariable=pos, variableChannel='y') endStop5 = Sensor(type="end_sensor", name="z_startSensor", tool="cartesianBot", boundVariable=pos, variableChannel='z') endStop6 = Sensor(type="end_sensor", name="z_endSensor", tool="cartesianBot", boundVariable=pos, variableChannel='z') """add all these to the current node""" self.add_variable(pos) self.add_elements([ mot1, mot2, mot3, endStop1, endStop2, endStop3, endStop4, endStop5, endStop6 ]) pos.attach_sensors([(endStop1, endStop1.channel), (endStop2, endStop2.channel), (endStop3, endStop3.channel), (endStop4, endStop4.channel), (endStop5, endStop5.channel), (endStop6, endStop6.channel)]) pos.attach_actors([(mot1, mot1.channel), (mot2, mot2.channel), (mot3, mot3.channel)]) """EXTRUDER 1 DEFINITION""" """two variables""" head_temp = Variable(self, "head_temp", 0, "temperature", "celcius") extrudate_lng = Variable(self, "filament_extrudate", Vector(['e']), "vector", "mm") """all the actors controlling the extrusion of this print head""" extrudMot = Actor(type="StepperMotor", name="e_motor1", tool="PrintHead", boundVariable=extrudate_lng, variableChannel='e') head_heater = Actor(type="Heater", name="extruder1_heater", tool="PrintHead", boundVariable=head_temp) """all the sensors giving feedback on the extrusion of this print head""" head_tempSensor = Sensor(type="temperature_sensor", name="extruder1_temp_sensor", tool="PrintHead", boundVariable=head_temp) extrudate_lng.attach_actor(extrudMot, 'e') head_temp.attach_both([(head_heater, None)], [(head_tempSensor, None)]) def elementsandVarsTest2(self): """test method, for experimental composition of nodes: this creates all the elements for a basic reprap type node""" """CARTESIAN BOT DEFINITION""" cartesianBot = NodeComponent("cartesian_bot", self.rootElement) """3d Position""" pos = Variable(self, "3d_position", Vector(['x', 'y', 'z']), "vector", "mm", None, "memory", 3, True, None, None, ['x', 'y', 'z']) """all the motors/actors controlling the 3d Position""" mot1 = Actor(type="StepperMotor", name="x_motor", tool="cartesianBot", boundVariable=pos, variableChannel='x') mot2 = Actor(type="StepperMotor", name="y_motor", tool="cartesianBot", boundVariable=pos, variableChannel='y') mot3 = Actor(type="StepperMotor", name="z_motor", tool="cartesianBot", boundVariable=pos, variableChannel='z') """all the sensors giving feedback on the 3d Position""" endStop1 = Sensor(type="end_sensor", name="x_startSensor", tool="cartesianBot", boundVariable=pos, variableChannel='x') endStop2 = Sensor(type="end_sensor", name="x_endSensor", tool="cartesianBot", boundVariable=pos, variableChannel='x') endStop3 = Sensor(type="end_sensor", name="y_startSensor", tool="cartesianBot", boundVariable=pos, variableChannel='y') endStop4 = Sensor(type="end_sensor", name="y_endSensor", tool="cartesianBot", boundVariable=pos, variableChannel='y') endStop5 = Sensor(type="end_sensor", name="z_startSensor", tool="cartesianBot", boundVariable=pos, variableChannel='z') endStop6 = Sensor(type="end_sensor", name="z_endSensor", tool="cartesianBot", boundVariable=pos, variableChannel='z') """add all these to the current tool""" cartesianBot.add_child(pos) cartesianBot.add_children([ mot1, mot2, mot3, endStop1, endStop2, endStop3, endStop4, endStop5, endStop6 ]) """EXTRUDER 1 DEFINITION""" """two variables""" extruder1 = Tool("extruder1") head_temp = Variable(self, "head_temp", 0, "temperature", "celcius") extrudate_lng = Variable(self, "filament_extrudate", Vector(['e']), "vector", "mm") """all the actors controlling the extrusion of this print head""" extrudMot = Actor(type="StepperMotor", name="e_motor1", tool="PrintHead", boundVariable=extrudate_lng, variableChannel='e') head_heater = Actor(type="Heater", name="extruder1_heater", tool="PrintHead", boundVariable=head_temp) """all the sensors giving feedback on the extrusion of this print head""" head_tempSensor = Sensor(type="temperature_sensor", name="extruder1_temp_sensor", tool="PrintHead", boundVariable=head_temp) extrudate_lng.attach_actor(extrudMot, 'e') head_temp.attach_both([(head_heater, None)], [(head_tempSensor, None)]) """EXTRUDER 2 DEFINITION""" """two variables""" extruder2 = Tool("extruder2") head_temp2 = Variable(self, "head_temp", 0, "temperature", "celcius") extrudate_lng2 = Variable(self, "filament_extrudate", Vector(['e']), "vector", "mm") """all the actors controlling the extrusion of this print head""" extrudMot2 = Actor(type="StepperMotor", name="e_motor1", tool="PrintHead", boundVariable=extrudate_lng2, variableChannel='e') head_heater2 = Actor(type="Heater", name="extruder1_heater", tool="PrintHead", boundVariable=head_temp2) """all the sensors giving feedback on the extrusion of this print head""" head_tempSensor = Sensor(type="temperature_sensor", name="extruder1_temp_sensor", tool="PrintHead", boundVariable=head_temp2) extrudate_lng2.attach_actor(extrudMot2, 'e') head_temp2.attach_both([(head_heater2, None)], [(head_tempSensor2, None)]) """""" """""" """""" """""" """""" "" cartesianBot.add_child(extruder1) cartesianBot.add_child(extruder2) def _toDict(self): return { "node": { "id": self.id, "name": self.name, "description": self.description, "type": self.type, "driver": { "status": { "connected": True }, "type": None, "driver": None }, "link": { "rel": "node" } } } @defer.inlineCallbacks def set_driver(self, params={}, *args, **kwargs): """ Method to set this node's connector Params: returns : a driver instance connector """ @defer.inlineCallbacks def update(): yield self.delete_driver() self.driver = yield DriverManager.create(parentNode=self, **kwargs) log.msg("Set driver of node", self.id, " with params ", kwargs, system="Node") defer.returnValue(None) yield self.driverLock.run(update) defer.returnValue(self.driver) def get_driver(self): if self.driver: return self.driver else: raise NoDriverSet() @defer.inlineCallbacks def delete_driver(self): if self.driver: self.driver.disconnect() DriverManager._unregister_driver(self.driver) yield self.driver.delete() self.driver = None log.msg("Disconnected and removed driver", logLevel=logging.CRITICAL, system="Node") defer.returnValue(None) def start(self): """ start this node """ pass def stop(self): """stop this node """ def add_variable(self, variable, *args, **kwarg): self.variables.append(variable) def remove_variable(self, variable, *args, **kwargs): self.variables.remove(variable) def add_element(self, element, *args, **kwargs): self.elements.append(element) def add_elements(self, elements, *args, **kwargs): for element in elements: self.elements.append(element) def remove_element(self, element, *args, **kwargs): self.elements.remove(elment) def connect(self, *args, **kwargs): d = defer.Deferred() def doConnect(driver): driver.connect(*args, **kwargs) return driver d.addCallback(doConnect) reactor.callLater(0, d.callback, self.driver) return d def disconnect(self): d = defer.Deferred() def doDisconnect(driver): driver.disconnect() return driver d.addCallback(doDisconnect) reactor.callLater(0, d.callback, self.driver) return d
def __init__(self,port,rootPath,filePath,dataPath): #app = Application("PollapliServer") self.port=port self.rootPath=rootPath self.filePath=filePath self.dataPath=dataPath self.logPath=dataPath self.updates_path=os.path.join(dataPath,"updates") self.addOnsPath=os.path.join(self.rootPath,"addons") self.environmentsPath=os.path.join(self.dataPath,"environments") self.depenciesPath=os.path.join(self.rootPath,"dependencies") if not os.path.exists(self.rootPath): os.makedirs(self.rootPath) if not os.path.exists(self.dataPath): os.makedirs(self.dataPath) if not os.path.exists(self.updates_path): os.makedirs(self.updates_path) if not os.path.exists(self.addOnsPath): os.makedirs(self.addOnsPath) if not os.path.exists(self.environmentsPath): os.makedirs(self.environmentsPath) """"""""""""""""""""""""""""""""""""""""" Initialize various subsystems /set correct paths """ UpdateManager._addon_path=self.addOnsPath UpdateManager.updates_path=self.updates_path EnvironmentManager.envPath=self.environmentsPath FileManager.rootDir=self.dataPath FileManager.corePath=os.path.join(self.rootPath,"core") FileManager.rootPath=self.rootPath FileManager.filePath=self.filePath FileManager.uploadPath=os.path.join(self.dataPath,"uploads") FileManager.dataPath=self.dataPath FileManager.logPath=self.logPath FileManager.updates_path=self.updates_path FileManager._addon_path=self.addOnsPath FileManager.depenciesPath=self.depenciesPath if not os.path.exists(FileManager.uploadPath): os.makedirs(FileManager.uploadPath) self.environmentManager=EnvironmentManager(self.dataPath) """""""""""""""""""""""""""""""""""""" exceptionConverter=ExceptionConverter() exceptionConverter.add_exception(ParameterParseException,400 ,1,"Params parse error") exceptionConverter.add_exception(UnhandledContentTypeException,415 ,2,"Bad content type") exceptionConverter.add_exception(EnvironmentAlreadyExists,409 ,3,"Environment already exists") exceptionConverter.add_exception(EnvironmentNotFound,404 ,4,"Environment not found") exceptionConverter.add_exception(UnknownDeviceType,500 ,5,"Unknown node type") exceptionConverter.add_exception(DeviceNotFound,404 ,6,"Node not found") exceptionConverter.add_exception(NoDriverSet,404,7,"Node has no connector") exceptionConverter.add_exception(UnknownDriver,500,8,"Unknown connector driver type") exceptionConverter.add_exception(DeviceHandshakeMismatch,500,9,"Device handshake failed to match the one defined by the driver") exceptionConverter.add_exception(InvalidFile,500,10,"Invalid File") exceptionConverter.add_exception(DeviceNotConnected,500,11,"Attempting to communicate with not connected device") self._signal_channel="main_signal_listener" self.signalHandler=SignalHander(self._signal_channel) self.signalHandler.add_handler(channel="driver_manager") self.signalHandler.add_handler(channel="update_manager") self.signalHandler.add_handler(channel="environment_manager") self.signalHandler.add_handler(channel="node_manager") self.setup()
class MainServer(): def __init__(self,port,rootPath,filePath,dataPath): #app = Application("PollapliServer") self.port=port self.rootPath=rootPath self.filePath=filePath self.dataPath=dataPath self.logPath=dataPath self.updates_path=os.path.join(dataPath,"updates") self.addOnsPath=os.path.join(self.rootPath,"addons") self.environmentsPath=os.path.join(self.dataPath,"environments") self.depenciesPath=os.path.join(self.rootPath,"dependencies") if not os.path.exists(self.rootPath): os.makedirs(self.rootPath) if not os.path.exists(self.dataPath): os.makedirs(self.dataPath) if not os.path.exists(self.updates_path): os.makedirs(self.updates_path) if not os.path.exists(self.addOnsPath): os.makedirs(self.addOnsPath) if not os.path.exists(self.environmentsPath): os.makedirs(self.environmentsPath) """"""""""""""""""""""""""""""""""""""""" Initialize various subsystems /set correct paths """ UpdateManager._addon_path=self.addOnsPath UpdateManager.updates_path=self.updates_path EnvironmentManager.envPath=self.environmentsPath FileManager.rootDir=self.dataPath FileManager.corePath=os.path.join(self.rootPath,"core") FileManager.rootPath=self.rootPath FileManager.filePath=self.filePath FileManager.uploadPath=os.path.join(self.dataPath,"uploads") FileManager.dataPath=self.dataPath FileManager.logPath=self.logPath FileManager.updates_path=self.updates_path FileManager._addon_path=self.addOnsPath FileManager.depenciesPath=self.depenciesPath if not os.path.exists(FileManager.uploadPath): os.makedirs(FileManager.uploadPath) self.environmentManager=EnvironmentManager(self.dataPath) """""""""""""""""""""""""""""""""""""" exceptionConverter=ExceptionConverter() exceptionConverter.add_exception(ParameterParseException,400 ,1,"Params parse error") exceptionConverter.add_exception(UnhandledContentTypeException,415 ,2,"Bad content type") exceptionConverter.add_exception(EnvironmentAlreadyExists,409 ,3,"Environment already exists") exceptionConverter.add_exception(EnvironmentNotFound,404 ,4,"Environment not found") exceptionConverter.add_exception(UnknownDeviceType,500 ,5,"Unknown node type") exceptionConverter.add_exception(DeviceNotFound,404 ,6,"Node not found") exceptionConverter.add_exception(NoDriverSet,404,7,"Node has no connector") exceptionConverter.add_exception(UnknownDriver,500,8,"Unknown connector driver type") exceptionConverter.add_exception(DeviceHandshakeMismatch,500,9,"Device handshake failed to match the one defined by the driver") exceptionConverter.add_exception(InvalidFile,500,10,"Invalid File") exceptionConverter.add_exception(DeviceNotConnected,500,11,"Attempting to communicate with not connected device") self._signal_channel="main_signal_listener" self.signalHandler=SignalHander(self._signal_channel) self.signalHandler.add_handler(channel="driver_manager") self.signalHandler.add_handler(channel="update_manager") self.signalHandler.add_handler(channel="environment_manager") self.signalHandler.add_handler(channel="node_manager") self.setup() # reactor.callLater(2,self.compiler_test) # reactor.callLater(2,self.compiler_test2) #reactor.callLater(5,self.uploader_test) #self.formatter_tests() #self.usbTest2() #reactor.callLater(1,self.gstInspectTest) def gstInspectTest(self): path="C:\\Program Files\\OSSBuild\\GStreamer\\v0.10.6\\bin\gst-inspect.exe" scp = SconsProcessProtocol("truc") scp.deferred = defer.Deferred() cmd = [path] p = reactor.spawnProcess(scp, cmd[0], cmd,env=os.environ ) #p = reactor.spawnProcess(processProtocol=scp, executable=cmd[0],args=cmd,env=os.environ ) return scp.deferred def usbTest_pyusb(self): #import pysusb.usb.core dev = usb.core.find(find_all=True) print("dev ",dev) def usbTest(self): #print("core inst",core.__name__) devices= usb.core.find(find_all=True) print("total devices",devices) try: for device in devices: print("====DEVICE====") _name = usb.util.get_string(device,256,device.iProduct) #This is where I'm having trouble print ("device name=",_name) #print ("Device:", device.filename) print("descriptor type",device.bDescriptorType) print("highest usb type",device.bcdUSB) print("class",device.bDeviceClass) print("subClass",device.bDeviceSubClass) print("vendor id",device.idVendor) print("device id",device.idProduct) print("bDeviceProtocol",device.bDeviceProtocol) print("bcdDevice",device.bcdDevice) print("iSerialNumber",device.iSerialNumber) print("serialNumber",usb.util.get_string(device,256,device.iSerialNumber)) print("iManufacturer",device.iManufacturer) print("manufacturer",usb.util.get_string(device,256,device.iManufacturer)) print("iProduct",device.iProduct) print("product",usb.util.get_string(device,256,device.iProduct)) print("configs",device.bNumConfigurations) print(" **getting data**") print("test",usb.util.get_string(device,256,3)) #device.set_configuration(0) activeConf=device.get_active_configuration() print("active conf", activeConf) print("bconfValue", activeConf.bConfigurationValue) print("bNumInterfaces", activeConf.bNumInterfaces) for interf in activeConf: print("bInterfaceNumber", interf.bInterfaceNumber) print("interfaceInterf", interf.iInterface) print("interfaceBaseClass", interf.bInterfaceClass) print("interfaceSubClass", interf.bInterfaceSubClass) except Exception as inst: print("error",inst) # busses = usb.busses() # print("busses",busses) # for bus in busses: # devices = bus.devices # for dev in devices: # print "Device:", dev.filename # _name = usb.util.get_string(device,256,0) #This is where I'm having trouble # print ("device name=",_name) # print " idVendor: %d (0x%04x)" % (dev.idVendor, dev.idVendor) # print " idProduct: %d (0x%04x)" % (dev.idProduct, dev.idProduct) reactor.stop() def usbTest2(self): # import wmi c = wmi.WMI() drivers=c.Win32_PnPSignedDriver() for driver in drivers: print(driver) print("devices") devices= c.Win32_USBControllerDevice() for dev in devices: #print(dev) devId=dev.Dependent.DeviceID for device in c.Win32_PnPEntity(DeviceID=devId): #print(device) print(device.DeviceID) #print (device.ClassGuid,device.Name,device.DeviceID) # dep=devices[0].Dependent # print("Did",dep) # for device in c.Win32_PnPEntity(DeviceID=dep.DeviceID): # print (device) def spawn_test(self): trucpath=os.path.join("d:\\Progra","arduino-0018","arduino.exe") trucpath=os.path.join("d:\\","data","projects","Doboz","pollapli","dependencies","scons","scons.py") """ env = os.environ.copy() env['PYTHONPATH'] = os.pathsep.join(sys.path) reactor.callLater(0,reactor.spawnProcess, env=env, *self.spawn) """ print('PYTHONPATH',os.environ['PYTHONPATH']) scp = SconsProcessProtocol("truc") scp.deferred = defer.Deferred() print("os environ",os.environ) print("sys exect",sys.executable) cmd = ["C:\Progra\Python26\python.exe",trucpath] cmd=[sys.executable,trucpath] p = reactor.spawnProcess(scp, cmd[0], cmd,env=os.environ ) #p = reactor.spawnProcess(processProtocol=scp, executable=cmd[0],args=cmd,env=os.environ ) return scp.deferred def compiler_test3(self): testTarget=os.path.join(self.rootPath,"arduinoexample") sconsPath=os.path.join(self.depenciesPath,"scons","scons.py") shutil.copy2(os.path.join(self.rootPath,"core","components","autocompile","SConstruct"),os.path.join(testTarget,"SConstruct")) if os.path.exists(sconsPath): print("scons found") print("sconsPath",sconsPath) scp = SconsProcessProtocol("arduino") scp.deferred = defer.Deferred() """on linux """ #cmd = [sconsPath,"-Y"+testTarget,"TARGETPATH="+testTarget,"-i"] """on win32""" cmd =[sys.executable,sconsPath,"-Y"+testTarget,"TARGETPATH="+testTarget,"-i"] p = reactor.spawnProcess(scp, cmd[0], cmd,env=os.environ ) return scp.deferred else: print("scons not found") def compiler_test(self): """todo: add temp file deletion""" testTarget=os.path.join(self.addOnsPath,"ArduinoExampleAddOn","arduinoExample" ,"firmware","arduinoexample") print(testTarget) #print("tutu","\\\?\\") ##apparently, max path limitation could get avoided with : "\\\?\\" prefix, causes the build ##to fail though envCopy=os.environ.copy() sconsPath=os.path.join(self.depenciesPath,"scons","scons.py") def create_dir_struture(source,inTemp=False): if inTemp: import distutils.dir_util targetBuildDir=tempfile.mkdtemp() distutils.dir_util.copy_tree(testTarget, targetBuildDir) else: buildsDir=os.path.join(self.rootPath,"builds") if not os.path.exists(buildsDir): os.makedirs(buildsDir) targetBuildName=str(uuid.uuid4()) targetBuildDir=os.path.join(buildsDir,targetBuildName) shutil.copytree(testTarget, targetBuildDir) """rename the pde file""" tmp = os.path.basename(testTarget) tmpDst=os.path.basename(targetBuildDir) shutil.move( os.path.join(targetBuildDir,tmp+".pde"),os.path.join(targetBuildDir,tmpDst+".pde")) """copy scons file to folder""" shutil.copy2(os.path.join(self.rootPath,"core","components","autocompile","SConstruct"),targetBuildDir) return targetBuildDir testTarget=create_dir_struture(testTarget) if os.path.exists(sconsPath): print("scons found") print("sconsPath",sconsPath) scp = SconsProcessProtocol("arduino",testTarget) scp.deferred = defer.Deferred() """on linux """ #cmd = [sconsPath,"-Y"+testTarget,"TARGETPATH="+testTarget,"-i"] """on win32""" cmd =[sys.executable,sconsPath,"-Y"+testTarget,"TARGETPATH="+testTarget,"-i","--diskcheck=none","--cache-disable","--config=force"] p = reactor.spawnProcess(scp, cmd[0], cmd,env=envCopy ) return scp.deferred else: print("scons not found") def compiler_test2(self): testTarget=os.path.join(self.addOnsPath,"Hydroduino_0_0_1_py2_6","hydroduino" ,"firmware","hydroduino") sconsPath=os.path.join(self.depenciesPath,"scons.py") scp = SconsProcessProtocol("hydroduino") scp.deferred = defer.Deferred() cmd = [sconsPath,"-Y"+testTarget,"TARGETPATH="+testTarget,"-i"] p = reactor.spawnProcess(scp, cmd[0], cmd,env=os.environ,usePTY=True ) return scp.deferred def uploader_test(self): testTarget=os.path.join(self.addOnsPath,"ArduinoExampleAddOn_0_0_1_py2_6","arduinoExample" ,"firmware","arduinoexample") sconsPath="/home/ckaos/data/Progra/Scons/scons.py" scp = SconsProcessProtocol() scp.deferred = defer.Deferred() cmd = [sconsPath,"-Y"+testTarget,"TARGETPATH="+testTarget,"-i", "upload"] p = reactor.spawnProcess(scp, cmd[0], cmd,env=os.environ,usePTY=True ) return scp.deferred # compiler=compiler_uploader(arduinoPath="/home/ckaos/utilz/Progra/arduino-0022/",targetDir=testTarget) # compiler.check_boardName() # compiler.do_stuff() # compiler.check_source_main() # compiler.set_flags() # compiler._createBuilders() # compiler.addArduinoCore() # compiler.addArduinoLibs() # compiler.do_convert() # # compiler.build() #compiler.tearDown() #subprocess.call("myProg -arg1 -arg2") @defer.inlineCallbacks def do_stuff(self): #filePath="D:\\data\\projects\\Doboz\\add_ons_egg_tests\\virtualDevice\\dist\\VirtualDeviceAddOn-0.0.1-py2.6.egg" rootAddonsPath="D:\\data\\projects\\Doboz\\add_ons_egg_tests\\" filePath=os.path.join(rootAddonsPath,"virtualDevice\\dist\\VirtualDeviceAddOn-0.0.1-py2.6.egg") filePath=os.path.join(rootAddonsPath,"arduinoExample\\dist\\ArduinoExampleAddOn-0.0.1-py2.6.egg") #filePath=os.path.join(rootAddonsPath,"reprap\\dist\\ReprapAddOn-0.0.1-py2.6.egg") hash=yield checksum_tools.generate_hash(filePath) print ("md5 hash",hash) hashCompare=yield checksum_tools.compare_hash("80e157c0f10baef206ee2de03fae7449",filePath) print("md5 compare", hashCompare) def formatter_tests(self): formater=JsonFormater(resource="Tutu",rootUri="http://localhost",ignoredAttrs=["blah","blob"],addedAttrs={"gateaux":75},list=False) class subThing(object): EXPOSE=["strengh","width","height"] def __init__(self,strengh="Max",width=10,height=7): self.strengh=strengh self.width=width self.height=height class Thing(object): #EXPOSE=["subThings"] def __init__(self): self.subThings=[] self.subThings.append(subThing("truc")) self.subThings.append(subThing("muche")) class OtherThing(object): EXPOSE=["var","subThing1","subThing2"] def __init__(self,var="somevalue"): self.var=var self.subThing1=subThing() self.subThing2=subThing("min") class Tutu(object): id=0 EXPOSE=["id","thing.subThings"] def __init__(self,blob="blob",blib=42,blah="nii"): self.blob=blob self.blib=blib self.blah=blah self.id=Tutu.id self.name="truc" self.thing=Thing() Tutu.id+=1 class ThingWithId(object): id=0 EXPOSE=["id","thingy"] def __init__(self,thingy="thing"): self.id=ThingWithId.id ThingWithId.id+=1 self.thingy=thingy print("single item: ",formater.format(OtherThing(),"Otherthing","http://localhost/otherthing")) print("single item: ",formater.format(Tutu(),"tutu","http://localhost/tutu")) print("multiple items: ",formater.format([subThing("min",0.5,3),subThing()],"kpouer","http://localhost/kpouer")) print("multiple items: ",formater.format([ThingWithId(),ThingWithId()],"wobbly","http://localhost/wobbly")) def callbackTests(self): d=defer.Deferred() def funct1(result): print("in funct1") def funct2(result): print("in funct2") def funct3(result): print("in funct3") d.addCallback(funct1) d.addCallback(funct2) d.addCallback(funct3) d.callback(None) @defer.inlineCallbacks def setup(self): """configure all systems """ from twisted.enterprise import adbapi from twistar.registry import Registry envPath=os.path.join(EnvironmentManager.envPath,"home") dbPath=os.path.join(envPath,"home")+".db" Registry.DBPOOL = adbapi.ConnectionPool("sqlite3",database=dbPath,check_same_thread=False) """this is a required but very cheap hack: since twistard does not support multiple databases, we do not have a "master" database, which causes problems because of the dependencies, and initialization order of different elements, so for now, the "home" database is enforced""" yield UpdateManager.setup() yield DriverManager.setup() yield EnvironmentManager.setup() defer.returnValue(None) def start(self): observer = log.PythonLoggingObserver("pollapli.core") observer.start() # log.startLogging(sys.stdout) # logfile=os.path.join(self.logPath,"pollapli.log") # log.startLogging(open(logfile, 'w'),setStdout=False) root = File(self.filePath) restRoot=Resource() root.putChild("rest",restRoot) try: restRoot.putChild("config", ConfigHandler("/rest/config")) restRoot.putChild("drivertypes", DriverTypesHandler("/rest/drivertypes")) restRoot.putChild("environments", EnvironmentsHandler("/rest/environments",self.environmentManager)) except Exception as inst: log.msg("Error in base rest resources creation",str(inst), system="server", logLevel=logging.CRITICAL) factory = Site(root) #self.port=9071#TEMP HACK!! reactor.listenTCP(self.port, factory) log.msg("Server started!", system="server", logLevel=logging.CRITICAL) reactor.run()
def __init__(self,parentEnvironment): self.tasks={} self.parentEnvironment=parentEnvironment self._signal_channel="task_manager" self.signalHandler=SignalHander(self._signal_channel)
class EnvironmentManager(object): """ Class acting as a central access point for all the functionality of environments """ envPath = None environments = {} idCounter = 1 def __init__(self, envPath): self.logger = log.PythonLoggingObserver( "dobozweb.core.components.environments.environmentManager") self.path = EnvironmentManager.envPath self.idCounter = EnvironmentManager.idCounter self._signal_channel = "environment_manager" self.signalHandler = SignalHander(self._signal_channel) @classmethod @defer.inlineCallbacks def setup(cls, *args, **kwargs): """Retrieve all existing environments from disk""" maxFoundId = 1 for fileDir in os.listdir(EnvironmentManager.envPath): if os.path.isdir(os.path.join(EnvironmentManager.envPath, fileDir)): envName = fileDir envPath = os.path.join(EnvironmentManager.envPath, envName) dbPath = os.path.join(envPath, envName) + ".db" if os.path.exists(dbPath): Registry.DBPOOL = adbapi.ConnectionPool( "sqlite3", database=dbPath, check_same_thread=False) @defer.inlineCallbacks def addEnv(env, maxFoundId): EnvironmentManager.environments[env[0].id] = env[0] yield env[0].setup() if env[0].id > maxFoundId: maxFoundId = env[0].id defer.returnValue(maxFoundId) maxFoundId = yield Environment.find().addCallback( addEnv, maxFoundId) EnvironmentManager.idCounter = maxFoundId + 1 #temporary: this should be recalled from db from within the environments ? log.msg("Environment manager setup correctly", system="environement manager", logLevel=logging.CRITICAL) def __getattr__(self, attr_name): for env in self.environments.values(): if hasattr(env, attr_name): return getattr(env, attr_name) raise AttributeError(attr_name) def stop(self): """ Shuts down the environment manager and everything associated with it : ie EVERYTHING !! Should not be called in most cases """ pass """ #################################################################################### The following are the "CRUD" (Create, read, update,delete) methods for the general handling of environements """ @defer.inlineCallbacks def add_environment(self, name="home_test", description="Add Description here", status="frozen"): """ Add an environment to the list of managed environements : Automatically creates a new folder and launches the new environement auto creation Params: EnvName: the name of the environment description:a short description of the environment status: either frozen or live : whether the environment is active or not """ envPath = os.path.join(self.path, name) dbpath = os.path.join(envPath, name) + ".db" #if such an environment does not exist, add it doCreate = True if name in os.listdir(self.path): if os.path.exists(os.path.join(self.path, name, dbpath)): doCreate = False else: os.mkdir(envPath) if doCreate: Registry.DBPOOL = adbapi.ConnectionPool("sqlite3", database=dbpath, check_same_thread=False) env = Environment(path=envPath, name=name, description=description, status=status) yield self._generateDatabase() yield env.save() """rather horrid hack of sorts, required to have different, sequential id in the different dbs""" self.force_id(self.idCounter) Registry.DBPOOL.close() Registry.DBPOOL = adbapi.ConnectionPool("sqlite3", database=dbpath, check_same_thread=False) def addEnv(env): self.environments[env[0].id] = env[0] self.idCounter += 1 yield Environment.find().addCallback(addEnv) env = self.environments[self.idCounter - 1] self.signalHandler.send_message("environment.created", self, env) log.msg("Adding environment named:", name, " description:", description, "with id", env.id, system="environment manager", logLevel=logging.CRITICAL) defer.returnValue(env) else: raise EnvironmentAlreadyExists() defer.returnValue(None) def get_environments(self, filter=None): """ Returns the list of environments, filtered by the filter param the filter is a dictionary of list, with each key beeing an attribute to check, and the values in the list , values of that param to check against """ d = defer.Deferred() def filter_check(env, filter): for key in filter.keys(): if not getattr(env, key) in filter[key]: return False return True def get(filter, envsList): if filter: #return [env for env in self.environments if getattr(env, "id") in filter["id"]] #return [env for env in self.environments if [True for key in filter.keys() if getattr(env, key)in filter[key]]] return WrapperList(data=[ env for env in envsList if filter_check(env, filter) ], rootType="environments") else: return WrapperList(data=envsList, rootType="environments") d.addCallback(get, self.environments.values()) reactor.callLater(0.5, d.callback, filter) return d def get_environment(self, envId): env = self.environments.get(envId) if env is None: raise EnvironmentNotFound() return env def update_environment(self, id, name, description, status): #print("updating env",id,name,description,status) return self.environments[id].update(name, description, status) def remove_environment(self, id): """ Remove an environment : this needs a whole set of checks, as it would delete an environment completely (very dangerous) Params: name: the name of the environment """ d = defer.Deferred() def remove(id, envs, path): try: Registry.DBPOOL.close() envName = envs[id].name envPath = os.path.join(path, envName) #self.environments[envName].shutdown() del envs[id] if os.path.isdir(envPath): shutil.rmtree(envPath) #self.logger.critical("Removed and deleted envrionment: '%s' at : '%s'",envName,envPath) log.msg("Removed environment ", envName, "with id ", id, system="environment manager", logLevel=logging.CRITICAL) except: pass #should raise specific exception #raise Exception("failed to delete env") d.addCallback(remove, self.environments, self.path) reactor.callLater(0, d.callback, id) return d @defer.inlineCallbacks def clear_environments(self): """ Removes & deletes ALL the environments, should be used with care """ print(self.environments) for env in self.environments.values(): yield self.remove_environment(env.id) defer.returnValue(None) """ #################################################################################### Helper Methods """ @defer.inlineCallbacks def force_id(self, id): query = '''UPDATE environments SET id =''' + str( id) + ''' where id=1''' yield Registry.DBPOOL.runQuery(query) defer.returnValue(None) @defer.inlineCallbacks def _generateMasterDatabase(self): yield Registry.DBPOOL.runQuery('''CREATE TABLE environments( id INTEGER PRIMARY KEY , name TEXT, status TEXT NOT NULL DEFAULT "Live", description TEXT )''') @defer.inlineCallbacks def _generateDatabase(self): yield Registry.DBPOOL.runQuery('''CREATE TABLE addons( id INTEGER PRIMARY KEY, name TEXT, description TEXT, active boolean NOT NULL default true )''') yield Registry.DBPOOL.runQuery('''CREATE TABLE environments( id INTEGER PRIMARY KEY, name TEXT, description TEXT, status TEXT NOT NULL DEFAULT "Live" )''') yield Registry.DBPOOL.runQuery('''CREATE TABLE nodes( id INTEGER PRIMARY KEY AUTOINCREMENT, environment_id INTEGER NOT NULL, type TEXT NOT NULL , name TEXT, description TEXT, recipe TEXT, FOREIGN KEY(environment_id) REFERENCES environments(id) )''') #FOREIGN KEY(node_id) REFERENCES nodes(id) yield Registry.DBPOOL.runQuery('''CREATE TABLE drivers( id INTEGER PRIMARY KEY AUTOINCREMENT, node_id INTEGER NOT NULL, driverType TEXT NOT NULL, deviceType TEXT NOT NULL , deviceId TEXT, options BLOB , FOREIGN KEY(node_id) REFERENCES nodes(id) )''') yield Registry.DBPOOL.runQuery('''CREATE TABLE tasks( id INTEGER PRIMARY KEY AUTOINCREMENT, environment_id INTEGER NOT NULL, name TEXT, description TEXT, type TEXT, params TEXT, FOREIGN KEY(environment_id) REFERENCES environments(id) )''') yield Registry.DBPOOL.runQuery('''CREATE TABLE actions( id INTEGER PRIMARY KEY AUTOINCREMENT, task_id INTEGER NOT NULL, actionType TEXT, params TEXT, FOREIGN KEY(task_id) REFERENCES tasks(id) )''') yield Registry.DBPOOL.runQuery('''CREATE TABLE conditions( id INTEGER PRIMARY KEY AUTOINCREMENT, task_id INTEGER NOT NULL, name TEXT, description TEXT, FOREIGN KEY(task_id) REFERENCES tasks(id) )''') yield Registry.DBPOOL.runQuery('''CREATE TABLE sensors( id INTEGER PRIMARY KEY AUTOINCREMENT, node_id INTEGER NOT NULL, captureType TEXT NOT NULL, captureMode TEXT NOT NULL DEFAULT "Analog", type TEXT NOT NULL , realName TEXT NOT NULL, name TEXT, description TEXT, FOREIGN KEY(node_id) REFERENCES nodes(id) )''') yield Registry.DBPOOL.runQuery('''CREATE TABLE readings( id INTEGER PRIMARY KEY AUTOINCREMENT, node_id INTEGER NOT NULL, sensor_id INTEGER NOT NULL, data INTEGER NOT NULL, dateTime TEXT NOT NULL, FOREIGN KEY(node_id) REFERENCES nodes(id), FOREIGN KEY(sensor_id) REFERENCES sensors(id) )''') """this should be in the master db, but will have to do for now (only support for one environment, because of the limitations of twistar: one db )""" yield Registry.DBPOOL.runQuery('''CREATE TABLE updates( id INTEGER PRIMARY KEY AUTOINCREMENT, type TEXT NOT NULL, name TEXT NOT NULL, description TEXT, version TEXT NOT NULL, downloadUrl TEXT NOT NULL, tags TEXT NOT NULL, img TEXT NOT NULL, file TEXT NOT NULL, fileHash TEXT NOT NULL, downloaded TEXT NOT NULL, installed TEXT NOT NULL, enabled TEXT NOT NULL )''') defer.returnValue(None)