Skip to content

Commit

Permalink
Merge pull request #6 from clementprevot/feat/raw-mode
Browse files Browse the repository at this point in the history
feat: Add `raw` mode
  • Loading branch information
clementprevot authored Nov 15, 2022
2 parents 83dcfb1 + 3148033 commit 5c2f352
Show file tree
Hide file tree
Showing 9 changed files with 145 additions and 52 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ ENV/
env.bak/
venv.bak/
pythonenv*
/pyduro/

# Spyder project settings
.spyderproject
Expand Down
20 changes: 15 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,15 +65,13 @@ And here the different part of the frame:
A response will always be formed in pretty much the same way:

```
abcdefghijkl123456 \x0200000065Serial=123456;IP=192.168.1.250;Type=v13std;Ver=705;Build=38;Lang=0\x04
abcdefghijkl123456\x0200000065Serial=123456;IP=192.168.1.250;Type=v13std;Ver=705;Build=38;Lang=0\x04
```

* **abcdefghijkl** - `appId`, 12 alphanumerical (upper and lowercase) characters -
Uniquely identify the application that the oven is talking to
* **123456** - `controllerId`, 6 digits - This is the "Serial number" of the
oven responding
* **space** or **\*** or **-** - Encryption level of the frame _(' ' = not
encrypted, '*' = RSA encrypted, '-' = XTEA encrypted)_
* **\x02** - `startChar`, the ASCII character `0x02` _(so 1 char, not "\x02")_ -
This is the separator to identify the beginning of the response
* **00** - `function`, 2 digits - Identify the type of response _(see below)_
Expand Down Expand Up @@ -106,7 +104,8 @@ There is a limited set of functions you can use in the NBE protocol:
* **9**: Read info
* **10**: Read available programs

> Note that your burner might not support all of them.
> Note that your burner might not support all of them and might also support
> others (for example, `11` is a supported type on Aduro H1 burners).
### More info

Expand All @@ -131,7 +130,7 @@ pip install pyduro
Simply import the actions and use them:

```python
from pyduro.actions import discover, get, set
from pyduro.actions import discover, get, set, raw

discover.run()
get.run(
Expand All @@ -149,6 +148,13 @@ set.run(
path="<path>"
value="<value>"
)
raw.run(
burner_address="<burner IP address>",
serial="<burner serial number>",
pin_code="<burner pin code>",
function_id="<function ID>",
payload="<payload>"
)
```

### Response
Expand Down Expand Up @@ -223,6 +229,10 @@ error).
> * "misc"
> * "alarm"
> * "manual"
>
> To see all sub element of a path, add `.*` at the end of the path.
> To see a specific element of a path, add `.<element name>` at the end of the
> path.
> For `consumption` action, you can pass one of the following path:
>
Expand Down
60 changes: 43 additions & 17 deletions src/pyduro/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import argparse
import json

from pyduro.actions import ACTIONS, FUNCTIONS, discover, get, set
from pyduro.actions import FUNCTIONS, discover, get, set, raw

# --------------------------------------------------------------------------------------------------

