WebAPI Core

The next module of this small API implementation focuses on the “FsNetRemoteLib.” All nodes presented here were converted from the Java source code of the app “Medion Lifestream 2.”

The script used for converting the code can be found in the repository. The source code was converted to reduce the manual effort, as the final “_nodes.py” file contained more than 4000 lines of code.

When querying a resource or attempting to set a value to a specific node, there is always a status message that accompanies the response. Common possible values for this status are:

Status

Body

Description

FS_OK

True

If everything goes right the status is set to FS_OK

FS_PACKET_BAD

False

This status code will be returned if a value should be applied to a read-only node.

FS_NODE_BLOCKED

False

Sometimes this status is given, maybe because the node was deactivated on the device.

FS_NODE_DOES_NOT_EXIST

False

As the name already states, the requested node is not implemented on that device.

FS_TIMEOUT

False

The device takes too long to respond

FS_FAIL

False

If the parameters given in the url are mot matching the node criteria, the request will fail.

net.nodes = Path ''

Global path object for defined API nodes.

This object can be used to search for registered node classes. For instance, following this control flow leads to all available nodes:

>>> available_nodes = list(nodes.iter_nodes())

Each node is mapped to a unique path, which can be accessed by using the true div operation in python:

>>> nodes / "foo" / "bar"
Path 'foo.bar'

Alternatively, the amount of operations can be reduced by specifying the complete path directly:

>>> nodes / "foo.bar"
Path 'foo.bar'
net.dynamic = <object object>

Specifier for dynamic prototypes.

If the structure of a certain node is not clear, the “dynamic” prototype can be used temporarily to parse incoming XML data.

>>> class foo_nt(Node):
...     class Meta:
...         path = "foo.bar"
...         prototype = dynamic
...

Note that list nodes should extend the NodeList class as the parsing workflow is slightly different.

class fsapi.net.NodeBase(name, bases, attrs: dict, **kwargs)

Base class for node classes.

In order to enable access to all defined nodes this class will add each defined node class that specifies a “path” to an internal map. Attributes are defined using an inner “Meta” class that stores special class attributes:

>>> class foo_nt(Node):
...     class Meta:
...         path = "foo.bar"
...         name = "Foo node"
...         prototype = [Argument(type=ArgType.ARG_TYPE_U16)]
...

Using the global nodes instance makes it easier to create instances of the previously defined node class.

>>> path = nodes / "foo" / "bar"
>>> if path.exists():
...     node: foo_nt = path.create()
...

Note that all attributes defined in the meta class will be accessable as class properties of the defined node class. For instance:

>>> node_class = path.get_node_type()
>>> node_class.path
'foo.bar'
>>> node.path
AttributeError: 'foo.bar' object has no attribute 'path'
property cacheable: bool

Specifies whether this node is cacheable.

property description: str

Documentation of the node.

property is_list: bool

Returns whether this class is a list class.

property name: str

Graphical display name

property notifying: bool

Specifies whether GET_NODTIFIES is applicable.

property path: str

Defines the unique path of a node.

property prototype: List[Argument] | object

Returns the prototype if this node.

read(tree: Element) Node

Converts XML input into the corresponding node object.

This method will automatically convert XML list structures to node list items only if the desired node class extends the NodeList class.

>>> class foo_nt(Node):
...     ... # meta is defined here
...
>>> node = foo_nt.read(xml_element)
Parameters:
  • cls (Type[Node]) – the node class

  • tree (ElementTree.Element) – the fsapiResponse XML element

Raises:

ValueError – if there is an invalid prototype

Returns:

the created node object storing the node’s value

Return type:

Node

read_list(tree: Element) Node

Converts XML input to a node extending the NodeList class.

Parameters:
  • cls (Type[NodeList]) – the node class

  • tree (ElementTree.Element) – the fsapiResponse XML element

Returns:

a node object storing a list of NodeListItem objects

Return type:

Node

property readonly: bool

Returns true if only non-write operations are permitted.

class fsapi.net.Node(value=None)

Base class of all node classes.

Each node stores a value and the node class stores the node’s meta information. Be aware of the difference, a node object is designed to store a node’s value, NOT the meta information. Those are linked to the class instance.

>>> path = NodePath("netRemote.sys.info.version")
>>> node_class = path.get_node_type()
>>> node_class.path
"netRemote.sys.info.version"
>>> node = path.create()
>>> node.path
AttributeError: '...' object has no attribute 'path'
Parameters:

value – the node’s value

property cls: Type[Node]

The node’ class (quick access property)

has_method(method: str) bool

Checks whether the provided method is allowed

supports_module(module_name: str) bool

Checks whether the provided FS module is supported.

property value: int | str | List[NodeListItem] | NodeValue

The node’s value

Returns:

the currently applied node value or None

Return type:

int | str | t.List[NodeListItem] | NodeValue

class fsapi.net.NodePath(name: str, base: str = None)

A class to search and navigate to implemented nodes.

NodePath objects store some utility attributes and capabilities that help searching for implemented notes. For instance, the following code searches for all implemented nodes starting with the path “netRemote.misc”:

>>> path = NodePath("netRemote") / "misc"
>>> list(path.iter_nodes())
['netRemote.misc.fsDebug.component', 'netRemote.misc.fsDebug.traceLevel', ...]

This class is designed to provide access to implemented node classes, create new instances of nodes and to be able to search for specific nodes. In order to verfiy that a certain node is implemented, there is a verification method:

