Exemple #1
0
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
Exemple #2
0
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
Exemple #3
0
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)
Exemple #4
0
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")
Exemple #5
0
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)
Exemple #6
0
from kervi.spine import Spine

spine = Spine()
spine.send_command("signalModuleLoad", "test_x")
Exemple #7
0
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")
Exemple #8
0
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")
Exemple #9
0
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)