Expand Down Expand Up @@ -40,48 +40,74 @@ def main():
help="Display the raw frames sent and received",
action="store_true",
)
parser.add_argument(
"action",
help='Run the given action (Default = "discover")',

# create sub-parser
sub_parsers = parser.add_subparsers(title="Action", dest="action")

sub_parsers.add_parser("discover", help="Discover any burner on your network")

parser_get = sub_parsers.add_parser("get", help="Get information from a burner")
parser_get.add_argument(
"function_name",
help="Specify the part of the burner you want to query",
type=str,
choices=FUNCTIONS,
)
parser_get.add_argument(
"path",
help="The path for your query",
type=str,
choices=ACTIONS,
nargs="?",
default=ACTIONS[0],
)
parser.add_argument(
"function",
help="Specify the part of the burner you want to query/modify",

parser_raw = sub_parsers.add_parser("raw", help="Send raw request to a burner")
parser_raw.add_argument(
"function_id",
help="Specify the function you want to call on the burner",
type=int,
)
parser_raw.add_argument(
"payload",
help="The payload of your request",
type=str,
choices=FUNCTIONS,
nargs="?",
)
parser.add_argument(

parser_set = sub_parsers.add_parser("set", help="Update setting of a burner")
parser_set.add_argument(
"path",
help="The path for your query/modification",
help="The path for your modification",
type=str,
nargs="?",
)
parser.add_argument(
parser_set.add_argument(
"value",
help="The payload for your modification",
type=str,
nargs="?",
)

args = parser.parse_args()

response = None
if args.action == "discover":
if args.action is None or args.action == "discover":
response = discover.run(verbose=args.verbose)
elif args.action == "get":
response = get.run(
burner_address=args.burner,
serial=args.serial,
pin_code=args.pin,
function_name=args.function,
function_name=args.function_name,
path=args.path,
verbose=args.verbose,
)
elif args.action == "raw":
response = raw.run(
burner_address=args.burner,
serial=args.serial,
pin_code=args.pin,
function_id=args.function_id,
payload=args.payload,
verbose=args.verbose,
)
elif args.action == "set":
response = set.run(
burner_address=args.burner,
Expand Down
1 change: 0 additions & 1 deletion src/pyduro/actions/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

DEFAULT_DISCOVERY_ADDRESS = "255.255.255.255"

ACTIONS = ["discover", "get", "set"]
FUNCTIONS = [
"settings",
"range",
Expand Down
26 changes: 13 additions & 13 deletions src/pyduro/actions/get.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,30 +26,30 @@ def run(burner_address, serial, pin_code, function_name, path="*", verbose=False
pin_code (str): The secret pincode of the burner (this can often be found on a sticker somewhere on the burner).
Note that this should be a 10 characters string. Any longer string will be truncated and any shorter string
will be right padded with 0s.
function (int): The part of the burner information you want to get.
path (str): The path of the payload to modify on the burner.
function_name (str): The name of the function you want to run.
path (str): The path of the payload to load from the burner (or the payload).
verbose (bool): Indicates if we want the frame to be printed before sending it.
Default: False
"""

try:
function = None
function_id = None

if function_name == "settings":
function = FUNCTIONS.get_settings.value
function_id = FUNCTIONS.get_settings.value

if path is None or len(path) == 0:
print("You must pass one of the following as path: {}".format(SETTINGS))

return
if function_name == "range":
function = FUNCTIONS.get_settings_range.value
function_id = FUNCTIONS.get_settings_range.value
elif function_name == "operating":
function = FUNCTIONS.get_operating_data.value
function_id = FUNCTIONS.get_operating_data.value
elif function_name == "advanced":
function = FUNCTIONS.get_advanced_data.value
function_id = FUNCTIONS.get_advanced_data.value
elif function_name == "consumption":
function = FUNCTIONS.get_consumption_data.value
function_id = FUNCTIONS.get_consumption_data.value

if path is None or len(path) == 0 or path not in CONSUMPTION_DATA:
print(
Expand All @@ -60,21 +60,21 @@ def run(burner_address, serial, pin_code, function_name, path="*", verbose=False

return
elif function_name == "chart":
function = FUNCTIONS.get_chart_data.value
function_id = FUNCTIONS.get_chart_data.value
elif function_name == "logs":
function = FUNCTIONS.get_event_log.value
function_id = FUNCTIONS.get_event_log.value

path = (
time.strftime("%y%m%d:%H%M%S;", time.localtime())
if path is None or len(path) == 0 or path == "now"
else path
)
elif function_name == "info":
function = FUNCTIONS.get_info.value
function_id = FUNCTIONS.get_info.value
elif function_name == "versions":
function = FUNCTIONS.get_sw_versions.value
function_id = FUNCTIONS.get_sw_versions.value

frame = Frame(serial, pin_code, function, path)
frame = Frame(serial, pin_code, function_id, path)

response = frame.send(burner_address, verbose=verbose)

Expand Down
42 changes: 42 additions & 0 deletions src/pyduro/actions/raw.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# -*- coding: utf-8 -*-

# --------------------------------------------------------------------------------------------------
import time

from pyduro.actions import CONSUMPTION_DATA, SETTINGS
from pyduro.protocol import (
FUNCTIONS,
FunctionNotFoundException,
PayloadToLargeException,
)
from pyduro.protocol.frame import Frame

# --------------------------------------------------------------------------------------------------


def run(burner_address, serial, pin_code, function_id, payload, verbose=False):
"""
Get information from the given burner.
Args:
burner_address (str): The IP address of the burner.
serial (str): The serial number of the burner (this can often be found on a sticker somewhere on the burner).
Note that this should be a 6 characters string. Any longer string will be truncated and any shorter string
will be left padded with 0s.
pin_code (str): The secret pincode of the burner (this can often be found on a sticker somewhere on the burner).
Note that this should be a 10 characters string. Any longer string will be truncated and any shorter string
will be right padded with 0s.
function_id (int): The raw identifier of the function you want to run on the burner.
payload (str): The payload to send to the burner.
verbose (bool): Indicates if we want the frame to be printed before sending it.
Default: False
"""

try:
frame = Frame(serial, pin_code, function_id, payload, function_check=False)

response = frame.send(burner_address, verbose=verbose)

return response
except PayloadToLargeException as e:
print(e.message)
4 changes: 2 additions & 2 deletions src/pyduro/actions/set.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def run(burner_address, serial, pin_code, path, value, verbose=False):
"""

try:
function = FUNCTIONS.set.value
function_id = FUNCTIONS.set.value

if path is None or len(path) == 0:
print("You must pass one of the following as path: {}".format(SETTINGS))
Expand All @@ -40,7 +40,7 @@ def run(burner_address, serial, pin_code, path, value, verbose=False):

payload = "{}={}".format(path, value)

frame = Frame(serial, pin_code, function, payload)
frame = Frame(serial, pin_code, function_id, payload)

response = frame.send(burner_address, verbose=verbose)

Expand Down
4 changes: 3 additions & 1 deletion src/pyduro/protocol/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ class PAYLOADS(enum.Enum):

class FUNCTIONS(enum.Enum):
discover = 0

set = 2

get_settings = 1
get_settings_range = 3
get_operating_data = 4
Expand All @@ -28,7 +31,6 @@ class FUNCTIONS(enum.Enum):
get_event_log = 8
get_info = 9
get_sw_versions = 10
set = 2


START_CHAR = chr(0x02)
Expand Down
Loading

0 comments on commit 5c2f352

Please sign in to comment.