>>> path = NodePath("netRemote") / "misc" / "fsDebug.component"
>>> path.exists()
True
>>> path.create()
Node(path="netRemote.misc.fsDebug.component", has_value=True)
create(*args, **kwargs) Node

Creates a new instance of a node with the given argument values.

Returns:

the new node instance

Return type:

Node

Raises:

KeyError – if the node path does not exists

exists() bool

Verifies that a certain node exists.

Returns:

True if the node is implemented, false otherwise

Return type:

bool

from_xml(tree: ElementTree) Node

Tries to convert the given XML tree to a node.

Parameters:

tree (ElementTree.ElementTree) – the XML response of the device

Raises:

KeyError – if the node does not exists

Returns:

the new node instance

Return type:

Node

get_node_type() Type[Node]

Returns the node type.

Returns:

the type of the implemented node

Return type:

Type[Node]

Raises:

KeyError – if the node path does not exists

iter_nodes() Iterator[str]

Iterates over all nodes that start with this path.

Returns:

all filtered nodes as an iterator

Return type:

Iterator[str]

class fsapi.net.ArgType(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)

Value types for node prototypes.

Argument types are used by node prototypes to enable appropriate de-serialization of incoming data.

ARG_TYPE_C8 = 16

C8-Array (char array), type: str

ARG_TYPE_E8 = 17

Type defined by an Enum, type: int

ARG_TYPE_S16 = 22

Signed Int16, type: int

ARG_TYPE_S32 = 23

Signed Int32, type: int

ARG_TYPE_S8 = 21

Signed Int8, type: int

ARG_TYPE_U = 24

Array of data, type: str

ARG_TYPE_U16 = 19

Unsigned Int16, type: int

ARG_TYPE_U32 = 20

Unsigned Int32, type: int

ARG_TYPE_U8 = 18

Unsigned Int8, type: int

ARG_TYPE_UNKNOWN = -1

Invalid type, will be mapped to str

to_python(value: str) Any

Convert the given value to a Python object based on the ArgType.

This method is used to convert a string representation of a value to a Python object of the appropriate type based on the ArgType.

Parameters:

value (str) – The value as a string to be converted.

Returns:

The Python object representing the converted value.

class fsapi.net.Argument(name: str = 'value', length: int = 1, type: ArgType = ArgType.ARG_TYPE_UNKNOWN)

Defines an argument within a node prototype.

A node’s prototype contains arguments in order to parse XML responses back to python values.

Parameters:
  • name (str) – The name of this argument, default “value”

  • length (int) – the length of this value, 1 := one element

  • type (ArgType) – the argument type used to parse the XML content

class fsapi.net.NodeValue(type: ArgType, value: int | str | None = None)

Anonymous value class.

When using dynamic prototypes, this class is used to represent the values in a XML response.

Parameters:

type – the argument type

Param:

value: the stored value (enum values won’t be covered)

Node Classes

class fsapi.net.NodeInt(value=None, minimum=0, maximum=0)

Defines an integer node with an acceptable range of values.

>>> node = NodeInt(minimum=0, maximum=10)
>>> node.value = 11
ValueError: Expected value between 0 and 10 - got 11
Parameters:
  • value (int) – the node’s value

  • minimum (int) – the minimum value that gets accepted

  • maximum (int) – the maximum value that gets accepted

class fsapi.net.NodeList(items: list = None)

Special node that contains multiple items.

You can use this class with the len function or within a loop.

>>> node_list = ...
>>> len(node_list)
2
>>> for item in node_list:
...     # inspect item
Parameters:

items (list) – a list of NodeListItem objects

property items: t.List[NodeListItem]

Returns the stored items as a list.

Returns:

the stored list items

Return type:

t.List[NodeListItem]

class fsapi.net.NodeListItem(attributes: dict = None)

Content item of a NodeList.

property fields: t.List[str]

Returns a list of field names.

Returns:

all field names stored by this item.

Return type:

t.List[str]

get(field_name: str, _NodeListItem__default=None) str | NodeE8 | int | NodeValue | None

Return the value for key if key is in the attribites, else default.

Parameters:
  • field_name (str) – the field’s name

  • __default – the default return value, defaults to None

Returns:

the stored, converted python representation

Return type:

_NodeListItemValue | None

class fsapi.net.NodeS8(value: int = 0)

Signed Int8 node (min: -127, max: 127)

class fsapi.net.NodeS16(value: int = 0)

Signed Int16 node (min: -0x7FFF, max: 0x7FFF)

class fsapi.net.NodeS32(value: int = 0)

Signed Int32 node (min: -0x7FFFFFFF, max: 0x7FFFFFFF)

class fsapi.net.NodeU8(value: int = 0)

Unsigned Int8 node (min: 0, max: 255)

class fsapi.net.NodeU16(value: int = 0)

Unsigned Int16 node (min: 0, max: 0xFFFF)

class fsapi.net.NodeU32(value: int = 0)

Unsigned Int32 node (min: 0, max: 0xFFFFFFFF)

class fsapi.net.NodeE8(value=None, defaults=None)

Enum node. (internal mapping contains enum names)

property enum_value: str | Any | None

Returns the associated value’s name (if present)

Returns:

the value’s names

Return type:

str | Any

class fsapi.net.NodeC8(value=None, max_size: int = 1024)

Character array node (string)