fsapi-tools 2.0.4
Frontier Smart Firmware Tools and FSAPI Implementation.

<div id="top"></div>
<div align="center">

![Company logo would be displayed here.](docs/graphics/company_logo.png)

</div>

# Frontier Smart API and Firmware Tools

[![python](https://img.shields.io/badge/python-3.8+-blue.svg?logo=python&labelColor=grey)](https://www.python.org/downloads/)
![Codestyle](https://img.shields.io:/static/v1?label=Codestyle&message=black&color=black)
![License](https://img.shields.io:/static/v1?label=License&message=MIT&color=blue)
[![PyPI](https://img.shields.io/pypi/v/fsapi-tools)](https://pypi.org/project/fsapi-tools/)

This repository comprises various tools written in `python3` that are designed to analyze properties of firmware binaries provided by Frontier Smart (formerly Frontier Silicon - FS) and interact with the inbuilt API. The decompiler used in this repository was initially forked from the [dead0007](https://github.com/molnarg/dead0007/blob/master/README.md) repository.

Although there are other repositories that focus on the specific API, the implementation provided here includes **ALL** available `Nodes` that were invented/developed by Frontier Smart. These nodes were converted from Java source code, and the tool used for the conversion can be found in this repository as well (the [Tool](apk/node_converter.py)).

Features:

- ISUTool: An inspector for Frontier Smart firmware binaries.
- Pattern Specification: Designed for ISU binaries to be used in ImHex.
- Python3 FSAPI implementation.
- XDR-Decompiler: For decompiling binary packed JavaScript files.
- FSAPI-NET Tool: Enables interaction with Frontier Smart IoT devices.

## Installation

The FS-API implementation is now available on the Python Package Index (PyPi). You can easily install it by using the `pip` package manager.

```bash
pip install fsapi-tools
```

## Firmware Binaries

To utilize the tools provided by this repository, the majority of available firmware binaries have been relocated to the [frontier-smart-firmwares](https://github.com/MatrixEditor/frontier-smart-firmwares) repository. Many of these binaries were forked from the [frontier-silicon-firmwares](https://github.com/cweiske/frontier-silicon-firmwares) repository maintained by cweiske.

## Documents

A comprehensive review of the firmware binaries used to update Frontier Smart devices is available in the following document: [Firmware-Analysis](https://matrixeditor.github.io/fsapi-tools/firmware-analysis.html). The documentation for the Frontier Smart API (NetRemoteApi) can be found here: [FSAPI Docs](https://matrixeditor.github.io/fsapi-tools/fsapi-tools.html). Additionally, the decompiler for ECMAScript is located in the `decompiler/` directory, which can be utilized for decompiling purposes.

## Overview

As mentioned earlier, this repository offers a utility for interacting with the FSAPI (Frontier Smart API) and provides an analysis of the firmware binary structure. The research conducted involved the following devices and apps:

- Device: Medion MD87805
- Apps: Lifestream II and UNDOK

These devices and apps were utilized during the research and analysis process. The source code includes a package called `src/com/frontier_silicon/NetRemoteLib/Node/`, which houses all the available nodes implemented as Java classes.

### Network Traffic

Let's examine the network traffic generated by the internet radio. To capture all packets, a proxy can be quite useful. However, in this case, since setting up a simple proxy on the device is not possible, the traffic was captured directly on the connected Wi-Fi access point.

Upon a quick analysis of the captured network traffic using Wireshark, several interesting findings emerge:

- The communication between the device and clients is handled using HTTP.
- Specific URLs are queried when searching for a software update. These URLs are:
    - update.wifiradiofrontier.com/FindUpdate.aspx
    - update.wifiradiofrontier.com/Update.aspx

The first URL returns a `404` or `403` HTTP status code if no update is available. However, if an update is available, the first URL query will return an XML response with update information.

The firmware binaries can be found at the second URL, with the mandatory parameter `f=/updates/xxx`. The naming convention for the files is structured as follows:

```bash
ir-$MODULE-$INTERFACE-$IFACEVERSION-${MODEL}_V$VERSION.$REVISION-$BRANCH
```

In the case of the internet radio device used here, an example file name would be:

```
ir-mmi-FS2026-0500-0549_V2.12.25c.EX72088-1A12
```

Please note that in the URL, the file name replaces `_V` with a simple dot. To download an update file, you can use `fsapi-net` or the `fsapi` module directly. The following command retrieves all the specified firmware binaries from the given file.

```bash
$ fsapi-net isu --file ./bin/updates.txt --verbose
# alternative with local device:
$ fsapi-net isu --find --collect myFile $IP_ADDRESS --verbose
```
<p align="right">(<a href="#top">back to top</a>)</p>

## Tools

There are three tools included in this repository: `isutool`, `fsapi-net` and  `fsapi-esbin`.

### ISUTool

The following example provides a brief overview of how the tool can be used. For detailed usage instructions, please refer to the [ISUTool Documentation](https://matrixeditor.github.io/fsapi-tools/isutool.html).

```bash
$ isutool --header firmware.isu.bin
[in] firmware.isu.bin
    > ISUHeader:
        - magic: 0x1176
        - length: 124
        - isu_version: 1
        - version: '2.14.33c.EX85186-1A17'
        - customisation: 'ir-mmi-FS2026-0500-0795'
        - os_major_version: None
        - os_minor_version: None
        - uuid: 32b8d035-d81b-42f0-436a-a686d0c9a8ab

$ isutool firmware.isu.bin --json ./firmware.json
[in] firmware.isu.bin
[out] JSON saved to firmware.json

$ isutool firmware.isu.bin --extract-archive ./rootfs
[in] firmware.isu.bin
[out] Directory Archive:
    > icons/ (5)
        > New folder/ (4)
            - dlna_icon_large.jpg
            - dlna_icon_large.png
            - dlna_icon_small.jpg
            - dlna_icon_small.png
        - dlna_icon_large.jpg
        - dlna_icon_large.png
        - dlna_icon_small.jpg
        - dlna_icon_small.png
    > web/ (10)
# --- snip ---
```

### XDR Decompiler

This module/tool is still under development and can cause errors an execution. Also, this tool can only be called on UNIX systems that are able to execute the `./decompiler/ecma-decompiler` binary.

```console
$ fsapi-xdr --help
usage: fsapi-xdr [-h] [-d] [-o OUT] [--use-decompiler DECOMPATH] [-r] path

positional arguments:
  path                  The target file that will be used to operate on.

optional arguments:
  -h, --help            show this help message and exit
  -d, --decompile       Indicates that the given input file should be decompiled.
  -o OUT, --out OUT     The path were the decompiled output should be saved.

  --use-decompiler DECOMPATH
                        Specifies the path to the decompiler.
  -r, --recurse         Indicates that all files in the given directory should be decompiled
```

### NET - FSAPI

This small tool can be utilized to interact with Frontier Smart devices via CLI.

```bash
$ fsapi-ctl set netremote.sys.info.friendlyName "MedionIR" 127.0.0.1
> FSResponse('netRemote.sys.info.friendlyName', <Method.SET: 'SET'>)
    - status: <Status.FS_OK: 'FS_OK'>

$ fsapi-ctl get netremote.sys.info.friendlyName 127.0.0.1
> FSResponse('netRemote.sys.info.friendlyName', <Method.GET: 'GET'>)
    - status: <Status.FS_OK: 'FS_OK'>
    - value: 'Hello World'

$ fsapi-ctl -X update fetch 127.0.0.1 .
[+] Generating current URL...
    > URL: 'https://update.wifiradiofrontier.com/Update.aspx?f=/updates/ir-mmi-FS2026-0500-0549.2.12.25c.EX72088-1A12.isu.bin'

$ fsapi-ctl view netremote.sys.power
> SYS: Power (netRemote_sys_power_nt):
    - path: 'netRemote.sys.power'
    - readonly: False
    - cacheable: True
    - notifying: True
    - type: <class 'fsapi.net.base.NodeE8'>
    - prototype:
        [0] => 'value'
            - length: 1
            - type: <ArgType.ARG_TYPE_E8: 17>
    - enum values:
        [0] => 'OFF'
        [1] => 'ON'
```

## Usage Examples

### ISU API

```python
from fsapi.isu import ISU
from fsapi.isu.util import DataclassPrinter

isu = ISU << "firmware.isu.bin"
# load an ISUHeader object and print the loaded data
pp = DataclassPrinter()
pp.print_object(isu.header)
```

## FSAPI

```python
from fsapi.net import FSDevice, wrap, nodes

# First, create the radio object
device = FSDevice("127.0.0.1")

# Create a new session id (only one at a time)
device.new_session()

# In order to simplify the usage of the FSDevice class
api = wrap(device)
friendly_name = api.friendly_name
# or manually
response = device.get(nodes / "netRemote.sys.info.friendlyName")
if response.success:
    #_ Again, type(content) = nodes.BaseSysInfoFriendlyName
    friendly_name = response.content.value

# Apply a new name via wrapper
api.friendly_name = "FooBar"
# or manually
device.put(nodes / "netRemote.sys.info.friendlyName", value="FooBar")

# get all elements of a list
valid_modes = api.ls_valid_modes()
# get a certain amount of elements beginning at index 3
valid_modes = api.ls_valid_modes(_pos=3, max_items=10)
```

## Software Update

```python
from fsapi.isu import find_update, url_get_update, get_update

# 1.Find and download updates
# without custom netconfig -> HTTPS traffic
request = find_update('$MAC', '$CUSTOM', '$VERSION')

# with custom config -> force HTTP traffic
config = FSNetConfiguration(http_pool=urllib3.HTTPConnectionPool('$HOST'))
request = find_update('$MAC', '$CUSTOM', '$VERSION', netconfig=config)

# without custom netconfig -> HTTPS traffic
if request.has_update:
    for _software in request.updates:
        get_update('$FILE_PATH', software=_software)
```

## Contributing

Contributions are highly appreciated as they contribute to the growth and improvement of the open-source community. If you have any suggestions that could enhance this project, please feel free to fork the repository and create a pull request. Alternatively, you can also open an issue with the "enhancement" tag.

To contribute, follow these steps:

1. Fork the Project
2. Create a new branch for your feature (`git checkout -b feature/new-feature`)
3. Commit your changes (`git commit -m 'Add some new amazing feature'`)
4. Push your changes to the branch (`git push origin feature/new-feature`)
5. Open a Pull Request

<p align="right">(<a href="#top">back to top</a>)</p>

<!-- LICENSE -->
---
## License

Distributed under the MIT License. See `MIT.txt` for more information.