class Settings(object): """ Class that persists settings to the Kervi database. :param group: To avoid name clash with other settings in the Kervi application enter name to group your settings under. :type group: ``str`` """ def __init__(self, settings_group=None): self.group = settings_group self.spine = Spine() def store_value(self, name, value): """Store a value to DB""" self.spine.send_command("storeSetting", self.group, name, value) def retrieve_value(self, name, default_value=None): """Retrieve a value from DB""" value = self.spine.send_query("retrieveSetting", self.group, name, processes=["kervi-main"]) if value is None: return default_value elif isinstance(value, list) and len(value) == 0: return default_value elif isinstance(default_value, int): return int(value) elif isinstance(default_value, float): return float(value) else: return value
def open_file(source, file_type, file_name, metadata=None): from kervi.spine import Spine spine = Spine() file_id = str(uuid.uuid4()) spine.send_command("files_open_file", file_id, source, file_type, file_name, metadata) return file_id
class _Messaging(object): def __init__(self): self.spine = Spine() pass def send_message(self, subject, **kwargs): #kwargs = dict(kwargs, run_async=True) #Actions["message_manager.send_message"](subject, **kwargs) self.spine.send_command("messageManagerSend", subject, **kwargs)
class Authorization: def __init__(self): self._spine = Spine() self._active = None @property def active(self): if self._active == None: self._active = self._spine.send_query("authorizationActive") return self._active def authorize(self, user_name, password): user = self._spine.send_query("authorizationAuthorizeUser", user_name, password) return user def allow_anonymous(self): return self._spine.send_query("authorizationAllowAnonymousUser") def valid_session_header(self, headers): return self._spine.send_query("authorizationValidSessionHeader", headers) def remove_session(self, session_id): return self._spine.send_command("authorizationRemoveSession", session_id) def get_users(self): return self._spine.send_query("authorizationGetUsers")
class _LinkedAction(object): def __init__(self, action_id): self._action_id = action_id self.spine = Spine() self.spine.register_event_handler("actionDone", self._action_done, action_id) self.spine.register_event_handler("actionStarted", self._action_started, action_id) self.spine.register_query_handler("getComponentRoutes", self._get_component_bus_routes) self._state = ACTION_STOPPED self._action_event = None self._action_lock = threading.Lock() self._process_locked = False self._is_running = False self._last_result = None self._observers = [] self._spine_observers = {} def _get_component_bus_routes(self): return { "id": None, "routes": [{ "id": self._action_id, "direction": "in", "topic_type": "event", "topic": "actionStarted" }, { "id": self._action_id, "direction": "in", "topic_type": "event", "topic": "actionDone" }, { "id": self._action_id, "direction": "out", "topic_type": "command", "topic": "kervi_action_" + self._action_id }], } def _action_done(self, id, state, result): if self._state == ACTION_RUNNING: self._state = state self._last_result = result if self._action_event: self._action_event.set() if self._process_locked: self._process_locked = False self._action_lock.release() self._is_running = False def _action_started(self, id): self._state = ACTION_RUNNING self._last_result = None self._is_running = True if self._action_lock.acquire(False): self._process_locked = True def run_every(self, interval=1): """ Schedule an action to run periodically. :param interval: A quantity of a certain time unit """ job = ActionJob(interval, default_scheduler, self) return job @property def is_running(self): return self._is_running @property def state(self): """Returns the running state of the action.""" return self._state def interrupt(self, *args, **kwargs): self.spine.send_command("kervi_action_interrupt_" + self._action_id, *args, **kwargs) def execute(self, *args, **kwargs): """Executes the action.""" timeout = kwargs.pop("timeout", -1) run_async = kwargs.pop("run_async", False) self._is_running = True result = None if self._action_lock.acquire(False): self._state = ACTION_PENDING self._action_event = threading.Event() self.spine.send_command("kervi_action_" + self._action_id, *args, **kwargs) if not run_async: if self._action_event.wait(timeout): self._state = ACTION_FAILED raise TimeoutError("Timeout in call to action: " + self._action_id) self._action_event = None result = self._last_result else: self._action_lock.release() else: if not self._action_lock.acquire(True, timeout): return None self._action_lock.release() return result def __call__(self, *args, **kwargs): self.execute(*args, **kwargs) def link_to(self, source, **kwargs): from kervi.values.kervi_value import KerviValue if isinstance(source, KerviValue): source.add_observer(self) self._spine_observers[source.value_id] = kwargs elif isinstance(source, str): self.spine.register_event_handler("valueChanged", self._link_changed_event, source) self._spine_observers[source] = kwargs def kervi_value_changed(self, source, value): self._link_changed_event(source.value_id, { "id": source.value_id, "value": source.value }, value) def _link_changed_event(self, id, source, old_value): if source["id"] in self._spine_observers.keys(): kwargs = self._spine_observers[source["id"]] value = source["value"] self._handle_link_event(value, **kwargs) def _handle_link_event(self, value, **kwargs): pass_value = kwargs.pop("pass_value", False) trigger_value = kwargs.pop("trigger_value", True) trigger_interrupt_value = kwargs.pop("trigger_interrupt_value", False) action_parameters = kwargs.pop("action_parameters", []) interrupt_parameters = kwargs.pop("interrupt_parameters", []) if pass_value: action_parameters = [value] + action_parameters if isinstance(trigger_value, types.LambdaType) and trigger_value( value) and not self.is_running: self.execute(*action_parameters, run_async=True) if isinstance(trigger_interrupt_value, types.LambdaType ) and trigger_interrupt_value(value) and self.is_running: self.interrupt(*interrupt_parameters) elif trigger_value == value and not self.is_running: self.execute(*action_parameters, run_async=True) elif trigger_interrupt_value == value and self.is_running: self.interrupt(*interrupt_parameters)
from kervi.spine import Spine spine = Spine() spine.send_command("signalModuleLoad", "test_x")
class _SpineProtocol(WebSocketServerProtocol): def __init__(self): self.spine = Spine() WebSocketServerProtocol.__init__(self) self.handlers = {"command": [], "query": [], "event": []} self.authenticated = False self.session = None self.user = None self._authorization = Authorization() def add_command_handler(self, command): found = False for command_handler in self.handlers["command"]: if command_handler.command == command: found = True if not found: self.handlers["command"] += [_WebCommandHandler(command, self)] def add_query_handler(self, query): found = False for query_handler in self.handlers["query"]: if query_handler.query == query: found = True if not found: self.handlers["query"] += [_WebQueryHandler(query, self)] def add_event_handler(self, event, id_event): #print("ah", event, id_event) found = False for event_handler in self.handlers["event"]: if event_handler.event == event and event_handler.id_event == id_event: found = True if not found: self.handlers["event"] += [_WebEventHandler(event, id_event, self)] def send_response(self, id, response, state="ok", message=""): res = { "id": id, "messageType": "response", "state": state, "message": message, "response": response } jsonres = json.dumps(res, ensure_ascii=False).encode('utf8') self.sendMessage(jsonres, False) def onConnect(self, request): #print("Web socket Client connecting: {}".format(request.peer)) pass def onOpen(self): if self._authorization.active: res = {"messageType": "authenticate"} else: self.authenticated = True res = { "messageType": "session_authenticated", "session": "123456", } jsonres = json.dumps(res, ensure_ascii=False).encode('utf8') self.sendMessage(jsonres, False) def onMessage(self, payload, is_binary): try: obj = json.loads(payload.decode('utf8')) if obj["messageType"] == "authenticate": session, user = self._authorization.authorize( obj["userName"], obj["password"]) if session is None: print("authorization failed for:", obj["userName"]) res = { "messageType": "authentication_failed", } #self.close() else: self.session = session self.user = user self.authenticated = True res = { "messageType": "session_authenticated", "session": session, } jsonres = json.dumps(res, ensure_ascii=False).encode('utf8') self.sendMessage(jsonres, False) elif obj["messageType"] == "logoff": self.authenticated = False self.session = None self._authorization.remove_session(obj["session"]) res = {"messageType": "session_logoff"} jsonres = json.dumps(res, ensure_ascii=False).encode('utf8') self.sendMessage(jsonres, False) else: self.spine.log.debug("WS onMessage:{0}", obj) if not self.authenticated: pass elif obj["messageType"] == "query": res = self.spine.send_query(obj["query"], *obj["args"], injected="socketSpine", session=self.user) self.spine.log.debug("query response:{0}", res) self.send_response(obj["id"], res) elif obj["messageType"] == "registerQueryHandler": self.add_query_handler(obj["query"]) self.send_response(None, None) elif obj["messageType"] == "command": self.spine.send_command(obj["command"], *obj["args"], injected="socketSpine", session=self.user) self.send_response(obj["id"], None) elif obj["messageType"] == "registerCommandHandler": self.add_command_handler(obj["command"]) self.send_response(obj["id"], None) elif obj["messageType"] == "event": self.spine.trigger_event(obj["event"], obj["id"], obj["args"], injected="socketSpine") self.send_response(obj["id"], None) elif obj["messageType"] == "registerEventHandler": self.add_event_handler(obj["event"], obj["eventId"]) self.send_response(obj["id"], None) except: self.spine.log.exception("WS onMessage exception")
class _SpineProtocol(WebSocketServerProtocol): loop = None def __init__(self): self.spine = Spine() WebSocketServerProtocol.__init__(self) self.handlers = {"command":[], "query":[], "event":[], "stream":[]} self.authenticated = False self.session = None self.user = None self._authorization = Authorization() @classmethod def broadcast_message(cls, connection, data, is_binary=False): #for c in set(cls.connections): cls.loop.call_soon_threadsafe(cls.sendMessage, connection, data, is_binary) def add_command_handler(self, command): found = False for command_handler in self.handlers["command"]: if command_handler.command == command: found = True if not found: self.handlers["command"] += [_WebCommandHandler(command, self)] def add_query_handler(self, query): found = False for query_handler in self.handlers["query"]: if query_handler.query == query: found = True if not found: self.handlers["query"] += [_WebQueryHandler(query, self)] def add_event_handler(self, event, id_event): found = False for event_handler in self.handlers["event"]: if event_handler.event == event and event_handler.id_event == id_event: found = True if not found: self.handlers["event"] += [_WebEventHandler(event, id_event, self)] def add_stream_handler(self, stream_id, stream_event): found = False for stream_handler in self.handlers["stream"]: if stream_handler.stream_id == stream_id: if stream_event and stream_handler.stream_event == stream_event: found = True elif not stream_event: found = True if not found: self.handlers["stream"] += [_WebStreamHandler(stream_id, stream_event, self)] def remove_stream_handler(self, stream_id, stream_event): #print("r", stream_id, stream_event) found_handler = None for stream_handler in self.handlers["stream"]: if stream_handler.stream_id == stream_id: if stream_event and stream_handler.stream_event == stream_event: found_handler = stream_handler elif not stream_event: found_handler = stream_handler if found_handler: found_handler.close() self.handlers["stream"].remove(found_handler) def send_response(self, id, response, state="ok", message=""): res = { "id":id, "messageType":"response", "state":state, "message":message, "response":response } jsonres = json.dumps(res, ensure_ascii=False).encode('utf8') self.sendMessage(jsonres, False) def onConnect(self, request): pass def onOpen(self): if self._authorization.active: res = { "messageType":"authenticate" } else: self.authenticated = True res = { "messageType":"session_authenticated", "session":"123456", } jsonres = json.dumps(res, ensure_ascii=False).encode('utf8') self.sendMessage(jsonres, False) # @asyncio.coroutine # def async_query(self, query, query_args, injected, session): # def do_req(): # return self.spine.send_query(query, *query_args, injected=injected, session=session) # #self.spine.log.debug("query response:{0}", res) # #self.send_response(obj["id"], res) # #return requests.get('https://api.github.com/user', auth=HTTPBasicAuth('user', 'pass')) # req = self.loop.run_in_executor(None, do_req) # resp = yield from req # return resp def onMessage(self, payload, is_binary): try: obj = json.loads(payload.decode('utf8')) if obj["messageType"] == "authenticate": session, user = self._authorization.authorize(obj["userName"], obj["password"]) if session is None: if obj["userName"] == "anonymous": self.spine.log.warning("Anonymous user disabled") else: self.spine.log.warning("authorization failed for: %s", obj["userName"]) res = { "messageType":"authentication_failed", } #self.close() else: self.session = session self.user = user self.authenticated = True res = { "messageType":"session_authenticated", "session":session, } jsonres = json.dumps(res, ensure_ascii=False).encode('utf8') self.sendMessage(jsonres, False) elif obj["messageType"] == "logoff": self.authenticated = False self.session = None self._authorization.remove_session(obj["session"]) res = { "messageType":"session_logoff" } jsonres = json.dumps(res, ensure_ascii=False).encode('utf8') self.sendMessage(jsonres, False) else: #self.spine.log.debug("WS onMessage:{0}", obj) if not self.authenticated: pass elif obj["messageType"] == "query": #res = yield from self.async_query(obj["query"], obj["args"], injected="socketSpine", session=self.user) res = self.spine.send_query(obj["query"], *obj["args"], injected="socketSpine", session=self.user) self.spine.log.debug("query response:{0}", res) self.send_response(obj["id"], res) elif obj["messageType"] == "registerQueryHandler": self.add_query_handler(obj["query"]) self.send_response(None, None) elif obj["messageType"] == "command": self.spine.send_command(obj["command"], *obj["args"], injected="socketSpine", session=self.user) self.send_response(obj["id"], None) elif obj["messageType"] == "registerCommandHandler": self.add_command_handler(obj["command"]) self.send_response(obj["id"], None) elif obj["messageType"] == "event": self.spine.trigger_event( obj["event"], obj["id"], obj["args"], injected="socketSpine" ) self.send_response(obj["id"], None) elif obj["messageType"] == "registerEventHandler": self.add_event_handler(obj["event"], obj["eventId"]) self.send_response(obj["id"], None) elif obj["messageType"] == "registerStreamHandler": self.add_stream_handler(obj["streamId"], obj["streamEvent"]) self.send_response(obj["id"], None) elif obj["messageType"] == "removeStreamHandler": self.remove_stream_handler(obj["streamId"], obj["streamEvent"]) self.send_response(obj["id"], None) except: self.spine.log.exception("WS onMessage exception")
def save_file(source, file_type, file_name, data_io, metadata=None): from kervi.spine import Spine spine = Spine() spine.send_command("files_save_file", source, file_type, file_name, metadata, data_io)