diff --git a/src/octoprint/cli/client.py b/src/octoprint/cli/client.py index c1ce9df0..7fe824d2 100644 --- a/src/octoprint/cli/client.py +++ b/src/octoprint/cli/client.py @@ -39,32 +39,7 @@ def client_commands(): def client(obj, host, port, httpuser, httppass, https, prefix): """Basic API client.""" obj.settings = init_settings(obj.basedir, obj.configfile) - - settings_host = obj.settings.get(["server", "host"]) - settings_port = obj.settings.getInt(["server", "port"]) - settings_apikey = obj.settings.get(["api", "key"]) - - octoprint_client.apikey = settings_apikey - octoprint_client.baseurl = build_base_url(https=https, - httpuser=httpuser, - httppass=httppass, - host=host or settings_host if settings_host != "0.0.0.0" else "127.0.0.1", - port=port or settings_port, - prefix=prefix) - - -def build_base_url(https=False, httpuser=None, httppass=None, host=None, port=None, prefix=None): - protocol = "https" if https else "http" - httpauth = "{}:{}@".format(httpuser, httppass) if httpuser and httppass else "" - host = host if host else "127.0.0.1" - port = ":{}".format(port) if port else ":5000" - prefix = prefix if prefix else "" - - return "{}://{}{}{}{}".format(protocol, httpauth, host, port, prefix) - - -def build_url(obj, path): - return "{}/{}".format(build_base_url(obj), path) + octoprint_client.init_client(obj.settings, https=https, httpuser=httpuser, httppass=httppass, host=host, port=port, prefix=prefix) def log_response(response, status_code=True, body=True, headers=False): @@ -143,7 +118,7 @@ def command(path, command, str_params, int_params, float_params, bool_params): params = str_params + int_params + float_params + bool_params for param in params: data[param[0]] = param[1] - r = octoprint_client.post_command(path, command, parameters=data) + r = octoprint_client.post_command(path, command, additional=data) log_response(r, body=False) @@ -159,7 +134,7 @@ def upload(path, file_path, params, file_name, content_type): for param in params: data[param[0]] = param[1] - r = octoprint_client.upload(path, file_path, parameters=data, file_name=file_name, content_type=content_type) + r = octoprint_client.upload(path, file_path, additional=data, file_name=file_name, content_type=content_type) log_response(r) diff --git a/src/octoprint_client/__init__.py b/src/octoprint_client/__init__.py index b91116ed..7134d115 100644 --- a/src/octoprint_client/__init__.py +++ b/src/octoprint_client/__init__.py @@ -10,17 +10,41 @@ import requests apikey = None baseurl = None -def prepare_request(method=None, path=None): +def build_base_url(https=False, httpuser=None, httppass=None, host=None, port=None, prefix=None): + protocol = "https" if https else "http" + httpauth = "{}:{}@".format(httpuser, httppass) if httpuser and httppass else "" + host = host if host else "127.0.0.1" + port = ":{}".format(port) if port else ":5000" + prefix = prefix if prefix else "" + + return "{}://{}{}{}{}".format(protocol, httpauth, host, port, prefix) + + +def init_client(settings, https=False, httpuser=None, httppass=None, host=None, port=None, prefix=None): + settings_host = settings.get(["server", "host"]) + settings_port = settings.getInt(["server", "port"]) + settings_apikey = settings.get(["api", "key"]) + + global apikey, baseurl + apikey = settings_apikey + baseurl = build_base_url(https=https, + httpuser=httpuser, + httppass=httppass, + host=host or settings_host if settings_host != "0.0.0.0" else "127.0.0.1", + port=port or settings_port, + prefix=prefix) + +def prepare_request(method=None, path=None, params=None): url = None if baseurl: while path.startswith("/"): path = path[1:] url = baseurl + "/" + path - return requests.Request(method=method, url=url, headers={"X-Api-Key": apikey}).prepare() + return requests.Request(method=method, url=url, params=params, headers={"X-Api-Key": apikey}).prepare() -def request(method, path, data=None, files=None, encoding=None): +def request(method, path, data=None, files=None, encoding=None, params=None): s = requests.Session() - request = prepare_request(method, path) + request = prepare_request(method, path, params=params) if data or files: if encoding == "json": request.prepare_body(None, None, json=data) @@ -29,22 +53,22 @@ def request(method, path, data=None, files=None, encoding=None): response = s.send(request) return response -def get(path): - return request("GET", path) +def get(path, params=None): + return request("GET", path, params=params) -def post(path, data, encoding=None): - return request("POST", path, data=data, encoding=encoding) +def post(path, data, encoding=None, params=None): + return request("POST", path, data=data, encoding=encoding, params=params) -def post_json(path, data): - return post(path, data, encoding="json") +def post_json(path, data, params=None): + return post(path, data, encoding="json", params=params) -def post_command(path, command, parameters=None): +def post_command(path, command, additional=None): data = dict(command=command) - if parameters: - data.update(parameters) - return post_json(path, data) + if additional: + data.update(additional) + return post_json(path, data, params=params) -def upload(path, file_path, parameters=None, file_name=None, content_type=None): +def upload(path, file_path, additional=None, file_name=None, content_type=None, params=None): import os if not os.path.isfile(file_path): @@ -59,15 +83,63 @@ def upload(path, file_path, parameters=None, file_name=None, content_type=None): else: files = dict(file=(file_name, fp)) - response = request("POST", path, data=parameters, files=files) + response = request("POST", path, data=additional, files=files, params=params) return response -def delete(path): - return request("DELETE", path) +def delete(path, params=None): + return request("DELETE", path, params=params) -def patch(path, data, encoding=None): - return request("PATCH", path, data=data, encoding=encoding) +def patch(path, data, encoding=None, params=None): + return request("PATCH", path, data=data, encoding=encoding, params=params) -def put(path, data, encoding=None): - return request("PUT", path, data=data, encoding=encoding) +def put(path, data, encoding=None, params=None): + return request("PUT", path, data=data, encoding=encoding, params=params) + +def connect_socket(**kwargs): + import uuid + import random + import threading + import websocket + import json + + url = "ws://{}/sockjs/{:0>3d}/{}/websocket".format(baseurl[baseurl.find("//") + 2:], random.randrange(0, stop=999), uuid.uuid4()) + + on_message_cb = kwargs.get("on_message", None) + on_close_cb = kwargs.get("on_close", None) + on_error_cb = kwargs.get("on_error", None) + + def on_message(ws, message): + if not callable(on_message_cb): + return + + if message.startswith(u"a["): + data = json.loads(message[2:-1]) + for msg_type, msg in data.items(): + on_message_cb(ws, msg_type, msg) + + def on_close(ws): + if callable(on_close_cb): + on_close_cb(ws) + + def on_error(ws, error): + if callable(on_error_cb): + on_error_cb(ws, error) + + ws = websocket.WebSocketApp(url, + on_message=on_message, + on_close=on_close, + on_error=on_error) + + class WebSocketThread(threading.Thread): + def __init__(self, ws): + threading.Thread.__init__(self) + self.ws = ws + + def run(self): + self.ws.run_forever() + + thread = WebSocketThread(ws) + thread.start() + + return thread