diff --git a/.buildinfo b/.buildinfo new file mode 100644 index 0000000..097f75c --- /dev/null +++ b/.buildinfo @@ -0,0 +1,4 @@ +# Sphinx build info version 1 +# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. +config: 959aa8e1cbad269255e4be71235447d9 +tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/_modules/index.html b/_modules/index.html new file mode 100644 index 0000000..94964e5 --- /dev/null +++ b/_modules/index.html @@ -0,0 +1,114 @@ + + + +
+ + +
+#!/usr/bin/python
+# coding: utf8
+
+from enum import Enum
+
+import requests
+
+INTEGRATION_API_V2_BASE_URL = "https://api.smaxtec.com/integration/v2"
+
+
+
+
+
+
+
+[docs]
+class BaseAPI(object):
+ def __init__(
+ self,
+ base_url,
+ email=None,
+ password=None,
+ api_token=None,
+ api_type=None,
+ ):
+ """Initialize a new base low level API client instance."""
+ self.api_base_url = base_url.rstrip("/")
+ self.email = email
+ self.password = password
+ self.api_token = api_token
+ self.api_type = api_type
+ self._session = None
+
+
+
+
+ @property
+ def session(self):
+ """
+ Geneates a new HTTP session on the fly and logs in if no session exists.
+ """
+ if self._session is None:
+ self._session = requests.Session()
+ self._login()
+ return self._session
+
+
+
+
+ def _login(self):
+ """
+ Login to the api with api key or the given credentials.
+ """
+ if self.api_token is not None:
+ self._session.headers.update({"Authorization": f"Bearer {self.api_token}"})
+ else:
+ params = {"user": self.email, "password": self.password}
+ response = requests.Response
+ if self.api_type == ApiTypes.PUBLIC:
+ response = self._session.post(
+ self.to_url("/users/credentials"), params=params
+ )
+ self.api_token = response.json().get("api_token", None)
+ elif self.api_type == ApiTypes.INTEGRATION:
+ response = self._session.post(
+ self.to_url("/users/session_token"), params=params
+ )
+ self.api_token = response.json().get("token", None)
+ if self.api_token is None:
+ raise requests.HTTPError(response.status_code, response.reason)
+ self._session.headers.update({"Authorization": f"Bearer {self.api_token}"})
+
+
+[docs]
+ def get(self, path, *args, **kwargs):
+ url = self.to_url(path)
+ r = self.session.get(url, *args, **kwargs)
+ return r.json()
+
+
+
+[docs]
+ def post(self, path, *args, **kwargs):
+ url = self.to_url(path)
+ r = self.session.post(url, *args, allow_redirects=False, **kwargs)
+ return r.json()
+
+
+
+[docs]
+ def put(self, path, *args, **kwargs):
+ url = self.to_url(path)
+ r = self.session.put(url, *args, allow_redirects=False, **kwargs)
+ return r.json()
+
+
+
+[docs]
+ def delete(self, path, *args, **kwargs):
+ url = self.to_url(path)
+ r = self.session.delete(url, *args, **kwargs)
+ return r.json()
+
+
+
+
+
+[docs]
+class IntegrationAPIV2(BaseAPI):
+ def __init__(self, base_url=None, email=None, password=None, api_token=None):
+ """Initialize a new integration api client instance."""
+ base_url = base_url or INTEGRATION_API_V2_BASE_URL
+ api_type = ApiTypes.INTEGRATION
+ super().__init__(
+ base_url,
+ email=email,
+ password=password,
+ api_token=api_token,
+ api_type=api_type,
+ )
+
+
+import argparse
+import configparser
+import os
+import sys
+from os.path import (
+ abspath,
+ expanduser,
+)
+
+from setuptools import setup
+
+from sxapi.cli import cli_user
+from sxapi.cli.subparser.get_sensor_data import create_gsd_parser
+from sxapi.cli.subparser.token import create_token_parser
+
+
+
+[docs]
+class Cli:
+ """CLI class for handling arguments and calling the API."""
+
+ def __init__(self):
+ self.config_file_paths = ["/etc/sxapi.conf", "~/.config/sxapi.conf"]
+
+
+[docs]
+ @staticmethod
+ def update_config_with_env(config_dict):
+ config_dict["user"] = os.getenv("SXAPI_USER", config_dict["user"])
+ config_dict["pwd"] = os.getenv("SXAPI_PASSWORD", config_dict["pwd"])
+ config_dict["orga"] = os.getenv("SXAPI_ORGA", config_dict["orga"])
+ config_dict["api_public_v2_path"] = os.getenv(
+ "SXAPI_API_PUBLIC_V2_PATH", config_dict["api_public_v2_path"]
+ )
+ config_dict["api_integration_v2_path"] = os.getenv(
+ "SXAPI_API_INTEGRATION_V2_PATH", config_dict["api_integration_v2_path"]
+ )
+
+
+
+[docs]
+ def read_config_from_file(self, config_file_path):
+ config_dict = {
+ "user": None,
+ "pwd": None,
+ "orga": None,
+ "api_public_v2_path": None,
+ "api_integration_v2_path": None,
+ }
+
+ if config_file_path:
+ self.config_file_paths.append(config_file_path)
+
+ parsable_files = []
+ for config_file in self.config_file_paths:
+ config_file = expanduser(config_file)
+ config_file = abspath(config_file)
+ parsable_files.append(config_file)
+
+ try:
+ config = configparser.ConfigParser(interpolation=None)
+ config.read(parsable_files)
+
+ config_dict["user"] = config.get("SXAPI", "USER")
+ config_dict["pwd"] = config.get("SXAPI", "PASSWORD")
+ config_dict["orga"] = config.get("SXAPI", "ORGA")
+ config_dict["api_public_v2_path"] = config.get(
+ "SXAPI", "API_PUBLIC_V2_PATH"
+ )
+ config_dict["api_integration_v2_path"] = config.get(
+ "SXAPI", "API_INTEGRATION_V2_PATH"
+ )
+ except (
+ KeyError,
+ configparser.NoSectionError,
+ configparser.MissingSectionHeaderError,
+ ) as e:
+ if config_file_path:
+ print(f"Error while reading config file: {e}")
+ return
+ # we should raise custom exception here
+
+ return config_dict
+
+
+
+[docs]
+ @staticmethod
+ def api_status():
+ """
+ Print online status of api/v2 and integration/v2
+ """
+
+ if not cli_user.api_access_token:
+ print("No credentials set. Use --help for more information.")
+ return
+
+ pub_resp = cli_user.public_v2_api.get("/service/status")
+ int_resp = cli_user.integration_v2_api.get("/service/status")
+
+ exit_code = 0
+
+ if not (pub_resp["result"] == "ok" and int_resp["result"] == "ok"):
+ exit_code = 1
+
+ print(f"PublicV2 status: {pub_resp['result']}")
+ print(f"IntegrationV2 status: {int_resp['result']}")
+
+ exit(exit_code)
+
+
+
+[docs]
+ @staticmethod
+ def version_info():
+ """Print version info."""
+ setup(use_scm_version={"version_scheme": "no-guess-dev"})
+
+
+
+[docs]
+ @staticmethod
+ def parse_args(args):
+ """
+ Parse arguments from the CLI and initializes subparsers.
+ """
+ main_parser = argparse.ArgumentParser(
+ description=(
+ "Issue calls to the smaXtec system API to import and export data."
+ )
+ )
+ main_parser.add_argument(
+ "--version",
+ action="store_true",
+ default=False,
+ help="print version info and exit.",
+ )
+ main_parser.add_argument(
+ "--status",
+ action="store_true",
+ default=False,
+ help="prints status of api/V2 and integration/v2",
+ )
+ main_parser.add_argument(
+ "-t",
+ "--arg_token",
+ type=str,
+ help="Access Token",
+ )
+ main_parser.add_argument(
+ "-k",
+ "--use_keyring",
+ action="store_true",
+ help="Use keyring as token source!",
+ )
+ main_parser.add_argument(
+ "-c", "--configfile", type=str, help="Path to config file"
+ )
+ main_parser.add_argument(
+ "--print-configfile",
+ action="store_true",
+ help="Print example config file and exits",
+ )
+
+ # gsd_parser
+ subparsers = main_parser.add_subparsers(help="sub-command help")
+ create_gsd_parser(subparsers)
+ create_token_parser(subparsers)
+
+ if not args:
+ main_parser.print_help()
+ return
+ return main_parser.parse_args(args)
+
+
+
+[docs]
+ def run(self):
+ """Call sxapi functions based on passed arguments."""
+ args = self.parse_args(sys.argv[1:])
+ if not args:
+ return 0
+
+ if args.print_configfile:
+ with open("./src/sxapi/cli/example-config.conf", "r") as f:
+ print(f.read())
+ return
+
+ config_dict = self.read_config_from_file(args.configfile or None)
+
+ self.update_config_with_env(config_dict)
+
+ cli_user.init_user(config_dict, args.arg_token, args.use_keyring)
+
+ if args.status:
+ self.api_status()
+
+ if args.version:
+ self.version_info()
+
+ if args.use_keyring and args.arg_token:
+ print("Choose either -k (keyring), -t (argument) or no flag (environment)!")
+ return
+
+ # run set_defaults for subparser
+ if hasattr(args, "func"):
+ args.func(args)
+
+
+
+
+
+
+
+import os
+
+import keyring
+
+from sxapi.base import IntegrationAPIV2
+from sxapi.publicV2 import PublicAPIV2
+
+
+
+[docs]
+class CliUser:
+ """
+ CliUser class used for initializing, storing, retrieving and deleting
+ credentials and creating/holding Instances of supported API
+ Client.
+
+ This class should only be used in the cli package.
+ """
+
+ def __init__(self):
+ """
+ Basic User Credentials Constructor
+
+ calls self._init_creds() to set available credentials on startup.
+ """
+
+ self.api_access_token = None
+ self.public_v2_api = None
+ self.integration_v2_api = None
+
+
+[docs]
+ @staticmethod
+ def get_token_environment():
+ """
+ Gets token named 'SMAXTEC_API_ACCESS_TOKEN' from the systems' environment.
+ """
+
+ return os.environ.get("SMAXTEC_API_ACCESS_TOKEN", None)
+
+
+
+[docs]
+ def set_token_keyring(self, token):
+ """
+ Store the given token in keyring.
+ """
+ keyring.set_password("sxapi", "SMAXTEC_API_ACCESS_TOKEN", token)
+ self.api_access_token = token
+
+
+
+[docs]
+ @staticmethod
+ def get_token_keyring():
+ """
+ Gets the token stored in the keyring.
+ """
+ return keyring.get_password("sxapi", "SMAXTEC_API_ACCESS_TOKEN")
+
+
+
+[docs]
+ @staticmethod
+ def clear_token_keyring():
+ """
+ Deletes the token from the keyring.
+ """
+ keyring.delete_password("sxapi", "SMAXTEC_API_ACCESS_TOKEN")
+
+
+ # general functions
+
+[docs]
+ def check_credentials_set(self):
+ """
+ Checks if token is already set.
+ """
+ if self.api_access_token is not None:
+ return True
+ return False
+
+
+
+[docs]
+ def init_user(self, config_dict, args_token, args_keyring):
+ """
+ This function retrieves the token from the specified resource
+ (keyring, environment or args) and initializes clients
+ of the supported APIs (PublicV2, IntegrationV2).
+
+ If no token can be found the token is retrieved via
+ the username and password.
+
+ If username and password are also missing, no credentials get
+ stored and not API clients are created.
+ """
+ if args_token:
+ self.api_access_token = args_token
+ elif args_keyring:
+ self.api_access_token = self.get_token_keyring()
+ else:
+ self.api_access_token = self.get_token_environment()
+
+ if self.api_access_token is None and config_dict["user"] and config_dict["pwd"]:
+ self.public_v2_api = PublicAPIV2(
+ base_url=config_dict["api_public_v2_path"],
+ email=config_dict["user"],
+ password=config_dict["pwd"],
+ )
+ self.integration_v2_api = IntegrationAPIV2(
+ base_url=config_dict["api_integration_v2_path"],
+ email=config_dict["user"],
+ password=config_dict["pwd"],
+ )
+
+ self.api_access_token = self.public_v2_api.get_token()
+
+ elif self.api_access_token:
+ self.public_v2_api = PublicAPIV2(
+ base_url=config_dict["api_public_v2_path"],
+ api_token=self.api_access_token,
+ )
+
+ self.integration_v2_api = IntegrationAPIV2(
+ base_url=config_dict["api_integration_v2_path"],
+ api_token=self.api_access_token,
+ )
+
+
+
+import json
+
+from sxapi.cli import cli_user
+from sxapi.publicV2.sensordata import get_sensor_data_from_animal
+
+
+
+[docs]
+def create_gsd_parser(subparsers):
+ """
+ get_sensor_data subparser for cli_tests.
+ Responsible for performing api-call to get the sensor data for a given animal.
+
+ The 'animals_id' is mandatory argument 'animal_id'.
+ It represents the animal you want to get data from.
+
+ The following flag are only optional.
+ The --metrics/-m Flag defines the metrics you want to get from the animal sensor.
+ It expects at most two arguments 'temp', 'act' or both together. Where 'temp' means
+ getting the temperature metric and 'act' means the activity metric.
+
+
+ The --from_date Flag defines the start-date of window you want to get data from.
+ It expects exactly one argument, a datetime in the format 'YYYY-MM-DD'
+ (e.g. 2022.01.12).
+
+ The --to_date Flag defines the end-date of window you want to get data from.
+ It expects exactly one argument, a datetime in the format 'YYYY-MM-DD'
+ (e.g. 2022.01.12).
+ """
+ gsd_parser = subparsers.add_parser(
+ "get_sensor_data",
+ aliases=["gsd"],
+ help="Get sensor data from animal(by its ID)",
+ )
+ gsd_parser.add_argument(
+ "animal_id",
+ help="Animal you want get data from",
+ )
+ gsd_parser.add_argument(
+ "--metrics",
+ "-m",
+ nargs="*",
+ default=None,
+ help="metrics for sensordata",
+ )
+ gsd_parser.add_argument(
+ "--from_date",
+ default=None,
+ nargs=1,
+ help="from_date format: YYYY-MM-DD",
+ )
+ gsd_parser.add_argument(
+ "--to_date",
+ default=None,
+ nargs=1,
+ help="to_date format: YYYY-MM-DD",
+ )
+
+ gsd_parser.set_defaults(func=gsd_sub_function)
+
+
+
+
+[docs]
+def gsd_sub_function(args):
+ """
+ The get_sensor_data subparser default function.
+ This function gets called if you get_sensor_data subparser is used.
+
+ Pares the given arguments and calls a function which
+ performs the desired api call.
+ """
+ if not cli_user.check_credentials_set():
+ print("No credentials set. Use --help for more information.")
+ return
+
+ api = cli_user.public_v2_api
+
+ id = args.animal_id
+ metrics = args.metrics
+ from_date = args.from_date
+ to_date = args.to_date
+ resp = get_sensor_data_from_animal(
+ api=api, animal_id=id, metrics=metrics, from_date=from_date, to_date=to_date
+ )
+ if resp is not None:
+ print(json.dumps(resp, indent=0))
+
+
+import getpass
+
+import requests
+
+from sxapi.cli import cli_user
+from sxapi.publicV2 import PublicAPIV2
+
+
+
+[docs]
+def create_token_parser(subparsers):
+ """
+ Token subparser for cli_tests.
+ Responsible for managing tokens/credentials.
+
+ The --print_token/-p Flag prints the token, stored in keyring or in
+ environment, to stdout. It expects exactly only one argument -> 'e'
+ for printing the token stored in the environment, 'k' for printing
+ the token stored in keyring and 'ek' for printing both at the same time.
+
+ The --set_keyring/-s flag stores the token (given as argument) in the keyring.
+ It expects exactly one argument -> the token you want to store.
+
+ The --clear_keyring/-c Flag deletes the token from the keyring.
+ This flag doesn't expect any argument.
+
+ The --new_token/-n Flag calls api to get new token and prints it to stdout.
+ It expects exactly two arguments -> smaxtec-username and smaxtec-password.
+
+ It is not possible to use more than one of those flags at the same time
+ """
+ token_parser = subparsers.add_parser(
+ "token",
+ help="Get/Set credentials aka 'SMAXTEC_API_ACCESS_TOKEN' from/to specified "
+ "storage location or create new one",
+ )
+
+ token_parser.add_argument(
+ "--print_token",
+ "-p",
+ nargs="?",
+ const="ek",
+ help="Print the current token stored in keyring/environment to stdout. "
+ "One argument required. Possible args 'e' environment | "
+ "'k' keyring | ek for printing both.",
+ )
+ token_parser.add_argument(
+ "--set_keyring",
+ "-s",
+ nargs=1,
+ help="Store the given token in keyring! Requires one argument <token>",
+ )
+ token_parser.add_argument(
+ "--new_token",
+ "-n",
+ nargs="+",
+ help="Reqeust new token. Requires one argument <username>, "
+ "second argument <password> is optional!",
+ )
+ token_parser.add_argument(
+ "--clear_keyring",
+ "-c",
+ action="store_true",
+ default=False,
+ help="Remove the token from keyring!",
+ )
+
+ token_parser.set_defaults(func=token_sub_function)
+
+
+
+
+[docs]
+def token_sub_function(args):
+ """
+ The token subparser default function.
+ This function gets called if token subparser is used.
+
+ Checks args and calls the specific helper function (see below) according to
+ the present flag.
+ """
+ number_op = (
+ bool(args.print_token)
+ + bool(args.set_keyring)
+ + bool(args.new_token)
+ + bool(args.clear_keyring)
+ )
+
+ if number_op > 1:
+ print(
+ "Invalid Combination! Please use just one out of these parameters "
+ "[--print_token, --set_keyring, --new_token, --clear_keyring]"
+ )
+ return
+
+ if args.print_token:
+ handle_print_token(args)
+ elif args.set_keyring:
+ handle_set_token(args)
+ elif args.clear_keyring:
+ handle_clear_token()
+ elif args.new_token:
+ handle_new_token(args)
+
+
+
+# Flag helper functions
+
+[docs]
+def handle_print_token(args):
+ """
+ Logic behind the token subparser --print_token flag.
+
+ Prints the token from the desired source (environment or keyring) to stdout.
+ """
+ keyring = str(cli_user.get_token_keyring())
+ env = str(cli_user.get_token_environment())
+
+ if args.print_token == "ek":
+ print(f"\nKeyring: {keyring}\n\nEnvironment: {env}")
+ return
+ elif len(args.print_token) > 2:
+ print("Invalid number of arguments. Use --help for usage information.")
+ return
+
+ if "e" != args.print_token and "k" != args.print_token:
+ print(
+ "Invalid arguments. Only use 'e' for environment, 'k' for keyring "
+ "or 'ek' for both."
+ )
+ return
+
+ if "e" == args.print_token:
+ print(f"\nEnvironment Token: {env}\n")
+ elif "k" == args.print_token:
+ print(f"\nKeyring Token: {keyring}\n")
+
+
+
+
+[docs]
+def handle_set_token(args):
+ """
+ Logic behind the token subparser --set_keyring flag.
+
+ Parses the args and stores the token in the keyring.
+ """
+ token = args.set_keyring[0]
+ cli_user.set_token_keyring(token=token)
+ print("Token is stored in keyring!")
+
+
+
+
+[docs]
+def handle_clear_token():
+ """
+ Logic behind the token subparser --clear_keyring flag.
+
+ Deletes the token from the keyring.
+ """
+ cli_user.clear_token_keyring()
+ print("Token was deleted from keyring!")
+
+
+
+
+[docs]
+def handle_new_token(args):
+ """
+ Logic behind the token subparser --new_token flag.
+
+ Parses the args, creates an PublicAPIV2 instance to get new token and
+ print the new token to stdout.
+ """
+ if len(args.new_token) == 2:
+ username = args.new_token[0] if "@" in args.new_token[0] else args.new_token[1]
+ pwd = args.new_token[1] if "@" not in args.new_token[1] else args.new_token[0]
+
+ if len(args.new_token) == 1:
+ username = args.new_token[0]
+ pwd = getpass.getpass()
+
+ if "@" not in username:
+ print("Username must be a email!")
+ return
+
+ try:
+ token = str(PublicAPIV2(email=username, password=pwd).get_token())
+ print("SMAXTEC_API_ACCESS_TOKEN=" + token)
+ except requests.HTTPError as e:
+ if "401" in str(e) or "422" in str(e):
+ print("Username or Password is wrong!")
+ except Exception as e:
+ print(e)
+
+
+from sxapi.base import (
+ ApiTypes,
+ BaseAPI,
+)
+from sxapi.publicV2.alarms import Alarms
+from sxapi.publicV2.data import Data
+from sxapi.publicV2.feedrations import Feedrations
+from sxapi.publicV2.groups import Groups
+from sxapi.publicV2.todos import Todos
+from sxapi.publicV2.users import Users
+
+PUBLIC_API_V2_BASE_URL = "https://api.smaxtec.com/api/v2"
+
+
+
+[docs]
+class PublicAPIV2(BaseAPI):
+ def __init__(self, base_url=None, email=None, password=None, api_token=None):
+ """Initialize a new public api client instance."""
+ base_url = base_url or PUBLIC_API_V2_BASE_URL
+ api_type = ApiTypes.PUBLIC
+
+ self.todos = Todos(api=self)
+ self.users = Users(api=self)
+ self.alarms = Alarms(api=self)
+ self.data = Data(api=self)
+ self.groups = Groups(api=self)
+ self.feedrations = Feedrations(api=self)
+
+ super().__init__(
+ base_url,
+ email=email,
+ password=password,
+ api_token=api_token,
+ api_type=api_type,
+ )
+
+
+
+[docs]
+class Alarms:
+ """
+ This class represents the /alarms API endpoint of the PublicAPIV2.
+ https://api.smaxtec.com/api/v2/
+ """
+
+ def __init__(self, api=None):
+ self.api = api
+ self.path_suffix = "/alarms"
+
+
+[docs]
+ def post(self, organisation_id, title, **kwargs):
+ """Creates a new alarm.
+
+ Args:
+ organisation_id (str): ID of organisation the alarm should be created for
+ title (str): Title of the alarm
+ **kwargs: Optional parameters of the API call.
+ Find supported parameters under
+ https://api.smaxtec.com/api/v2/
+
+ Returns:
+ dict: Response of API call. Created alarm on success, error message else.
+
+ """
+ params = {
+ "organisation_id": organisation_id,
+ "title": title,
+ }
+
+ for k, v in kwargs.items():
+ params[k] = v
+
+ return self.api.post(self.path_suffix, json=params)
+
+
+
+[docs]
+ def get_categories(self, **kwargs):
+ """Get all alarms categories for a user or organisation.
+ If no user or organisation is given, this
+ function return a BadRequestError
+
+ Args:
+ **kwargs: Optional parameters of the API call.
+ Find supported parameters under
+ https://api.smaxtec.com/api/v2/
+
+ Returns:
+ dict: Response of API call. List of alarms on success, error message else.
+
+ """
+ params = {}
+
+ for k, v in kwargs.items():
+ params[k] = v
+
+ url_suffix = self.path_suffix + "/categories"
+ return self.api.get(url_suffix, json=params)
+
+
+
+[docs]
+ def put(self, alarm_id, organisation_id, **kwargs):
+ """Updates an existing alarm.
+
+ Args:
+ alarm_id (str): ID of the alarm which should be updated.
+ organisation_id (str): ID of organisation the alarm should be updated for
+ **kwargs: Optional parameters of the API call.
+ Find supported parameters under
+ https://api.smaxtec.com/api/v2/
+
+ Returns:
+ dict: Response of API call. Updated alarm on success, error message else.
+
+ """
+ params = {
+ "organisation_id": organisation_id,
+ }
+ for k, v in kwargs.items():
+ params[k] = v
+
+ url_suffix = self.path_suffix + f"/{alarm_id}"
+ return self.api.put(url_suffix, json=params)
+
+
+
+[docs]
+ def get(self, alarm_id, **kwargs):
+ """Get one alarm.
+
+ Args:
+ alarm_id (str): ID of the desired alarm
+ **kwargs: Optional parameters of the API call.
+ Find supported parameters under
+ https://api.smaxtec.com/api/v2/
+
+ Returns:
+ dict: Response of API call. Queried alarm on success, error message else.
+
+ """
+ params = {}
+
+ for k, v in kwargs.items():
+ params[k] = v
+
+ url_suffix = self.path_suffix + f"/{alarm_id}"
+ return self.api.get(url_suffix, json=params)
+
+
+
+[docs]
+ def delete(self, alarm_id, **kwargs):
+ """Delete one alarm.
+
+ Args:
+ alarm_id (str): ID of the alarm to delete
+ **kwargs: Optional parameters of the API call.
+ Find supported parameters under
+ https://api.smaxtec.com/api/v2/
+
+ Returns:
+ dict: Response of API call. Deleted alarm on success, error message else.
+
+ """
+ params = {}
+ for k, v in kwargs.items():
+ params[k] = v
+
+ url_suffix = self.path_suffix + f"/{alarm_id}"
+ return self.api.delete(url_suffix, json=params)
+
+
+
+
+[docs]
+class Data:
+ """
+ This Class represents the /data endpoint fo the PublicAPIV2
+ """
+
+ def __init__(self, api=None):
+ self.api = api
+ self.path_suffix = "/data"
+
+
+[docs]
+ def get_data_animals(self, animal_id, metrics, from_date, to_date, **kwargs):
+ """Query sensordata for an animal.
+
+ Args:
+ animal_id (str): ID of the animal
+ metrics (list(str)): List of metrics to query
+ from_date (str): Query from date
+ to_date (str): Query end date
+ **kwargs: Optional parameters of the API call.
+ Find supported parameters under
+ https://api.smaxtec.com/api/v2/
+
+ Returns:
+ dict: Response from the API. Requested Metric values on success,
+ error message else.
+
+ """
+ params = {"metrics": metrics, "from_date": from_date, "to_date": to_date}
+
+ for k, v in kwargs.items():
+ params[k] = v
+
+ url_suffix = self.path_suffix + f"/animals/{animal_id}.json"
+ return self.api.get(url_suffix, json=params)
+
+
+
+[docs]
+ def get_metrics_animals(self, animal_id, **kwargs):
+ """List available metrics for an animal.
+
+ Args:
+ animal_id (str): ID of the animal
+ **kwargs: Optional parameters of the API call.
+ Find supported parameters under
+ https://api.smaxtec.com/api/v2/
+
+ Returns:
+ dict: Response from the API. List of available metrics on success,
+ error message else.
+
+ """
+ params = {}
+ for k, v in kwargs.items():
+ params[k] = v
+
+ url_suffix = self.path_suffix + f"/animals/{animal_id}/metrics"
+ self.api.get(url_suffix, json=params)
+
+
+
+[docs]
+ def get_data_devices(self, device_id, metrics, from_date, to_date, **kwargs):
+ """Query sensordata for a device.
+
+ Args:
+ device_id (str): ID of the device
+ metrics (list(str)): List of metrics to query
+ from_date (str): Query from date
+ to_date (str): Query end date
+ **kwargs: Optional parameters of the API call.
+ Find supported parameters under
+ https://api.smaxtec.com/api/v2/
+
+ Returns:
+ dict: Response from the API. Requested Metric values on success,
+ error message else.
+
+ """
+ params = {"metrics": metrics, "from_date": from_date, "to_date": to_date}
+
+ for k, v in kwargs.items():
+ params[k] = v
+
+ url_suffix = self.path_suffix + f"/devices/{device_id}.json"
+ return self.api.get(url_suffix, json=params)
+
+
+
+[docs]
+ def get_metrics_devices(self, device_id, **kwargs):
+ """List available metrics for a device.
+
+ Args:
+ device_id (str): ID of the device
+ **kwargs: Optional parameters of the API call.
+ Find supported parameters under
+ https://api.smaxtec.com/api/v2/
+
+ Returns:
+ dict: Response from the API. List of available metrics on success,
+ error message else.
+
+ """
+ params = {}
+ for k, v in kwargs.items():
+ params[k] = v
+
+ url_suffix = self.path_suffix + f"/devices/{device_id}/metrics"
+ return self.api.get(url_suffix, json=params)
+
+
+
+[docs]
+ def get_download_animal_data(
+ self, animal_ids, metrics, from_date, to_date, **kwargs
+ ):
+ """Download sensordata for animals.
+
+ Args:
+ animal_ids (list(str)): List of animal IDs
+ metrics (list(str)): List of metrics to query
+ from_date (str): Query from date
+ to_date (str): Query end date
+ **kwargs: Optional parameters of the API call.
+ Find supported parameters under
+ https://api.smaxtec.com/api/v2/
+
+ Returns:
+ dict: Response from the API. Requested Metric values on success,
+ error message else.
+
+ """
+ params = {
+ "animal_ids": animal_ids,
+ "metrics": metrics,
+ "from_date": from_date,
+ "to_date": to_date,
+ }
+
+ for k, v in kwargs.items():
+ params[k] = v
+
+ url_suffix = self.path_suffix + "/download_animal_data"
+ return self.api.get(url_suffix, json=params)
+
+
+
+[docs]
+ def get_download_device_data(
+ self, device_ids, metrics, from_date, to_date, **kwargs
+ ):
+ """Download sensordata for devices.
+
+ Args:
+ device_ids (list(str)): List of device IDs
+ metrics (list(str)): List of metrics to query
+ from_date (str): Query from date
+ to_date (str): Query end date
+ **kwargs: Optional parameters of the API call.
+ Find supported parameters under
+ https://api.smaxtec.com/api/v2/
+
+ Returns:
+ dict: Response from the API. Requested Metric values on success,
+ error message else.
+
+ """
+ params = {
+ "device_ids": device_ids,
+ "metrics": metrics,
+ "from_date": from_date,
+ "to_date": to_date,
+ }
+
+ for k, v in kwargs.items():
+ params[k] = v
+
+ url_suffix = self.path_suffix + "/download_device_data"
+ return self.api.get(url_suffix, json=params)
+
+
+
+[docs]
+ def get_download_group_data(self, group_ids, metrics, from_date, to_date, **kwargs):
+ """Download sensordata for groups.
+
+ Args:
+ group_ids (list(str)): List of group IDs
+ metrics (list(str)): List of metrics to query
+ from_date (str): Query from date
+ to_date (str): Query end date
+ **kwargs: Optional parameters of the API call.
+ Find supported parameters under
+ https://api.smaxtec.com/api/v2/
+
+ Returns:
+ dict: Response from the API. Requested Metric values on success,
+ error message else.
+
+ """
+ params = {
+ "group_ids": group_ids,
+ "metrics": metrics,
+ "from_date": from_date,
+ "to_date": to_date,
+ }
+
+ for k, v in kwargs.items():
+ params[k] = v
+
+ url_suffix = self.path_suffix + "/download_group_data"
+ return self.api.get(url_suffix, json=params)
+
+
+
+[docs]
+ def post_downloads_excel_report(self, from_date, to_date, **kwargs):
+ """Generates an Excel report and sends an email
+ containing a download link for the Excel report to the user.
+
+ Args:
+ from_date (str): Query from date
+ to_date (str): Query end date
+ **kwargs: Optional parameters of the API call.
+ Find supported parameters under
+ https://api.smaxtec.com/api/v2/
+
+ Returns:
+ dict: Empty dict on success, error message else.
+
+ """
+ params = {"from_date": from_date, "to_date": to_date}
+
+ for k, v in kwargs.items():
+ params[k] = v
+
+ url_suffix = self.path_suffix + "/downloads/generate_excel_report"
+ return self.api.post(url_suffix, json=params)
+
+
+
+[docs]
+ def post_downloads_messages_excel_report(self, from_date, to_date, **kwargs):
+ """Generates an Excel report and sends an email
+ containing a download link for the Excel report to the user.
+
+ Args:
+ from_date (str): Query from date
+ to_date (str): Query end date
+ **kwargs: Optional parameters of the API call.
+ Find supported parameters under
+ https://api.smaxtec.com/api/v2/
+
+ Returns:
+ dict: Empty dict on success, error message else.
+
+ """
+ params = {"from_date": from_date, "to_date": to_date}
+
+ for k, v in kwargs.items():
+ params[k] = v
+
+ url_suffix = self.path_suffix + "/downloads/generate_messages_excel_report"
+ return self.api.post(url_suffix, json=params)
+
+
+
+[docs]
+ def post_downloads_organisation_messages_excel_report(
+ self, organisation_id, from_date, to_date, **kwargs
+ ):
+ """Generates an Excel report and sends an email
+ containing a download link for the Excel report to the user.
+
+ Args:
+ organisation_id (str): ID of organisation the report should be created for
+ from_date (str): Query from date
+ to_date (str): Query end date
+ **kwargs: Optional parameters of the API call.
+ Find supported parameters under
+ https://api.smaxtec.com/api/v2/
+
+ Returns:
+ dict: Empty dict on success, error message else.
+
+ """
+ params = {
+ "organisation_id": organisation_id,
+ "from_date": from_date,
+ "to_date": to_date,
+ }
+
+ for k, v in kwargs.items():
+ params[k] = v
+
+ url_suffix = (
+ self.path_suffix + "/downloads/generate_organisation_messages_excel_report"
+ )
+ return self.api.post(url_suffix, json=params)
+
+
+
+[docs]
+ def get_downloads(self, download_id, **kwargs):
+ """Download a generated Excel report.
+
+ Args:
+ download_id (str): ID of the download
+ **kwargs: Optional parameters of the API call.
+ Find supported parameters under
+ https://api.smaxtec.com/api/v2/
+
+ Returns:
+
+ """
+ params = {}
+ for k, v in kwargs.items():
+ params[k] = v
+
+ url_suffix = self.path_suffix + f"/downloads/{download_id}"
+ return self.api.get(url_suffix, json=params)
+
+
+
+[docs]
+ def get_data_feedrations(
+ self, feedration_id, metrics, from_date, to_date, **kwargs
+ ):
+ """Query feedration data.
+
+ Args:
+ feedration_id (str): ID of the feedration group
+ metrics (list(str)): List of metrics to query
+ from_date (str): Query from date
+ to_date (str): Query end date
+ **kwargs: Optional parameters of the API call.
+ Find supported parameters under
+ https://api.smaxtec.com/api/v2/
+
+ Returns:
+ dict: Response from the API. Requested Metric values on success,
+ error message else.
+
+ """
+ params = {"metrics": metrics, "from_date": from_date, "to_date": to_date}
+
+ for k, v in kwargs.items():
+ params[k] = v
+
+ url_suffix = self.path_suffix + f"/feedrations/{feedration_id}.json"
+ return self.api.get(url_suffix, json=params)
+
+
+
+[docs]
+ def get_data_groups(self, group_id, metrics, from_date, to_date, **kwargs):
+ """Query group data.
+
+ Args:
+ group_id (str): ID of the group
+ metrics (list(str)): List of metrics to query
+ from_date (str): Query from date
+ to_date (str): Query end date
+ **kwargs: Optional parameters of the API call.
+ Find supported parameters under
+ https://api.smaxtec.com/api/v2/
+ Returns:
+ dict: Response from the API. Requested Metric values on success,
+ error message else.
+ """
+ params = {"metrics": metrics, "from_date": from_date, "to_date": to_date}
+
+ for k, v in kwargs.items():
+ params[k] = v
+
+ url_suffix = self.path_suffix + f"/groups/{group_id}.json"
+ return self.api.get(url_suffix, json=params)
+
+
+
+[docs]
+ def get_metrics_groups(self, group_id, **kwargs):
+ """List available metrics for a group.
+
+ Args:
+ group_id (str): ID of the group
+ **kwargs: Optional parameters of the API call.
+ Find supported parameters under
+ https://api.smaxtec.com/api/v2/
+ Returns:
+ dict: Response from the API. List of available metrics on success,
+ error message else.
+ """
+ params = {}
+ for k, v in kwargs.items():
+ params[k] = v
+
+ url_suffix = self.path_suffix + f"/groups/{group_id}/metrics"
+ return self.api.get(url_suffix, json=params)
+
+
+
+
+[docs]
+class Feedrations:
+ """
+ This Class represents the /feedrations endpoint of the PublicAPIV2.
+ https://api.smaxtec.com/api/v2/
+ """
+
+ def __init__(self, api=None):
+ self.api = api
+ self.path_suffix = "/feedrations"
+
+
+[docs]
+ def post(self, name, organisation_id, **kwargs):
+ """Creates a new feedration.
+
+ Args:
+ name (str): Name of the feedration to be created
+ organisation_id (str): ID of the organisation the feedration
+ should be created for
+ **kwargs: Optional parameters of the API call.
+ Find supported parameters under
+ https://api.smaxtec.com/api/v2/
+
+ Returns:
+ dict: Response of API call. Created feedration on success,
+ error message else.
+
+ """
+ params = {
+ "name": name,
+ "organisation_id": organisation_id,
+ }
+
+ for k, v in kwargs.items():
+ params[k] = v
+
+ self.api.post(self.path_suffix, json=params)
+
+
+
+[docs]
+ def put(self, feedration_id, name, organisation_id, **kwargs):
+ """Updates an existing feedration.
+
+ Args:
+ feedration_id (str): ID of the feedration which should be updated.
+ name (str): Name of the feedration to be updated
+ organisation_id (str): ID of the organisation the feedration
+ should be updated for
+ **kwargs: Optional parameters of the API call.
+ Find supported parameters under
+ https://api.smaxtec.com/api/v2/
+
+ Returns:
+ dict: Response of API call. Updated feedration on success,
+ error message else.
+
+ """
+ params = {
+ "name": name,
+ "organisation_id": organisation_id,
+ }
+ for k, v in kwargs.items():
+ params[k] = v
+
+ url_suffix = self.path_suffix + f"/{feedration_id}"
+ return self.api.put(url_suffix, json=params)
+
+
+
+[docs]
+ def get(self, feedration_id, **kwargs):
+ """Get one feedration.
+
+ Args:
+ feedration_id (str): ID of the desired feedration
+ **kwargs: Optional parameters of the API call.
+ Find supported parameters under
+ https://api.smaxtec.com/api/v2/
+
+ Returns:
+ dict: Response of API call. Feedration on success,
+ error message else.
+
+ """
+ params = {}
+ for k, v in kwargs.items():
+ params[k] = v
+
+ url_suffix = self.path_suffix + f"/{feedration_id}"
+ return self.api.get(url_suffix, json=params)
+
+
+
+[docs]
+ def delete(self, feedration_id, **kwargs):
+ """Deletes a feedration.
+
+ Args:
+ feedration_id (str): ID of the feedration which should be deleted.
+ **kwargs: Optional parameters of the API call.
+ Find supported parameters under
+ https://api.smaxtec.com/api/v2/
+
+ Returns:
+ dict: Response of API call. Result on success, error message else.
+
+ """
+ params = {}
+ for k, v in kwargs.items():
+ params[k] = v
+
+ url_suffix = self.path_suffix + f"/{feedration_id}"
+ return self.api.delete(url_suffix, json=params)
+
+
+
+
+[docs]
+class Groups:
+ """
+ This Class represents the /groups endpoint of the PublicAPIV2.
+ https://api.smaxtec.com/api/v2/
+ """
+
+ def __init__(self, api=None):
+ self.api = api
+ self.path_suffix = "/groups"
+
+
+[docs]
+ def put_actions(self, group_id, **kwargs):
+ """
+ Add an action to a group.
+
+ Args:
+ group_id (str): ID of the group which should be updated.
+ **kwargs: Optional parameters of the API call.
+ Find supported parameters under
+ https://api.smaxtec.com/api/v2/
+
+ Returns:
+ dict: Response of API call. Updated group on success, error message else.
+ """
+ params = {}
+
+ for k, v in kwargs.items():
+ params[k] = v
+
+ url_suffix = self.path_suffix + f"/{group_id}/actions"
+ self.api.put(url_suffix, json=params)
+
+
+
+[docs]
+ def get_actions(self, group_id, **kwargs):
+ """
+ Get all actions of a group.
+
+ Args:
+ group_id (str): ID of the group which should be updated.
+ **kwargs: Optional parameters of the API call.
+ Find supported parameters under
+ https://api.smaxtec.com/api/v2/
+
+ Returns:
+ dict: Response of API call. Updated group on success, error message else.
+ """
+ params = {}
+
+ for k, v in kwargs.items():
+ params[k] = v
+
+ url_suffix = self.path_suffix + f"/{group_id}/actions"
+ return self.api.get(url_suffix, json=params)
+
+
+
+[docs]
+ def delete_actions(self, group_id, action_id, **kwargs):
+ """
+ Delete an action from a group.
+
+ Args:
+ group_id (str): ID of the group which should be updated.
+ action_id (str): ID of the action which should be deleted.
+ **kwargs: Optional parameters of the API call.
+ Find supported parameters under
+ https://api.smaxtec.com/api/v2/
+
+ Returns:
+ dict: Response of API call. Result on success, error message else.
+ """
+ params = {}
+
+ for k, v in kwargs.items():
+ params[k] = v
+
+ url_suffix = self.path_suffix + f"/{group_id}/actions/{action_id}"
+ return self.api.delete(url_suffix, json=params)
+
+
+
+from datetime import (
+ datetime,
+ timedelta,
+)
+
+from sxapi.publicV2 import PublicAPIV2
+
+
+
+[docs]
+def get_sensor_data_from_animal(api, animal_id, *args, **kwargs):
+ """
+ Performs a get call to PUBLIC_API_V2, to get the sensordata from the given animal_id
+ """
+ if not isinstance(api, PublicAPIV2):
+ print("This function is only available to PublicAPIV2!")
+ return
+
+ metrics = kwargs.get("metrics", None)
+ if not metrics:
+ metrics = ["temp", "act"]
+ from_date_string = kwargs.get("from_date")
+ to_date_string = kwargs.get("to_date")
+
+ to_date = datetime.utcnow()
+ from_date = to_date - timedelta(days=2)
+
+ if to_date_string:
+ try:
+ to_date = datetime.strptime(*to_date_string, "%Y-%m-%d")
+ except ValueError:
+ print("to_date has not the right format YYYY-MM-DD!")
+ return None
+
+ if from_date_string:
+ try:
+ from_date = datetime.strptime(*from_date_string, "%Y-%m-%d")
+ except ValueError:
+ print("from_date has not the right format YYYY-MM-DD!")
+ return None
+
+ return api.data.get_data_animals(
+ animal_id, metrics, from_date.isoformat(), to_date.isoformat()
+ )
+
+
+
+[docs]
+class Todos:
+ """
+ This Class represents the /todos endpoint of the PublicAPIV2.
+
+ """
+
+ def __init__(self, api=None):
+ self.api = api
+ self.path_suffix = "/todos"
+
+
+[docs]
+ def post(self, todo_type, organisation_id, **kwargs):
+ """Creates a new todo.
+
+ Args:
+ todo_type (str): Type of the todo to be created
+ organisation_id (str): Id of organisation the todo should be created for
+ **kwargs: Optional parameters of the API call.
+ Find supported parameters under
+ https://api.smaxtec.com/api/v2/
+
+ Returns:
+ dict: Response of API call. Created todo on success, error message else.
+
+ """
+ params = {
+ "todo_type": todo_type,
+ "organisation_id": organisation_id,
+ }
+
+ for k, v in kwargs.items():
+ params[k] = v
+
+ self.api.post(self.path_suffix, json=params)
+
+
+
+[docs]
+ def put(self, todo_id, **kwargs):
+ """Updates an existing todo.
+
+ Args:
+ todo_id (str): Id of the todo which should be updated.
+ **kwargs: Optional parameters of the API call.
+ Find supported parameters under
+ https://api.smaxtec.com/api/v2/
+
+ Returns:
+ dict: Response of API call. Updated todo on success, error message else.
+
+ """
+ params = {}
+ for k, v in kwargs.items():
+ params[k] = v
+
+ url_suffix = self.path_suffix + f"/{todo_id}"
+ return self.api.put(url_suffix, json=params)
+
+
+
+[docs]
+ def get(self, todo_id):
+ """Get one todo.
+
+ Args:
+ todo_id (str): Id of the desired todo
+
+ Returns:
+ dict: Response of API call. Queried todo on success, error message else.
+
+ """
+ return self.api.get(self.path_suffix + f"/{todo_id}")
+
+
+
+[docs]
+ def post_comment(self, todo_id, content):
+ """Create a comment for a todo.
+
+ Args:
+ todo_id (str): Id of the todo a comment is to be created.
+ content (str): Content of the comment
+
+ Returns:
+ dict: Response of API call. Updated todo on success, error message else.
+ """
+ params = {
+ "content": content,
+ }
+
+ url_suffix = self.path_suffix + f"/{todo_id}/comments"
+ return self.api.post(url_suffix, json=params)
+
+
+
+[docs]
+ def delete_comment(self, todo_id, comment_id):
+ """Delete a comment from a todo.
+
+ Args:
+ todo_id (str): Id of the todo a comment is to be deleted.
+ comment_id (str): Id of the comment to delete.
+
+ Returns:
+ dict: Response of API call. Updated todo on success, error message else.
+ """
+
+ url_suffix = self.path_suffix + f"/{todo_id}/comments/{comment_id}"
+ return self.api.delete(url_suffix)
+
+
+
+[docs]
+ def put_comment(self, todo_id, comment_id, content):
+ """Update a comment from a todo.
+
+ Args:
+ todo_id (str): Id of the todo a comment is to be updated.
+ comment_id (str): Id of the comment to be updated.
+ content (str): Updated content of the Id.
+
+ Returns:
+ dict: Response of API call. Updated todo on success, error message else.
+ """
+ params = {
+ "content": content,
+ }
+
+ url_suffix = self.path_suffix + f"/{todo_id}/comments/{comment_id}"
+ return self.api.put(url_suffix, json=params)
+
+
+
+
+[docs]
+class Users:
+ """
+ This Class represents the /users endpoint fo the PublicAPIV2
+ https://api.smaxtec.com/api/v2/
+ """
+
+ def __init__(self, api=None):
+ self.api = api
+ self.path_suffix = "/users"
+
+
+[docs]
+ def post_activate(self, user_secret, **kwargs):
+ """Active a user with secret.
+
+ Args:
+ user_secret (str): secrete received from registration email.
+
+ Returns:
+ dict: Response of API call. Activated User on success, error message else.
+ """
+
+ params = {"secret": user_secret}
+
+ for k, v in kwargs.items():
+ params[k] = v
+
+ url_suffix = self.path_suffix + "/activate"
+ return self.api.post(url_suffix, json=params)
+
+
+
+[docs]
+ def post_credentials(self, user, password, **kwargs):
+ """Create smaxtec api-access-token and an optional firestore-token.
+
+ Args:
+ user (str): Username/email
+ password (str): User password
+ **kwargs: Optional parameters of the API call.
+ Find supported parameters under
+ https://api.smaxtec.com/api/v2/
+
+ Returns:
+ dict: Response of API call. Requested tokens and additional user
+ information on success, error message else.
+ """
+
+ params = {
+ "user": user,
+ "password": password,
+ }
+
+ for k, v in kwargs.items():
+ params[k] = v
+
+ url_suffix = self.path_suffix + "/credentials"
+ return self.api.post(url_suffix, json=params)
+
+
+
+[docs]
+ def get_credentials(self, **kwargs):
+ """Retrieve smaxtec api-access-tokens with a JWT Token.
+
+ Args:
+ **kwargs: Optional parameters of the API call.
+ Find supported parameters under
+ https://api.smaxtec.com/api/v2/
+
+ Returns:
+ dict: Response of API call. Current tokens and additional user
+ information on success, error message else.
+ """
+
+ params = {}
+
+ for k, v in kwargs.items():
+ params[k] = v
+
+ url_suffix = self.path_suffix + "/credentials"
+ return self.api.get(url_suffix, json=params)
+
+
+
+[docs]
+ def post_reset_password(self, secret, new_password, **kwargs):
+ """Reset password with secret.
+
+ Args:
+ secret (str): secret received from email request.
+ new_password (str): new password for the user.
+ **kwargs: Optional parameters of the API call.
+ Find supported parameters under
+ https://api.smaxtec.com/api/v2/
+
+ Returns:
+ dict: Response of API call. Updated User on success, error message else.
+ """
+
+ params = {"secret": secret, "new_password": new_password}
+
+ for k, v in kwargs.items():
+ params[k] = v
+
+ url_suffix = self.path_suffix + "/reset_password"
+ return self.api.post(url_suffix, json=params)
+
+
+
+[docs]
+ def get_reset_password_request(self, email, **kwargs):
+ """Request a password reset email.
+
+ Args:
+ email (str): email of the user.
+ **kwargs: Optional parameters of the API call.
+ Find supported parameters under
+ https://api.smaxtec.com/api/v2/
+
+ Returns:
+ dict: Response of API call. Request result on success, error message else.
+ """
+
+ params = {"email": email}
+
+ for k, v in kwargs.items():
+ params[k] = v
+
+ url_suffix = self.path_suffix + "/reset_password_request"
+ return self.api.get(url_suffix, json=params)
+
+
+
+[docs]
+ def get(self, user_id, **kwargs):
+ """Get one user by id.
+
+ Args:
+ user_id (str): ID of the desired user
+ **kwargs: Optional parameters of the API call.
+ Find supported parameters under
+ https://api.smaxtec.com/api/v2/
+
+ Returns:
+ dict: Response of API call. User object on success, error message else.
+
+ """
+ params = {}
+
+ for k, v in kwargs.items():
+ params[k] = v
+
+ url_suffix = self.path_suffix + f"/{user_id}"
+ return self.api.get(url_suffix, json=params)
+
+
+
+[docs]
+ def get_account(self, user_id, **kwargs):
+ """Get a list of all Accounts of the given user
+
+ Args:
+ user_id (str): ID of the desired user
+ **kwargs: Optional parameters of the API call.
+ Find supported parameters under
+ https://api.smaxtec.com/api/v2/
+
+ Returns:
+ dict: Response of API call. List of Account objects on success,
+ error message else.
+
+ """
+ params = {}
+
+ for k, v in kwargs.items():
+ params[k] = v
+
+ url_suffix = self.path_suffix + f"/{user_id}/account"
+ return self.api.get(url_suffix, json=params)
+
+
+
+[docs]
+ def get_alarms(self, user_id, **kwargs):
+ """Get a list of all Alarms of the given user
+
+ Args:
+ user_id (str): ID of the desired user
+ **kwargs: Optional parameters of the API call.
+ Find supported parameters under
+ https://api.smaxtec.com/api/v2/
+
+ Returns:
+ dict: Response of API call. List of Alarm objects on success,
+ error message else.
+
+ """
+ params = {}
+
+ for k, v in kwargs.items():
+ params[k] = v
+
+ url_suffix = self.path_suffix + f"/{user_id}/alarms"
+ return self.api.get(url_suffix, json=params)
+
+
+
+[docs]
+ def put_change_password(self, user_id, old_password, new_password, **kwargs):
+ """Change password of a user with old password.
+
+ Args:
+ user_id (str): ID of the desired user
+ old_password (str): old password of the user
+ new_password (str): new password of the user
+ **kwargs: Optional parameters of the API call.
+ Find supported parameters under
+ https://api.smaxtec.com/api/v2/
+
+ Returns:
+ dict: Response of API call. Request result on success, error message else.
+
+ """
+ params = {
+ "old_password": old_password,
+ "new_password": new_password,
+ }
+
+ for k, v in kwargs.items():
+ params[k] = v
+
+ url_suffix = self.path_suffix + f"/{user_id}/change_password"
+ return self.api.put(url_suffix, json=params)
+
+
+
+[docs]
+ def post_password_strength(self, user_id, email, password, **kwargs):
+ """Check password strength.
+
+ Args:
+ user_id (str): ID of the desired user
+ email (str): email of the user
+ password (str): password to check
+ **kwargs: Optional parameters of the API call.
+ Find supported parameters under
+ https://api.smaxtec.com/api/v2/
+
+ Returns:
+ dict: Response of API call. Request result and password strength on success,
+ error message else.
+
+ """
+ params = {
+ "password": password,
+ "email": email,
+ }
+
+ for k, v in kwargs.items():
+ params[k] = v
+
+ url_suffix = self.path_suffix + f"/{user_id}/password_strength"
+ return self.api.post(url_suffix, json=params)
+
+
+
+
+
+
+[docs]
+ def post_test_email(self, user_id, **kwargs):
+ """Send a test email to the user.
+
+ Args:
+ user_id (str): ID of the desired user
+ **kwargs: Optional parameters of the API call.
+ Find supported parameters under
+ https://api.smaxtec.com/api/v2/
+
+ Returns:
+ dict: Empty dict on success, error message else.
+
+ """
+ params = {}
+
+ for k, v in kwargs.items():
+ params[k] = v
+
+ url_suffix = self.path_suffix + f"/{user_id}/test_email"
+ return self.api.post(url_suffix, json=params)
+
+
+
+[docs]
+ def post_test_push(self, user_id, **kwargs):
+ """Send a test push notification to the user.
+
+ Args:
+ user_id (str): ID of the desired user
+ **kwargs: Optional parameters of the API call.
+ Find supported parameters under
+ https://api.smaxtec.com/api/v2/
+
+ Returns:
+ dict: Empty dict on success, error message else.
+
+ """
+ params = {}
+
+ for k, v in kwargs.items():
+ params[k] = v
+
+ url_suffix = self.path_suffix + f"/{user_id}/test_push"
+ return self.api.post(url_suffix, json=params)
+
+
+
+[docs]
+ def put_tokens(self, user_id, token, platform, token_type, **kwargs):
+ """Adds the token if it does not exist, else updates the token.
+
+ Args:
+ user_id (str): ID of the desired user
+ token (str): some kind of token
+ platform (str): platform of the token device
+ token_type (str): type of the token (add push_ if push token)
+ **kwargs: Optional parameters of the API call.
+ Find supported parameters under
+ https://api.smaxtec.com/api/v2/
+
+ Returns:
+ dict: Response of API call. Request result on success, error message else.
+
+ """
+ params = {
+ "token": token,
+ "platform": platform,
+ "token_type": token_type,
+ }
+
+ for k, v in kwargs.items():
+ params[k] = v
+
+ url_suffix = self.path_suffix + f"/{user_id}/tokens"
+ return self.api.put(url_suffix, json=params)
+
+
+
+[docs]
+ def post_tokens(self, user_id, token, platform, token_type, **kwargs):
+ """Adds the token to the user.
+
+ Args:
+ user_id (str): ID of the desired user
+ token (str): some kind of token
+ platform (str): platform of the token device
+ token_type (str): type of the token (add push_ if push token)
+ **kwargs: Optional parameters of the API call.
+ Find supported parameters under
+ https://api.smaxtec.com/api/v2/
+
+ Returns:
+ dict: Response of API call. Request result on success, error message else.
+
+ """
+ params = {
+ "token": token,
+ "platform": platform,
+ "token_type": token_type,
+ }
+
+ for k, v in kwargs.items():
+ params[k] = v
+
+ url_suffix = self.path_suffix + f"/{user_id}/tokens"
+ return self.api.post(url_suffix, json=params)
+
+
+
+[docs]
+ def delete_tokens(self, user_id, token, **kwargs):
+ """Deletes the token from the user.
+
+ Args:
+ user_id (str): ID of the desired user
+ token (str): token to be deleted
+ **kwargs: Optional parameters of the API call.
+ Find supported parameters under
+ https://api.smaxtec.com/api/v2/
+
+ Returns:
+ dict: Response of API call. Request result on success, error message else.
+
+ """
+ params = {}
+
+ for k, v in kwargs.items():
+ params[k] = v
+
+ url_suffix = self.path_suffix + f"/{user_id}/tokens/{token}"
+ return self.api.delete(url_suffix, json=params)
+
+
+
+[docs]
+ def post_update_metadata(self, user_id, metadata, **kwargs):
+ """Update metadata of a user.
+
+ Args:
+ user_id (str): ID of the desired user
+ metadata (dict): updated metadata
+ **kwargs: Optional parameters of the API call.
+ Find supported parameters under
+ https://api.smaxtec.com/api/v2/
+
+ Returns:
+ dict: Response of API call. Updated user on success, error message else.
+
+ """
+ params = {
+ "metadata": metadata,
+ }
+
+ for k, v in kwargs.items():
+ params[k] = v
+
+ url_suffix = self.path_suffix + f"/{user_id}/update_metadata"
+ return self.api.post(url_suffix, json=params)
+
+
+
' + + '' + + _("Hide Search Matches") + + "
" + ) + ); + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords: () => { + document + .querySelectorAll("#searchbox .highlight-link") + .forEach((el) => el.remove()); + document + .querySelectorAll("span.highlighted") + .forEach((el) => el.classList.remove("highlighted")); + localStorage.removeItem("sphinx_highlight_terms") + }, + + initEscapeListener: () => { + // only install a listener if it is really needed + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; + // bail with special keys + if (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) return; + if (DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS && (event.key === "Escape")) { + SphinxHighlight.hideSearchWords(); + event.preventDefault(); + } + }); + }, +}; + +_ready(() => { + /* Do not call highlightSearchWords() when we are on the search page. + * It will highlight words from the *previous* search query. + */ + if (typeof Search === "undefined") SphinxHighlight.highlightSearchWords(); + SphinxHighlight.initEscapeListener(); +}); diff --git a/api/modules.html b/api/modules.html new file mode 100644 index 0000000..fd16cac --- /dev/null +++ b/api/modules.html @@ -0,0 +1,165 @@ + + + + + + + +Bases: object
CliUser class used for initializing, storing, retrieving and deleting +credentials and creating/holding Instances of supported API +Client.
+This class should only be used in the cli package.
+ + + + +Gets token named ‘SMAXTEC_API_ACCESS_TOKEN’ from the systems’ environment.
+This function retrieves the token from the specified resource +(keyring, environment or args) and initializes clients +of the supported APIs (PublicV2, IntegrationV2).
+If no token can be found the token is retrieved via +the username and password.
+If username and password are also missing, no credentials get +stored and not API clients are created.
+get_sensor_data subparser for cli_tests. +Responsible for performing api-call to get the sensor data for a given animal.
+The ‘animals_id’ is mandatory argument ‘animal_id’. +It represents the animal you want to get data from.
+The following flag are only optional. +The –metrics/-m Flag defines the metrics you want to get from the animal sensor. +It expects at most two arguments ‘temp’, ‘act’ or both together. Where ‘temp’ means +getting the temperature metric and ‘act’ means the activity metric.
+The –from_date Flag defines the start-date of window you want to get data from. +It expects exactly one argument, a datetime in the format ‘YYYY-MM-DD’ +(e.g. 2022.01.12).
+The –to_date Flag defines the end-date of window you want to get data from. +It expects exactly one argument, a datetime in the format ‘YYYY-MM-DD’ +(e.g. 2022.01.12).
+Token subparser for cli_tests. +Responsible for managing tokens/credentials.
+The –print_token/-p Flag prints the token, stored in keyring or in +environment, to stdout. It expects exactly only one argument -> ‘e’ +for printing the token stored in the environment, ‘k’ for printing +the token stored in keyring and ‘ek’ for printing both at the same time.
+The –set_keyring/-s flag stores the token (given as argument) in the keyring. +It expects exactly one argument -> the token you want to store.
+The –clear_keyring/-c Flag deletes the token from the keyring. +This flag doesn’t expect any argument.
+The –new_token/-n Flag calls api to get new token and prints it to stdout. +It expects exactly two arguments -> smaxtec-username and smaxtec-password.
+It is not possible to use more than one of those flags at the same time
+Logic behind the token subparser –clear_keyring flag.
+Deletes the token from the keyring.
+Logic behind the token subparser –new_token flag.
+Parses the args, creates an PublicAPIV2 instance to get new token and +print the new token to stdout.
+Logic behind the token subparser –print_token flag.
+Prints the token from the desired source (environment or keyring) to stdout.
+Data
Data.get_data_animals()
Data.get_data_devices()
Data.get_data_feedrations()
Data.get_data_groups()
Data.get_download_animal_data()
Data.get_download_device_data()
Data.get_download_group_data()
Data.get_downloads()
Data.get_metrics_animals()
Data.get_metrics_devices()
Data.get_metrics_groups()
Data.post_downloads_excel_report()
Data.post_downloads_messages_excel_report()
Data.post_downloads_organisation_messages_excel_report()
Users
Users.delete_tokens()
Users.get()
Users.get_account()
Users.get_alarms()
Users.get_credentials()
Users.get_reset_password_request()
Users.get_shares()
Users.post_activate()
Users.post_credentials()
Users.post_password_strength()
Users.post_reset_password()
Users.post_test_email()
Users.post_test_push()
Users.post_tokens()
Users.post_update_metadata()
Users.put_change_password()
Users.put_tokens()
PublicAPIV2
Bases: Enum
An enumeration.
+Bases: object
This class represents the /alarms API endpoint of the PublicAPIV2. +https://api.smaxtec.com/api/v2/
+Delete one alarm.
+alarm_id (str) – ID of the alarm to delete
**kwargs – Optional parameters of the API call. +Find supported parameters under +https://api.smaxtec.com/api/v2/
Response of API call. Deleted alarm on success, error message else.
+Get one alarm.
+alarm_id (str) – ID of the desired alarm
**kwargs – Optional parameters of the API call. +Find supported parameters under +https://api.smaxtec.com/api/v2/
Response of API call. Queried alarm on success, error message else.
+Get all alarms categories for a user or organisation. +If no user or organisation is given, this +function return a BadRequestError
+**kwargs – Optional parameters of the API call. +Find supported parameters under +https://api.smaxtec.com/api/v2/
+Response of API call. List of alarms on success, error message else.
+Creates a new alarm.
+organisation_id (str) – ID of organisation the alarm should be created for
title (str) – Title of the alarm
**kwargs – Optional parameters of the API call. +Find supported parameters under +https://api.smaxtec.com/api/v2/
Response of API call. Created alarm on success, error message else.
+Updates an existing alarm.
+alarm_id (str) – ID of the alarm which should be updated.
organisation_id (str) – ID of organisation the alarm should be updated for
**kwargs – Optional parameters of the API call. +Find supported parameters under +https://api.smaxtec.com/api/v2/
Response of API call. Updated alarm on success, error message else.
+Bases: object
This Class represents the /data endpoint fo the PublicAPIV2
+Query sensordata for an animal.
+error message else.
+Query sensordata for a device.
+error message else.
+Query feedration data.
+error message else.
+Query group data.
+error message else.
+Download sensordata for animals.
+error message else.
+Download sensordata for devices.
+error message else.
+Download sensordata for groups.
+error message else.
+Download a generated Excel report.
+download_id (str) – ID of the download
**kwargs – Optional parameters of the API call. +Find supported parameters under +https://api.smaxtec.com/api/v2/
Returns:
+List available metrics for an animal.
+animal_id (str) – ID of the animal
**kwargs – Optional parameters of the API call. +Find supported parameters under +https://api.smaxtec.com/api/v2/
error message else.
+List available metrics for a device.
+device_id (str) – ID of the device
**kwargs – Optional parameters of the API call. +Find supported parameters under +https://api.smaxtec.com/api/v2/
error message else.
+List available metrics for a group.
+group_id (str) – ID of the group
**kwargs – Optional parameters of the API call. +Find supported parameters under +https://api.smaxtec.com/api/v2/
error message else.
+Generates an Excel report and sends an email +containing a download link for the Excel report to the user.
+from_date (str) – Query from date
to_date (str) – Query end date
**kwargs – Optional parameters of the API call. +Find supported parameters under +https://api.smaxtec.com/api/v2/
Empty dict on success, error message else.
+Generates an Excel report and sends an email +containing a download link for the Excel report to the user.
+from_date (str) – Query from date
to_date (str) – Query end date
**kwargs – Optional parameters of the API call. +Find supported parameters under +https://api.smaxtec.com/api/v2/
Empty dict on success, error message else.
+Generates an Excel report and sends an email +containing a download link for the Excel report to the user.
+organisation_id (str) – ID of organisation the report should be created for
from_date (str) – Query from date
to_date (str) – Query end date
**kwargs – Optional parameters of the API call. +Find supported parameters under +https://api.smaxtec.com/api/v2/
Empty dict on success, error message else.
+Bases: object
This Class represents the /feedrations endpoint of the PublicAPIV2. +https://api.smaxtec.com/api/v2/
+Deletes a feedration.
+feedration_id (str) – ID of the feedration which should be deleted.
**kwargs – Optional parameters of the API call. +Find supported parameters under +https://api.smaxtec.com/api/v2/
Response of API call. Result on success, error message else.
+Get one feedration.
+feedration_id (str) – ID of the desired feedration
**kwargs – Optional parameters of the API call. +Find supported parameters under +https://api.smaxtec.com/api/v2/
error message else.
+Creates a new feedration.
+name (str) – Name of the feedration to be created
organisation_id (str) – ID of the organisation the feedration +should be created for
**kwargs – Optional parameters of the API call. +Find supported parameters under +https://api.smaxtec.com/api/v2/
error message else.
+Updates an existing feedration.
+feedration_id (str) – ID of the feedration which should be updated.
name (str) – Name of the feedration to be updated
organisation_id (str) – ID of the organisation the feedration +should be updated for
**kwargs – Optional parameters of the API call. +Find supported parameters under +https://api.smaxtec.com/api/v2/
error message else.
+Bases: object
This Class represents the /groups endpoint of the PublicAPIV2. +https://api.smaxtec.com/api/v2/
+Delete an action from a group.
+group_id (str) – ID of the group which should be updated.
action_id (str) – ID of the action which should be deleted.
**kwargs – Optional parameters of the API call. +Find supported parameters under +https://api.smaxtec.com/api/v2/
Response of API call. Result on success, error message else.
+Get all actions of a group.
+group_id (str) – ID of the group which should be updated.
**kwargs – Optional parameters of the API call. +Find supported parameters under +https://api.smaxtec.com/api/v2/
Response of API call. Updated group on success, error message else.
+Add an action to a group.
+group_id (str) – ID of the group which should be updated.
**kwargs – Optional parameters of the API call. +Find supported parameters under +https://api.smaxtec.com/api/v2/
Response of API call. Updated group on success, error message else.
+Bases: object
This Class represents the /todos endpoint of the PublicAPIV2.
+ + + + +Creates a new todo.
+todo_type (str) – Type of the todo to be created
organisation_id (str) – Id of organisation the todo should be created for
**kwargs – Optional parameters of the API call. +Find supported parameters under +https://api.smaxtec.com/api/v2/
Response of API call. Created todo on success, error message else.
+Updates an existing todo.
+todo_id (str) – Id of the todo which should be updated.
**kwargs – Optional parameters of the API call. +Find supported parameters under +https://api.smaxtec.com/api/v2/
Response of API call. Updated todo on success, error message else.
+Bases: object
This Class represents the /users endpoint fo the PublicAPIV2 +https://api.smaxtec.com/api/v2/
+Deletes the token from the user.
+user_id (str) – ID of the desired user
token (str) – token to be deleted
**kwargs – Optional parameters of the API call. +Find supported parameters under +https://api.smaxtec.com/api/v2/
Response of API call. Request result on success, error message else.
+Get one user by id.
+user_id (str) – ID of the desired user
**kwargs – Optional parameters of the API call. +Find supported parameters under +https://api.smaxtec.com/api/v2/
Response of API call. User object on success, error message else.
+Get a list of all Accounts of the given user
+user_id (str) – ID of the desired user
**kwargs – Optional parameters of the API call. +Find supported parameters under +https://api.smaxtec.com/api/v2/
error message else.
+Get a list of all Alarms of the given user
+user_id (str) – ID of the desired user
**kwargs – Optional parameters of the API call. +Find supported parameters under +https://api.smaxtec.com/api/v2/
error message else.
+Retrieve smaxtec api-access-tokens with a JWT Token.
+**kwargs – Optional parameters of the API call. +Find supported parameters under +https://api.smaxtec.com/api/v2/
+Response of API call. Current tokens and additional user +information on success, error message else.
+Request a password reset email.
+email (str) – email of the user.
**kwargs – Optional parameters of the API call. +Find supported parameters under +https://api.smaxtec.com/api/v2/
Response of API call. Request result on success, error message else.
+Get a list of all Shares of the given user
+user_id (str) – ID of the desired user
**kwargs – Optional parameters of the API call. +Find supported parameters under +https://api.smaxtec.com/api/v2/
error message else.
+Create smaxtec api-access-token and an optional firestore-token.
+user (str) – Username/email
password (str) – User password
**kwargs – Optional parameters of the API call. +Find supported parameters under +https://api.smaxtec.com/api/v2/
Response of API call. Requested tokens and additional user +information on success, error message else.
+Check password strength.
+user_id (str) – ID of the desired user
email (str) – email of the user
password (str) – password to check
**kwargs – Optional parameters of the API call. +Find supported parameters under +https://api.smaxtec.com/api/v2/
error message else.
+Reset password with secret.
+secret (str) – secret received from email request.
new_password (str) – new password for the user.
**kwargs – Optional parameters of the API call. +Find supported parameters under +https://api.smaxtec.com/api/v2/
Response of API call. Updated User on success, error message else.
+Send a test email to the user.
+user_id (str) – ID of the desired user
**kwargs – Optional parameters of the API call. +Find supported parameters under +https://api.smaxtec.com/api/v2/
Empty dict on success, error message else.
+Send a test push notification to the user.
+user_id (str) – ID of the desired user
**kwargs – Optional parameters of the API call. +Find supported parameters under +https://api.smaxtec.com/api/v2/
Empty dict on success, error message else.
+Adds the token to the user.
+user_id (str) – ID of the desired user
token (str) – some kind of token
platform (str) – platform of the token device
token_type (str) – type of the token (add push_ if push token)
**kwargs – Optional parameters of the API call. +Find supported parameters under +https://api.smaxtec.com/api/v2/
Response of API call. Request result on success, error message else.
+Update metadata of a user.
+user_id (str) – ID of the desired user
metadata (dict) – updated metadata
**kwargs – Optional parameters of the API call. +Find supported parameters under +https://api.smaxtec.com/api/v2/
Response of API call. Updated user on success, error message else.
+Change password of a user with old password.
+user_id (str) – ID of the desired user
old_password (str) – old password of the user
new_password (str) – new password of the user
**kwargs – Optional parameters of the API call. +Find supported parameters under +https://api.smaxtec.com/api/v2/
Response of API call. Request result on success, error message else.
+Adds the token if it does not exist, else updates the token.
+user_id (str) – ID of the desired user
token (str) – some kind of token
platform (str) – platform of the token device
token_type (str) – type of the token (add push_ if push token)
**kwargs – Optional parameters of the API call. +Find supported parameters under +https://api.smaxtec.com/api/v2/
Response of API call. Request result on success, error message else.
+Florian Klien <florian.klien@smaxtec.com>
Philipp Kulich <philipp.kulich@smaxtec.com>
Marco Julian Moser <hyper_chrome@gmx.at>
Welcome to sxapi
contributor’s guide.
This document focuses on getting any potential contributor familiarized +with the development processes, but other kinds of contributions are also +appreciated.
+If you are new to using git or have never collaborated in a project previously, +please have a look at contribution-guide.org. Other resources are also +listed in the excellent guide created by FreeCodeCamp [1].
+Please notice, all users and contributors are expected to be open, +considerate, reasonable, and respectful. When in doubt, Python Software +Foundation’s Code of Conduct is a good reference in terms of behavior +guidelines.
+If you experience bugs or general issues with sxapi
, please have a look
+on the issue tracker. If you don’t see anything useful there, please feel
+free to fire an issue report.
Tip
+Please don’t forget to include the closed issues in your search. +Sometimes a solution was already reported, and the problem is considered +solved.
+New issue reports should include information about your programming environment +(e.g., operating system, Python version) and steps to reproduce the problem. +Please try also to simplify the reproduction steps to a very minimal example +that still illustrates the problem you are facing. By removing other factors, +you help us to identify the root cause of the issue.
+You can help improve sxapi
docs by making them more readable and coherent, or
+by adding missing information and correcting mistakes.
sxapi
documentation uses Sphinx as its main documentation compiler, with reStructuredText as markup language.
+This means that the docs are kept in the same repository as the project code, and
+that any documentation update is done in the same way was a code contribution.
Tip
+Please notice that the GitHub web interface provides a quick way of
+propose changes in sxapi
’s files. While this mechanism can
+be tricky for normal code contributions, it works perfectly fine for
+contributing to the docs, and can be quite handy.
If you are interested in trying this method out, please navigate to
+the docs
folder in the source repository, find which file you
+would like to propose changes and click in the little pencil icon at the
+top, to open GitHub’s code editor. Once you finish editing the file,
+please write a message in the form at the bottom of the page describing
+which changes have you made and what are the motivations behind them and
+submit your proposal.
When working on documentation changes in your local machine, you can
+compile them using tox
:
tox -e docs
+
and use Python’s built-in web server for a preview in your web browser
+(http://localhost:8000
):
python3 -m http.server --directory 'docs/_build/html'
+
You can find the API documentation for the smaxtec system on the API documentation page and the integration API documentation page.
+This API is only available with a smaxtec user account after logging in. All calls must use an access token. +.. todo:: fix contact info. +If you need an account for the API you can contact smaXtec.
+Before you work on any non-trivial code contribution it’s best to first create +a report in the issue tracker to start a discussion on the subject. +This often provides additional considerations and avoids unnecessary work.
+Before you start coding, we recommend creating an isolated virtual
+environment to avoid any problems with your installed Python packages.
+This can easily be done via either virtualenv
:
virtualenv <PATH TO VENV>
+source <PATH TO VENV>/bin/activate
+
Create an user account on GitHub if you do not already have one.
Fork the project repository: click on the Fork button near the top of the +page. This creates a copy of the code under your account on GitHub.
Clone this copy to your local disk:
+git clone git@github.com:YourLogin/sxapi.git
+cd sxapi
+
You should run:
+pip install -U pip setuptools -e .
+
to be able run putup --help
.
Install pre-commit
:
pip install pre-commit
+pre-commit install
+
sxapi
comes with a lot of hooks configured to automatically help the
+developer to check the code being written.
Create a branch to hold your changes:
+git checkout -b my-feature
+
and start making changes. Never work on the master branch!
+Start your work on this branch. Don’t forget to add docstrings to new +functions, modules and classes, especially if they are part of public APIs.
Add yourself to the list of contributors in AUTHORS.rst
.
When you’re done editing, do:
+git add <MODIFIED FILES>
+git commit
+
to record your changes in git.
+Please make sure to see the validation messages from pre-commit
and fix
+any eventual issues.
+This should automatically use flake8/black to check/fix the code style
+in a way that is compatible with the project.
Important
+Don’t forget to add unit tests and documentation in case your +contribution adds an additional feature and is not just a bugfix.
+Moreover, writing a descriptive commit message is highly recommended. +In case of doubt, you can check the commit history with:
+git log --graph --decorate --pretty=oneline --abbrev-commit --all
+
to look for recurring communication patterns.
+Please check that your changes don’t break any unit tests with:
+tox
+
(after having installed tox
with pip install tox
or pipx
).
You can also use tox
to run several other pre-configured tasks in the
+repository. Try tox -av
to see a list of the available checks.
If everything works fine, push your local branch to GitHub with:
+git push -u origin my-feature
+
Go to the web page of your fork and click “Create pull request” +to send your changes for review.
+Find more detailed information creating a PR. You might also want to open +the PR as a draft first and mark it as ready for review after the feedbacks +from the continuous integration (CI) system or any required fixes.
+The following tips can be used when facing problems to build or test the +package:
+Make sure to fetch all the tags from the upstream repository.
+The command git describe --abbrev=0 --tags
should return the version you
+are expecting. If you are trying to run CI scripts in a fork repository,
+make sure to push all the tags.
+You can also try to remove all the egg files or the complete egg folder, i.e.,
+.eggs
, as well as the *.egg-info
folders in the src
folder or
+potentially in the root of your project.
Sometimes tox
misses out when new dependencies are added, especially to
+setup.cfg
and docs/requirements.txt
. If you find any problems with
+missing dependencies when running a command with tox
, try to recreate the
+tox
environment using the -r
flag. For example, instead of:
tox -e docs
+
Try running:
+tox -r -e docs
+
Make sure to have a reliable tox
installation that uses the correct
+Python version (e.g., 3.7+). When in doubt you can run:
tox --version
+# OR
+which tox
+
If you have trouble and are seeing weird errors upon running tox
, you can
+also try to create a dedicated virtual environment with a tox
binary
+freshly installed. For example:
virtualenv .venv
+source .venv/bin/activate
+.venv/bin/pip install tox
+.venv/bin/tox -e all
+
Pytest can drop you in an interactive session in the case an error occurs.
+In order to do that you need to pass a --pdb
option (for example by
+running tox -- -k <NAME OF THE FALLING TEST> --pdb
).
+You can also setup breakpoints manually instead of using the --pdb
option.
If you are part of the group of maintainers and have correct user permissions
+on PyPI, the following steps can be used to release a new version for
+sxapi
:
Make sure all unit tests are successful.
Tag the current commit on the main branch with a release tag, e.g., v1.2.3
.
Push the new tag to the upstream repository, e.g., git push upstream v1.2.3
Clean up the dist
and build
folders with tox -e clean
+(or rm -rf dist build
)
+to avoid confusion with old builds and Sphinx docs.
Run tox -e build
and check that the files in dist
have
+the correct version (no .dirty
or git hash) according to the git tag.
+Also check the sizes of the distributions, if they are too big (e.g., >
+500KB), unwanted clutter may have been accidentally included.
Run tox -e publish -- --repository pypi
and check that everything was
+uploaded to PyPI correctly.
+ | + |
+ |
+ | + |
+ | + |
+ |
+ | + |
+ | + |
|
+
+ | + |
|
+
|
+
+ | + |
+ | + |
+ |
This is the documentation of sxapi.
+Note
+This is the main page of your project’s Sphinx documentation.
+It is formatted in reStructuredText. Add additional pages
+by creating rst-files in docs
and adding them to the toctree below.
+Use then references in order to link them from this page, e.g.
+Contributors and Changelog.
It is also possible to refer to the documentation of other Python packages
+with the Python domain syntax. By default you can reference the
+documentation of Sphinx, Python, NumPy, SciPy, matplotlib,
+Pandas, Scikit-Learn. You can add more by extending the
+intersphinx_mapping
in your Sphinx’s conf.py
.
The pretty useful extension autodoc is activated by default and lets +you include documentation from docstrings. Docstrings can be written in +Google style (recommended!), NumPy style and classical style.
+++++++ +++Apache License
+Version 2.0, January 2004
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
++
+- +
Definitions.
+“License” shall mean the terms and conditions for use, reproduction, +and distribution as defined by Sections 1 through 9 of this document.
+“Licensor” shall mean the copyright owner or entity authorized by +the copyright owner that is granting the License.
+“Legal Entity” shall mean the union of the acting entity and all +other entities that control, are controlled by, or are under common +control with that entity. For the purposes of this definition, +“control” means (i) the power, direct or indirect, to cause the +direction or management of such entity, whether by contract or +otherwise, or (ii) ownership of fifty percent (50%) or more of the +outstanding shares, or (iii) beneficial ownership of such entity.
+“You” (or “Your”) shall mean an individual or Legal Entity +exercising permissions granted by this License.
+“Source” form shall mean the preferred form for making modifications, +including but not limited to software source code, documentation +source, and configuration files.
+“Object” form shall mean any form resulting from mechanical +transformation or translation of a Source form, including but +not limited to compiled object code, generated documentation, +and conversions to other media types.
+“Work” shall mean the work of authorship, whether in Source or +Object form, made available under the License, as indicated by a +copyright notice that is included in or attached to the work +(an example is provided in the Appendix below).
+“Derivative Works” shall mean any work, whether in Source or Object +form, that is based on (or derived from) the Work and for which the +editorial revisions, annotations, elaborations, or other modifications +represent, as a whole, an original work of authorship. For the purposes +of this License, Derivative Works shall not include works that remain +separable from, or merely link (or bind by name) to the interfaces of, +the Work and Derivative Works thereof.
+“Contribution” shall mean any work of authorship, including +the original version of the Work and any modifications or additions +to that Work or Derivative Works thereof, that is intentionally +submitted to Licensor for inclusion in the Work by the copyright owner +or by an individual or Legal Entity authorized to submit on behalf of +the copyright owner. For the purposes of this definition, “submitted” +means any form of electronic, verbal, or written communication sent +to the Licensor or its representatives, including but not limited to +communication on electronic mailing lists, source code control systems, +and issue tracking systems that are managed by, or on behalf of, the +Licensor for the purpose of discussing and improving the Work, but +excluding communication that is conspicuously marked or otherwise +designated in writing by the copyright owner as “Not a Contribution.”
+“Contributor” shall mean Licensor and any individual or Legal Entity +on behalf of whom a Contribution has been received by Licensor and +subsequently incorporated within the Work.
+- +
Grant of Copyright License. Subject to the terms and conditions of +this License, each Contributor hereby grants to You a perpetual, +worldwide, non-exclusive, no-charge, royalty-free, irrevocable +copyright license to reproduce, prepare Derivative Works of, +publicly display, publicly perform, sublicense, and distribute the +Work and such Derivative Works in Source or Object form.
- +
Grant of Patent License. Subject to the terms and conditions of +this License, each Contributor hereby grants to You a perpetual, +worldwide, non-exclusive, no-charge, royalty-free, irrevocable +(except as stated in this section) patent license to make, have made, +use, offer to sell, sell, import, and otherwise transfer the Work, +where such license applies only to those patent claims licensable +by such Contributor that are necessarily infringed by their +Contribution(s) alone or by combination of their Contribution(s) +with the Work to which such Contribution(s) was submitted. If You +institute patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the Work +or a Contribution incorporated within the Work constitutes direct +or contributory patent infringement, then any patent licenses +granted to You under this License for that Work shall terminate +as of the date such litigation is filed.
- +
Redistribution. You may reproduce and distribute copies of the +Work or Derivative Works thereof in any medium, with or without +modifications, and in Source or Object form, provided that You +meet the following conditions:
++
+- +
You must give any other recipients of the Work or +Derivative Works a copy of this License; and
- +
You must cause any modified files to carry prominent notices +stating that You changed the files; and
- +
You must retain, in the Source form of any Derivative Works +that You distribute, all copyright, patent, trademark, and +attribution notices from the Source form of the Work, +excluding those notices that do not pertain to any part of +the Derivative Works; and
- +
If the Work includes a “NOTICE” text file as part of its +distribution, then any Derivative Works that You distribute must +include a readable copy of the attribution notices contained +within such NOTICE file, excluding those notices that do not +pertain to any part of the Derivative Works, in at least one +of the following places: within a NOTICE text file distributed +as part of the Derivative Works; within the Source form or +documentation, if provided along with the Derivative Works; or, +within a display generated by the Derivative Works, if and +wherever such third-party notices normally appear. The contents +of the NOTICE file are for informational purposes only and +do not modify the License. You may add Your own attribution +notices within Derivative Works that You distribute, alongside +or as an addendum to the NOTICE text from the Work, provided +that such additional attribution notices cannot be construed +as modifying the License.
You may add Your own copyright statement to Your modifications and +may provide additional or different license terms and conditions +for use, reproduction, or distribution of Your modifications, or +for any such Derivative Works as a whole, provided Your use, +reproduction, and distribution of the Work otherwise complies with +the conditions stated in this License.
+- +
Submission of Contributions. Unless You explicitly state otherwise, +any Contribution intentionally submitted for inclusion in the Work +by You to the Licensor shall be under the terms and conditions of +this License, without any additional terms or conditions. +Notwithstanding the above, nothing herein shall supersede or modify +the terms of any separate license agreement you may have executed +with Licensor regarding such Contributions.
- +
Trademarks. This License does not grant permission to use the trade +names, trademarks, service marks, or product names of the Licensor, +except as required for reasonable and customary use in describing the +origin of the Work and reproducing the content of the NOTICE file.
- +
Disclaimer of Warranty. Unless required by applicable law or +agreed to in writing, Licensor provides the Work (and each +Contributor provides its Contributions) on an “AS IS” BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied, including, without limitation, any warranties or conditions +of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A +PARTICULAR PURPOSE. You are solely responsible for determining the +appropriateness of using or redistributing the Work and assume any +risks associated with Your exercise of permissions under this License.
- +
Limitation of Liability. In no event and under no legal theory, +whether in tort (including negligence), contract, or otherwise, +unless required by applicable law (such as deliberate and grossly +negligent acts) or agreed to in writing, shall any Contributor be +liable to You for damages, including any direct, indirect, special, +incidental, or consequential damages of any character arising as a +result of this License or out of the use or inability to use the +Work (including but not limited to damages for loss of goodwill, +work stoppage, computer failure or malfunction, or any and all +other commercial damages or losses), even if such Contributor +has been advised of the possibility of such damages.
- +
Accepting Warranty or Additional Liability. While redistributing +the Work or Derivative Works thereof, You may choose to offer, +and charge a fee for, acceptance of support, warranty, indemnity, +or other liability obligations and/or rights consistent with this +License. However, in accepting such obligations, You may act only +on Your own behalf and on Your sole responsibility, not on behalf +of any other Contributor, and only if You agree to indemnify, +defend, and hold each Contributor harmless for any liability +incurred by, or claims asserted against, such Contributor by reason +of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
+APPENDIX: How to apply the Apache License to your work.
+++To apply the Apache License to your work, attach the following +boilerplate notice, with the fields enclosed by brackets “[]” +replaced with your own identifying information. (Don’t include +the brackets!) The text should be enclosed in the appropriate +comment syntax for the file format. We also recommend that a +file or class name and description of purpose be included on the +same “printed page” as the copyright notice for easier +identification within third-party archives.
+Copyright [yyyy] [name of copyright owner]
+Licensed under the Apache License, Version 2.0 (the “License”); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at
+++Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an “AS IS” BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License.
+
+ s | ||
+ |
+ sxapi | + |
+ |
+ sxapi.base | + |
+ |
+ sxapi.cli | + |
+ |
+ sxapi.cli.cli | + |
+ |
+ sxapi.cli.cli_user | + |
+ |
+ sxapi.cli.subparser | + |
+ |
+ sxapi.cli.subparser.get_sensor_data | + |
+ |
+ sxapi.cli.subparser.token | + |
+ |
+ sxapi.publicV2 | + |
+ |
+ sxapi.publicV2.alarms | + |
+ |
+ sxapi.publicV2.data | + |
+ |
+ sxapi.publicV2.feedrations | + |
+ |
+ sxapi.publicV2.groups | + |
+ |
+ sxapi.publicV2.sensordata | + |
+ |
+ sxapi.publicV2.todos | + |
+ |
+ sxapi.publicV2.users | + |
++a new API to interact with the smaXtec system.
+
sxapi lets you import and export data through an easy to understand python API and a command line interface.
+This project has been set up using PyScaffold 4.1. For details and usage +information on PyScaffold see https://pyscaffold.org/.
++ Searching for multiple words only shows matches that contain + all words. +
+ + + + + + +