Ready for publish
This commit is contained in:
parent
99e222a4b5
commit
06e293b86a
@ -1,2 +1,6 @@
|
|||||||
# tasmota-sml-parser
|
# tasmota-sml-parser
|
||||||
Tasmota SML Parser
|
Webapp to conveniently parse Tasmota SML Dump output and display the actual data contained.
|
||||||
|
|
||||||
|
Makes building a Tasmota SML Script much easier.
|
||||||
|
|
||||||
|
Online Demo is at https://tasmota-sml-parser.azurewebsites.net/.
|
||||||
|
|||||||
49
app.py
Executable file
49
app.py
Executable file
@ -0,0 +1,49 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from flask import Flask, render_template, request, redirect, url_for
|
||||||
|
from flask_bootstrap import Bootstrap
|
||||||
|
from flask_nav import Nav
|
||||||
|
from flask_nav.elements import Navbar, View, Subgroup, Link, Text, Separator
|
||||||
|
from sml_decoder import TasmotaSMLParser
|
||||||
|
|
||||||
|
app = Flask(__name__)
|
||||||
|
Bootstrap(app)
|
||||||
|
app.config["BOOTSTRAP_SERVE_LOCAL"] = True
|
||||||
|
app.debug = False
|
||||||
|
nav = Nav()
|
||||||
|
nav.init_app(app)
|
||||||
|
nav.register_element("frontend_top", Navbar(View("Tasmota SML Decoder", ".index")))
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/")
|
||||||
|
def index():
|
||||||
|
return render_template("index.html")
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/decode", methods=["POST", "GET"])
|
||||||
|
def decode():
|
||||||
|
if request.method == "GET":
|
||||||
|
return redirect("/")
|
||||||
|
elif request.method == "POST":
|
||||||
|
data = request.form["smldump"].splitlines()
|
||||||
|
|
||||||
|
tas = TasmotaSMLParser()
|
||||||
|
msgs = tas.decode_messages(data)
|
||||||
|
messages = []
|
||||||
|
for msg in msgs:
|
||||||
|
details = tas.get_message_details(msg)
|
||||||
|
tasmota_script = tas.build_meter_def(msg)
|
||||||
|
messages.append({"msg": details, "tas": tasmota_script})
|
||||||
|
|
||||||
|
messages = sorted(messages, key=lambda x: x["msg"]["obis"])
|
||||||
|
|
||||||
|
return render_template(
|
||||||
|
"decode.html",
|
||||||
|
smldump=data,
|
||||||
|
parse_errors=tas.parse_errors,
|
||||||
|
messages=messages,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
app.run()
|
||||||
7
requirements.txt
Normal file
7
requirements.txt
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
Flask==2.0.3
|
||||||
|
Flask-Bootstrap==3.3.7.1
|
||||||
|
flask-nav==0.6
|
||||||
|
#smllib==1.1
|
||||||
|
# SML Lib with grid freq and current power
|
||||||
|
git+https://github.com/spacemanspiff2007/SmlLib.git@3d4a106#egg=smllib
|
||||||
|
|
||||||
122
sml_decoder.py
Executable file
122
sml_decoder.py
Executable file
@ -0,0 +1,122 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from binascii import a2b_hex
|
||||||
|
from smllib.sml_frame import SmlFrame
|
||||||
|
from smllib.const import OBIS_NAMES, UNITS
|
||||||
|
|
||||||
|
file = "test-data.txt"
|
||||||
|
|
||||||
|
|
||||||
|
class TasmotaSMLParser:
|
||||||
|
def __init__(self):
|
||||||
|
self.obis_decoded = []
|
||||||
|
self.obis_errors = []
|
||||||
|
self.parse_errors = []
|
||||||
|
|
||||||
|
def parse_input(self, input):
|
||||||
|
"""Parse a line into a frame"""
|
||||||
|
if " : 77 " in input:
|
||||||
|
# Remove the spaces and return a bytestring
|
||||||
|
frame = a2b_hex("".join((input.split(" : ", 1)[1]).split()))
|
||||||
|
elif input.startswith("77 0"):
|
||||||
|
frame = a2b_hex("".join(input.split()))
|
||||||
|
else:
|
||||||
|
self.parse_errors.append(input)
|
||||||
|
return
|
||||||
|
|
||||||
|
return frame
|
||||||
|
|
||||||
|
def decode_frame(self, frame):
|
||||||
|
f = SmlFrame(frame)
|
||||||
|
try:
|
||||||
|
msgs = f.get_obis()
|
||||||
|
if len(msgs) == 0:
|
||||||
|
return False
|
||||||
|
except:
|
||||||
|
self.obis_errors.append(frame)
|
||||||
|
return None
|
||||||
|
return msgs
|
||||||
|
|
||||||
|
def decode_messages(self, input):
|
||||||
|
messages = []
|
||||||
|
for line in input:
|
||||||
|
frame = self.parse_input(line)
|
||||||
|
if frame is None:
|
||||||
|
continue
|
||||||
|
msgs = self.decode_frame(frame)
|
||||||
|
if msgs in [None, False]:
|
||||||
|
continue
|
||||||
|
for msg in msgs:
|
||||||
|
if msg.obis in self.obis_decoded:
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
self.obis_decoded.append(msg.obis)
|
||||||
|
messages.append(msg)
|
||||||
|
return messages
|
||||||
|
|
||||||
|
def get_message_details(self, msg):
|
||||||
|
name = OBIS_NAMES.get(msg.obis, "Unbekannter Datentyp")
|
||||||
|
unit = UNITS.get(msg.unit, "Unbekannte Einheit")
|
||||||
|
mqtt_topic = (
|
||||||
|
"_".join(OBIS_NAMES.get(msg.obis, "Unbekanntes MQTT Topic").split())
|
||||||
|
.replace("/", "-")
|
||||||
|
.lower()
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
precision = msg.scaler * -1
|
||||||
|
except TypeError:
|
||||||
|
precision = 0
|
||||||
|
|
||||||
|
try:
|
||||||
|
human_readable = f"{msg.value * pow(10, msg.scaler)}{unit} ({name})"
|
||||||
|
except TypeError:
|
||||||
|
if msg.unit in UNITS and msg.name in OBIS_NAMES:
|
||||||
|
human_readable = f"{msg.value}{unit} ({name})"
|
||||||
|
elif msg.unit in UNITS and msg.name not in OBIS_NAMES:
|
||||||
|
human_readable = f"{msg.value}{unit}"
|
||||||
|
else:
|
||||||
|
human_readable = f"{msg.value}"
|
||||||
|
|
||||||
|
data = {
|
||||||
|
"obis": msg.obis,
|
||||||
|
"obis_code": msg.obis.obis_code,
|
||||||
|
"obis_short": msg.obis.obis_short,
|
||||||
|
"name": name,
|
||||||
|
"unit": unit,
|
||||||
|
"topic": mqtt_topic,
|
||||||
|
"precision": precision,
|
||||||
|
"value": msg.value,
|
||||||
|
"status": msg.status,
|
||||||
|
"val_time": msg.val_time,
|
||||||
|
"unit_raw": msg.unit,
|
||||||
|
"scaler": msg.scaler,
|
||||||
|
"value_signature": msg.value_signature,
|
||||||
|
"human_readable": human_readable,
|
||||||
|
}
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
def build_meter_def(self, msg):
|
||||||
|
data = self.get_message_details(msg)
|
||||||
|
return f"1,7707{data['obis'].upper()}@1,{data['name']},{data['unit']},{data['topic']},{data['precision']}"
|
||||||
|
|
||||||
|
def pretty_print(self, msg):
|
||||||
|
print(msg.format_msg())
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
tas = TasmotaSMLParser()
|
||||||
|
msgs = []
|
||||||
|
with open(file, "r") as fp:
|
||||||
|
msgs = tas.decode_messages(fp.read().splitlines())
|
||||||
|
|
||||||
|
for msg in msgs:
|
||||||
|
tas.pretty_print(msg)
|
||||||
|
details = tas.get_message_details(msg)
|
||||||
|
print("Tasmota SML Script meter definition:")
|
||||||
|
print(tas.build_meter_def(msg))
|
||||||
|
print(80 * "#")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
17
static/app.css
Normal file
17
static/app.css
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
.jumbotron {
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.parser-error {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.parser-success {
|
||||||
|
color: green;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer {
|
||||||
|
border-top: 1px solid black;
|
||||||
|
margin: 5em;
|
||||||
|
margin-top: 2em;
|
||||||
|
}
|
||||||
64
templates/base.html
Normal file
64
templates/base.html
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
{# ``base.html`` is the template all our other templates derive from. While
|
||||||
|
Flask-Bootstrap ships with its own base, it is good form to create a custom
|
||||||
|
one for our app, as it allows customizing some aspects.
|
||||||
|
|
||||||
|
Deriving from bootstap/base.html gives us a basic page scaffoling.
|
||||||
|
|
||||||
|
You can find additional information about template inheritance at
|
||||||
|
|
||||||
|
http://jinja.pocoo.org/docs/templates/#template-inheritance
|
||||||
|
#}
|
||||||
|
{%- extends "bootstrap/base.html" %}
|
||||||
|
|
||||||
|
{# We also set a default title, usually because we might forget to set one.
|
||||||
|
In our sample app, we will most likely just opt not to change it #}
|
||||||
|
{% block title %}Tasmota SML Decoder{% endblock %}
|
||||||
|
|
||||||
|
{# While we are at it, we also enable fixes for legacy browsers. First we
|
||||||
|
import the necessary macros: #}
|
||||||
|
{% import "bootstrap/fixes.html" as fixes %}
|
||||||
|
|
||||||
|
{# Then, inside the head block, we apply these. To not replace the header,
|
||||||
|
``super()`` is used: #}
|
||||||
|
|
||||||
|
{% block head %}
|
||||||
|
{{super()}}
|
||||||
|
|
||||||
|
{#- Docs: http://pythonhosted.org/Flask-Bootstrap/macros.html#fixes
|
||||||
|
The sample application already contains the required static files. #}
|
||||||
|
{{fixes.ie8()}}
|
||||||
|
{%- endblock %}
|
||||||
|
|
||||||
|
{# Adding our own CSS files is also done here. Check the documentation at
|
||||||
|
http://pythonhosted.org/Flask-Bootstrap/basic-usage.html#available-blocks
|
||||||
|
for an overview. #}
|
||||||
|
{% block styles -%}
|
||||||
|
{{super()}} {# do not forget to call super or Bootstrap's own stylesheets
|
||||||
|
will disappear! #}
|
||||||
|
|
||||||
|
<link rel="stylesheet" type="text/css"
|
||||||
|
href="{{url_for('static', filename='app.css')}}">
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{# Finally, round things out with navigation #}
|
||||||
|
{% block navbar %}
|
||||||
|
{{nav.frontend_top.render()}}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{#
|
||||||
|
{%- block content %}
|
||||||
|
{{ super() }}
|
||||||
|
{%- block footer %}
|
||||||
|
<footer>© 2022 <a href="https://github.com/ixs/tasmota-sml-parser/">Andreas Thienemann</a></footer>
|
||||||
|
{%- endblock footer %}
|
||||||
|
{%- endblock content %}
|
||||||
|
#}
|
||||||
|
|
||||||
|
|
||||||
|
{%- block body %}
|
||||||
|
{{ super() }}
|
||||||
|
{%- block footer %}
|
||||||
|
<footer>© 2022 <a href="https://github.com/ixs/tasmota-sml-parser/">Andreas Thienemann</a></footer>
|
||||||
|
{%- endblock footer %}
|
||||||
|
{%- endblock body %}
|
||||||
76
templates/decode.html
Normal file
76
templates/decode.html
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
{# This simple template derives from ``base.html``. See ``base.html`` for
|
||||||
|
more information about template inheritance. #}
|
||||||
|
{%- extends "base.html" %}
|
||||||
|
|
||||||
|
{# Loads some of the macros included with Flask-Bootstrap. We are using the
|
||||||
|
utils module here to automatically render Flask's flashed messages in a
|
||||||
|
bootstrap friendly manner #}
|
||||||
|
{% import "bootstrap/utils.html" as utils %}
|
||||||
|
|
||||||
|
|
||||||
|
{# Inside the ``content`` is where you should place most of your own stuff.
|
||||||
|
This will keep scripts at the page end and a navbar you add on later
|
||||||
|
intact. #}
|
||||||
|
{% block content %}
|
||||||
|
<div class="container">
|
||||||
|
{%- with messages = get_flashed_messages(with_categories=True) %}
|
||||||
|
{%- if messages %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12">
|
||||||
|
{{utils.flashed_messages(messages)}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{%- endif %}
|
||||||
|
{%- endwith %}
|
||||||
|
<div class="jumbotron">
|
||||||
|
<h1>Tasmota SML Dekoder</h1>
|
||||||
|
<p><p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{% if messages | length > 0 %}
|
||||||
|
<h2>Dekodierte SML Nachrichten</h2>
|
||||||
|
<table class="table table-striped">
|
||||||
|
<thead class="thead-light">
|
||||||
|
<tr>
|
||||||
|
<th scope="col">OBIS (hex)</th>
|
||||||
|
<th scope="col">OBIS</th>
|
||||||
|
<th scope="col">Name</th>
|
||||||
|
<th scope="col">Wert</th>
|
||||||
|
<th scope="col">Einheit</th>
|
||||||
|
<th scope="col">Parsed</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{%- for msg in messages %}
|
||||||
|
<tr>
|
||||||
|
<td>0x{{ msg.msg.obis }}</td>
|
||||||
|
<td>{{ msg.msg.obis_short }}</td>
|
||||||
|
<td>{{ msg.msg.name }}</td>
|
||||||
|
<td>{{ msg.msg.value}}</td>
|
||||||
|
<td>{{ msg.msg.unit }}</td>
|
||||||
|
<td>{{ msg.msg.human_readable }}</td>
|
||||||
|
</tr>
|
||||||
|
{%- endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<h2>Tasmota Meter Definition</h2>
|
||||||
|
<p>Aufgrund der erkannten SML Elemente wäre dies ein Vorschlag für eine Tasmota Meter Definition.</p>
|
||||||
|
<pre>M 1
|
||||||
|
+1,3,s,0,9600,
|
||||||
|
{% for msg in messages -%}
|
||||||
|
{{ msg.tas }}
|
||||||
|
{% endfor -%}</pre>
|
||||||
|
{% endif %}
|
||||||
|
<hr>
|
||||||
|
<h2>Empfangene Daten</h2>
|
||||||
|
Folgende Daten wurden empfangen.
|
||||||
|
<pre>{% for line in smldump -%}
|
||||||
|
{% if line in parse_errors -%}
|
||||||
|
<span class="parser-error">{{ line }}</span>
|
||||||
|
{% else -%}
|
||||||
|
<span class="parser-success">{{ line }}</span>
|
||||||
|
{% endif -%}
|
||||||
|
{% endfor -%}</pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{%- endblock %}
|
||||||
79
templates/index.html
Normal file
79
templates/index.html
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
{# This simple template derives from ``base.html``. See ``base.html`` for
|
||||||
|
more information about template inheritance. #}
|
||||||
|
{%- extends "base.html" %}
|
||||||
|
|
||||||
|
{# Loads some of the macros included with Flask-Bootstrap. We are using the
|
||||||
|
utils module here to automatically render Flask's flashed messages in a
|
||||||
|
bootstrap friendly manner #}
|
||||||
|
{% import "bootstrap/utils.html" as utils %}
|
||||||
|
|
||||||
|
|
||||||
|
{# Inside the ``content`` is where you should place most of your own stuff.
|
||||||
|
This will keep scripts at the page end and a navbar you add on later
|
||||||
|
intact. #}
|
||||||
|
{% block content %}
|
||||||
|
<div class="container">
|
||||||
|
{%- with messages = get_flashed_messages(with_categories=True) %}
|
||||||
|
{%- if messages %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12">
|
||||||
|
{{utils.flashed_messages(messages)}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{%- endif %}
|
||||||
|
{%- endwith %}
|
||||||
|
<div class="jumbotron">
|
||||||
|
<h1>Tasmota SML Dekoder</h1>
|
||||||
|
<p><a href="https://tasmota.github.io">Tasmota</a> unterstützt <a href="https://tasmota.github.io/docs/Smart-Meter-Interface/">
|
||||||
|
verschiedene intelligente Stromzähler</a> und kann deren Daten auslesen und z.B. als MQTT Telegramm verschicken.</p>
|
||||||
|
<p>Die Konfiguration des Stromzählers erfolgt hierbei mit der <a href="https://tasmota.github.io/docs/Scripting-Language/">
|
||||||
|
Tasmota Scripting Language</a> um die verschiedenen auf dem Markt gebräuchlichen Stromzähler zu unterstützen.<p>
|
||||||
|
<hr>
|
||||||
|
<p>Diese Webseite hilft, den eigenen Stromzähler richtig zu konfigurieren, indem der "SML dump" von Tasmota dekodiert
|
||||||
|
wird um zu erkennen, was der Stromzähler für Daten sendet. Damit kann dann einfach ein entsprechendes Tasmota Script
|
||||||
|
gebaut werden um die gewünschten Daten zu extrahieren.</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h2>Ablauf</h2>
|
||||||
|
|
||||||
|
<ol>
|
||||||
|
<li>Tasmota Befehl <code>sensor53 d1</code> in der Konsole eingeben, damit die empfangenen SML Daten ausgegeben
|
||||||
|
werden anstelle interpretiert zu werden.<br>
|
||||||
|
Beispielhaft enthält die Tasmota Konsole anschließend Zeilen wie diese:<br>
|
||||||
|
<pre>14:10:15.988 : 77 07 01 00 10 07 00 ff 01 01 62 1b 52 00 53 01 c6 01
|
||||||
|
14:10:16.009 : 77 07 01 00 20 07 00 ff 01 01 62 23 52 ff 63 08 f2 01
|
||||||
|
14:10:16.029 : 77 07 01 00 34 07 00 ff 01 01 62 23 52 ff 63 08 de 01
|
||||||
|
14:10:16.050 : 77 07 01 00 48 07 00 ff 01 01 62 23 52 ff 63 08 ee 01
|
||||||
|
14:10:16.070 : 77 07 01 00 1f 07 00 ff 01 01 62 21 52 fe 62 34 01
|
||||||
|
14:10:16.089 : 77 07 01 00 33 07 00 ff 01 01 62 21 52 fe 62 23 01
|
||||||
|
14:10:16.109 : 77 07 01 00 47 07 00 ff 01 01 62 21 52 fe 62 c7 01
|
||||||
|
14:10:16.128 : 77 07 01 00 51 07 01 ff 01 01 62 08 52 00 62 f1 01
|
||||||
|
14:10:16.145 : 77 07 01 00 51 07 02 ff 01 01 62 08 52 00 62 </pre></li>
|
||||||
|
<li>Diese Ausgabe der gelesenen SML Daten in die Zwischenablage kopieren.</li>
|
||||||
|
<li>Tasmota Befehl <code>sensor53 d0</code> in der Konsole eingeben um den "Dump" Modus zu beenden.</li>
|
||||||
|
<li>Die in der Zwischenablage gespeicherten Daten in das Feld auf dieser Webseite eingeben und das Formular absenden.</li>
|
||||||
|
<li>Dekodierte Daten anschauen und den Meter Definition Vorschlag gegebenenfalls anpassen.</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<form name="smldump" action="/decode" method="POST">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="formGroupSMLDumpInput">SML Dump</label>
|
||||||
|
<textarea class="form-control" id="formGroupSMLDumpInput" name="smldump" rows=10
|
||||||
|
placeholder="14:10:15.988 : 77 07 01 00 10 07 00 ff 01 01 62 1b 52 00 53 01 c6 01
|
||||||
|
14:10:16.009 : 77 07 01 00 20 07 00 ff 01 01 62 23 52 ff 63 08 f2 01
|
||||||
|
14:10:16.029 : 77 07 01 00 34 07 00 ff 01 01 62 23 52 ff 63 08 de 01
|
||||||
|
14:10:16.050 : 77 07 01 00 48 07 00 ff 01 01 62 23 52 ff 63 08 ee 01
|
||||||
|
14:10:16.070 : 77 07 01 00 1f 07 00 ff 01 01 62 21 52 fe 62 34 01
|
||||||
|
14:10:16.089 : 77 07 01 00 33 07 00 ff 01 01 62 21 52 fe 62 23 01
|
||||||
|
14:10:16.109 : 77 07 01 00 47 07 00 ff 01 01 62 21 52 fe 62 c7 01
|
||||||
|
14:10:16.128 : 77 07 01 00 51 07 01 ff 01 01 62 08 52 00 62 f1 01
|
||||||
|
14:10:16.145 : 77 07 01 00 51 07 02 ff 01 01 62 08 52 00 62 "></textarea>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-primary">Dekodieren</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{%- endblock %}
|
||||||
59
test-data.txt
Normal file
59
test-data.txt
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
>D
|
||||||
|
>B
|
||||||
|
->sensor53 r
|
||||||
|
>M 1
|
||||||
|
+1,3,s,0,9600,Haus
|
||||||
|
1,770701000F0700FF@1,Aktuell,W,Power_curr,0
|
||||||
|
1,77070100010800FF@1000,Zählerstand Verb.,kWh,Tariflos,2
|
||||||
|
1,77070100020800FF@1000,Zählerstand Einsp.,kWh,Tariflos,2
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
15:57:05.415 : 77 07 01 00 60 05 00 ff 01 01 01 01 65 00 1c 81 04 01 01 01 63 33 14 00 76 04 00 00 03 62 00 62 00 72 65 00 00 02 01 71
|
||||||
|
15:57:05.435 : 77 01 0b 0a 01 48 4c 59 02 00 01 1c 0f 01 01 f1 04
|
||||||
|
15:57:05.455 : 77 07 01 00 60 32 01 01 01 01 01 01 04 48 4c 59 01
|
||||||
|
15:57:05.483 : 77 07 01 00 60 01 00 ff 01 01 01 01 0b 0a 01 48 4c 59 02 00 01 1c 0f 01
|
||||||
|
15:57:05.516 : 77 07 01 00 01 08 00 ff 65 00 1c 81 04 65 05 a2 99 1e 62 1e 52 ff 65 0b e8 4d cf 01
|
||||||
|
15:57:05.544 : 77 07 01 00 02 08 00 ff 65 00 1c 81 04 65 05 a2 99 1e 62 1e 52 ff 62 00 01
|
||||||
|
15:57:05.565 : 77 07 01 00 10 07 00 ff 01 01 62 1b 52 00 53 01 a0 01
|
||||||
|
15:57:05.586 : 77 07 01 00 20 07 00 ff 01 01 62 23 52 ff 63 09 04 01
|
||||||
|
15:57:05.606 : 77 07 01 00 34 07 00 ff 01 01 62 23 52 ff 63 08 e5 01
|
||||||
|
15:57:05.627 : 77 07 01 00 48 07 00 ff 01 01 62 23 52 ff 63 09 10 01
|
||||||
|
15:57:05.647 : 77 07 01 00 1f 07 00 ff 01 01 62 21 52 fe 62 31 01
|
||||||
|
15:57:05.666 : 77 07 01 00 33 07 00 ff 01 01 62 21 52 fe 62 24 01
|
||||||
|
15:57:05.685 : 77 07 01 00 47 07 00 ff 01 01 62 21 52 fe 62 c6 01
|
||||||
|
15:57:05.706 : 77 07 01 00 51 07 01 ff 01 01 62 08 52 00 62 f0 01
|
||||||
|
15:57:05.725 : 77 07 01 00 51 07 02 ff 01 01 62 08 52 00 62 76 01
|
||||||
|
15:57:05.745 : 77 07 01 00 51 07 04 ff 01 01 62 08 52 00 63 01 2f 01
|
||||||
|
15:57:05.767 : 77 07 01 00 51 07 0f ff 01 01 62 08 52 00 63 01 31 01
|
||||||
|
15:57:05.787 : 77 07 01 00 51 07 1a ff 01 01 62 08 52 00 63 01 37 01
|
||||||
|
15:57:05.808 : 77 07 01 00 0e 07 00 ff 01 01 62 2c 52 ff 63 01 f4 01
|
||||||
|
15:57:05.834 : 77 07 01 00 00 02 00 00 01 01 01 01 09 31 2e 30 32 2e 30 30 37 01
|
||||||
|
15:57:05.854 : 77 07 01 00 60 5a 02 01 01 01 01 01 05 41 30 31 41 01
|
||||||
|
15:57:07.029 : 77 07 01 00 60 05 00 ff 01 01 01 01 65 00 1c 81 04 01 01 01 63 68 a4 00 76 04 00 00 03 62 00 62 00 72 65 00 00 02 01 71
|
||||||
|
15:57:07.049 : 77 01 0b 0a 01 48 4c 59 02 00 01 1c 0f 01 01 f1 04
|
||||||
|
15:57:07.068 : 77 07 01 00 60 32 01 01 01 01 01 01 04 48 4c 59 01
|
||||||
|
15:57:07.111 : 77 07 01 00 60 01 00 ff 01 01 01 01 0b 0a 01 48 4c 59 02 00 01 1c 0f 01
|
||||||
|
15:57:07.127 : 77 07 01 00 01 08 00 ff 65 00 1c 81 04 65 05 a2 99 20 62 1e 52 ff 65 0b e8 4d d1 01
|
||||||
|
15:57:07.157 : 77 07 01 00 02 08 00 ff 65 00 1c 81 04 65 05 a2 99 20 62 1e 52 ff 62 00 01
|
||||||
|
15:57:07.177 : 77 07 01 00 10 07 00 ff 01 01 62 1b 52 00 53 01 9f 01
|
||||||
|
15:57:07.198 : 77 07 01 00 20 07 00 ff 01 01 62 23 52 ff 63 09 04 01
|
||||||
|
15:57:07.219 : 77 07 01 00 34 07 00 ff 01 01 62 23 52 ff 63 08 e4 01
|
||||||
|
15:57:07.239 : 77 07 01 00 48 07 00 ff 01 01 62 23 52 ff 63 09 0e 01
|
||||||
|
15:57:07.259 : 77 07 01 00 1f 07 00 ff 01 01 62 21 52 fe 62 31 01
|
||||||
|
15:57:07.279 : 77 07 01 00 33 07 00 ff 01 01 62 21 52 fe 62 24 01
|
||||||
|
15:57:07.299 : 77 07 01 00 47 07 00 ff 01 01 62 21 52 fe 62 c6 01
|
||||||
|
15:57:07.318 : 77 07 01 00 51 07 01 ff 01 01 62 08 52 00 62 f1 01
|
||||||
|
15:57:07.336 : 77 07 01 00 51 07 02 ff 01 01 62 08 52 00 62
|
||||||
|
15:57:07.338 : 77 01
|
||||||
|
15:57:07.358 : 77 07 01 00 51 07 04 ff 01 01 62 08 52 00 63 01 2f 01
|
||||||
|
15:57:07.380 : 77 07 01 00 51 07 0f ff 01 01 62 08 52 00 63 01 31 01
|
||||||
|
15:57:07.400 : 77 07 01 00 51 07 1a ff 01 01 62 08 52 00 63 01 37 01
|
||||||
|
15:57:07.421 : 77 07 01 00 0e 07 00 ff 01 01 62 2c 52 ff 63 01 f4 01
|
||||||
|
15:57:07.446 : 77 07 01 00 00 02 00 00 01 01 01 01 09 31 2e 30 32 2e 30 30 37 01
|
||||||
|
15:57:07.466 : 77 07 01 00 60 5a 02 01 01 01 01 01 05 41 30 31 41 01
|
||||||
|
|
||||||
|
|
||||||
|
foobar
|
||||||
Loading…
Reference in New Issue
Block a user