mirror of
https://github.com/meshtastic/python.git
synced 2026-09-14 22:39:18 -04:00
Merge pull request #182 from mkinney/update_doc
fix some comments for doc
This commit is contained in:
29 files changed
+5838
-15929
No files matched your search
+14
-731
@@ -223,756 +223,67 @@ DESCRIPTOR._options = None
|
||||
<dl>
|
||||
<dt id="meshtastic.admin_pb2.AdminMessage"><code class="flex name class">
|
||||
<span>class <span class="ident">AdminMessage</span></span>
|
||||
<span>(</span><span>**kwargs)</span>
|
||||
<span>(</span><span>*args, **kwargs)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Abstract base class for protocol messages.</p>
|
||||
<p>Protocol message classes are almost always generated by the protocol
|
||||
compiler.
|
||||
These generated types subclass Message and implement the methods
|
||||
shown below.</p></div>
|
||||
<div class="desc"><p>A ProtocolMessage</p></div>
|
||||
<h3>Ancestors</h3>
|
||||
<ul class="hlist">
|
||||
<li>google.protobuf.pyext._message.CMessage</li>
|
||||
<li>google.protobuf.message.Message</li>
|
||||
</ul>
|
||||
<h3>Class variables</h3>
|
||||
<dl>
|
||||
<dt id="meshtastic.admin_pb2.AdminMessage.CONFIRM_SET_CHANNEL_FIELD_NUMBER"><code class="name">var <span class="ident">CONFIRM_SET_CHANNEL_FIELD_NUMBER</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.admin_pb2.AdminMessage.CONFIRM_SET_RADIO_FIELD_NUMBER"><code class="name">var <span class="ident">CONFIRM_SET_RADIO_FIELD_NUMBER</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.admin_pb2.AdminMessage.DESCRIPTOR"><code class="name">var <span class="ident">DESCRIPTOR</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.admin_pb2.AdminMessage.EXIT_SIMULATOR_FIELD_NUMBER"><code class="name">var <span class="ident">EXIT_SIMULATOR_FIELD_NUMBER</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.admin_pb2.AdminMessage.GET_CHANNEL_REQUEST_FIELD_NUMBER"><code class="name">var <span class="ident">GET_CHANNEL_REQUEST_FIELD_NUMBER</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.admin_pb2.AdminMessage.GET_CHANNEL_RESPONSE_FIELD_NUMBER"><code class="name">var <span class="ident">GET_CHANNEL_RESPONSE_FIELD_NUMBER</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.admin_pb2.AdminMessage.GET_RADIO_REQUEST_FIELD_NUMBER"><code class="name">var <span class="ident">GET_RADIO_REQUEST_FIELD_NUMBER</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.admin_pb2.AdminMessage.GET_RADIO_RESPONSE_FIELD_NUMBER"><code class="name">var <span class="ident">GET_RADIO_RESPONSE_FIELD_NUMBER</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.admin_pb2.AdminMessage.REBOOT_SECONDS_FIELD_NUMBER"><code class="name">var <span class="ident">REBOOT_SECONDS_FIELD_NUMBER</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.admin_pb2.AdminMessage.SET_CHANNEL_FIELD_NUMBER"><code class="name">var <span class="ident">SET_CHANNEL_FIELD_NUMBER</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.admin_pb2.AdminMessage.SET_OWNER_FIELD_NUMBER"><code class="name">var <span class="ident">SET_OWNER_FIELD_NUMBER</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.admin_pb2.AdminMessage.SET_RADIO_FIELD_NUMBER"><code class="name">var <span class="ident">SET_RADIO_FIELD_NUMBER</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>Static methods</h3>
|
||||
<dl>
|
||||
<dt id="meshtastic.admin_pb2.AdminMessage.FromString"><code class="name flex">
|
||||
<span>def <span class="ident">FromString</span></span>(<span>s)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def FromString(s):
|
||||
message = cls()
|
||||
message.MergeFromString(s)
|
||||
return message</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.admin_pb2.AdminMessage.RegisterExtension"><code class="name flex">
|
||||
<span>def <span class="ident">RegisterExtension</span></span>(<span>extension_handle)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def RegisterExtension(extension_handle):
|
||||
extension_handle.containing_type = cls.DESCRIPTOR
|
||||
# TODO(amauryfa): Use cls.MESSAGE_FACTORY.pool when available.
|
||||
# pylint: disable=protected-access
|
||||
cls.DESCRIPTOR.file.pool._AddExtensionDescriptor(extension_handle)
|
||||
_AttachFieldHelpers(cls, extension_handle)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>Instance variables</h3>
|
||||
<dl>
|
||||
<dt id="meshtastic.admin_pb2.AdminMessage.confirm_set_channel"><code class="name">var <span class="ident">confirm_set_channel</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Getter for confirm_set_channel.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def getter(self):
|
||||
# TODO(protobuf-team): This may be broken since there may not be
|
||||
# default_value. Combine with has_default_value somehow.
|
||||
return self._fields.get(field, default_value)</code></pre>
|
||||
</details>
|
||||
<div class="desc"><p>Field AdminMessage.confirm_set_channel</p></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.admin_pb2.AdminMessage.confirm_set_radio"><code class="name">var <span class="ident">confirm_set_radio</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Getter for confirm_set_radio.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def getter(self):
|
||||
# TODO(protobuf-team): This may be broken since there may not be
|
||||
# default_value. Combine with has_default_value somehow.
|
||||
return self._fields.get(field, default_value)</code></pre>
|
||||
</details>
|
||||
<div class="desc"><p>Field AdminMessage.confirm_set_radio</p></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.admin_pb2.AdminMessage.exit_simulator"><code class="name">var <span class="ident">exit_simulator</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Getter for exit_simulator.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def getter(self):
|
||||
# TODO(protobuf-team): This may be broken since there may not be
|
||||
# default_value. Combine with has_default_value somehow.
|
||||
return self._fields.get(field, default_value)</code></pre>
|
||||
</details>
|
||||
<div class="desc"><p>Field AdminMessage.exit_simulator</p></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.admin_pb2.AdminMessage.get_channel_request"><code class="name">var <span class="ident">get_channel_request</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Getter for get_channel_request.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def getter(self):
|
||||
# TODO(protobuf-team): This may be broken since there may not be
|
||||
# default_value. Combine with has_default_value somehow.
|
||||
return self._fields.get(field, default_value)</code></pre>
|
||||
</details>
|
||||
<div class="desc"><p>Field AdminMessage.get_channel_request</p></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.admin_pb2.AdminMessage.get_channel_response"><code class="name">var <span class="ident">get_channel_response</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Getter for get_channel_response.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def getter(self):
|
||||
field_value = self._fields.get(field)
|
||||
if field_value is None:
|
||||
# Construct a new object to represent this field.
|
||||
field_value = field._default_constructor(self)
|
||||
|
||||
# Atomically check if another thread has preempted us and, if not, swap
|
||||
# in the new object we just created. If someone has preempted us, we
|
||||
# take that object and discard ours.
|
||||
# WARNING: We are relying on setdefault() being atomic. This is true
|
||||
# in CPython but we haven't investigated others. This warning appears
|
||||
# in several other locations in this file.
|
||||
field_value = self._fields.setdefault(field, field_value)
|
||||
return field_value</code></pre>
|
||||
</details>
|
||||
<div class="desc"><p>Field AdminMessage.get_channel_response</p></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.admin_pb2.AdminMessage.get_radio_request"><code class="name">var <span class="ident">get_radio_request</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Getter for get_radio_request.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def getter(self):
|
||||
# TODO(protobuf-team): This may be broken since there may not be
|
||||
# default_value. Combine with has_default_value somehow.
|
||||
return self._fields.get(field, default_value)</code></pre>
|
||||
</details>
|
||||
<div class="desc"><p>Field AdminMessage.get_radio_request</p></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.admin_pb2.AdminMessage.get_radio_response"><code class="name">var <span class="ident">get_radio_response</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Getter for get_radio_response.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def getter(self):
|
||||
field_value = self._fields.get(field)
|
||||
if field_value is None:
|
||||
# Construct a new object to represent this field.
|
||||
field_value = field._default_constructor(self)
|
||||
|
||||
# Atomically check if another thread has preempted us and, if not, swap
|
||||
# in the new object we just created. If someone has preempted us, we
|
||||
# take that object and discard ours.
|
||||
# WARNING: We are relying on setdefault() being atomic. This is true
|
||||
# in CPython but we haven't investigated others. This warning appears
|
||||
# in several other locations in this file.
|
||||
field_value = self._fields.setdefault(field, field_value)
|
||||
return field_value</code></pre>
|
||||
</details>
|
||||
<div class="desc"><p>Field AdminMessage.get_radio_response</p></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.admin_pb2.AdminMessage.reboot_seconds"><code class="name">var <span class="ident">reboot_seconds</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Getter for reboot_seconds.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def getter(self):
|
||||
# TODO(protobuf-team): This may be broken since there may not be
|
||||
# default_value. Combine with has_default_value somehow.
|
||||
return self._fields.get(field, default_value)</code></pre>
|
||||
</details>
|
||||
<div class="desc"><p>Field AdminMessage.reboot_seconds</p></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.admin_pb2.AdminMessage.set_channel"><code class="name">var <span class="ident">set_channel</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Getter for set_channel.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def getter(self):
|
||||
field_value = self._fields.get(field)
|
||||
if field_value is None:
|
||||
# Construct a new object to represent this field.
|
||||
field_value = field._default_constructor(self)
|
||||
|
||||
# Atomically check if another thread has preempted us and, if not, swap
|
||||
# in the new object we just created. If someone has preempted us, we
|
||||
# take that object and discard ours.
|
||||
# WARNING: We are relying on setdefault() being atomic. This is true
|
||||
# in CPython but we haven't investigated others. This warning appears
|
||||
# in several other locations in this file.
|
||||
field_value = self._fields.setdefault(field, field_value)
|
||||
return field_value</code></pre>
|
||||
</details>
|
||||
<div class="desc"><p>Field AdminMessage.set_channel</p></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.admin_pb2.AdminMessage.set_owner"><code class="name">var <span class="ident">set_owner</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Getter for set_owner.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def getter(self):
|
||||
field_value = self._fields.get(field)
|
||||
if field_value is None:
|
||||
# Construct a new object to represent this field.
|
||||
field_value = field._default_constructor(self)
|
||||
|
||||
# Atomically check if another thread has preempted us and, if not, swap
|
||||
# in the new object we just created. If someone has preempted us, we
|
||||
# take that object and discard ours.
|
||||
# WARNING: We are relying on setdefault() being atomic. This is true
|
||||
# in CPython but we haven't investigated others. This warning appears
|
||||
# in several other locations in this file.
|
||||
field_value = self._fields.setdefault(field, field_value)
|
||||
return field_value</code></pre>
|
||||
</details>
|
||||
<div class="desc"><p>Field AdminMessage.set_owner</p></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.admin_pb2.AdminMessage.set_radio"><code class="name">var <span class="ident">set_radio</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Getter for set_radio.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def getter(self):
|
||||
field_value = self._fields.get(field)
|
||||
if field_value is None:
|
||||
# Construct a new object to represent this field.
|
||||
field_value = field._default_constructor(self)
|
||||
|
||||
# Atomically check if another thread has preempted us and, if not, swap
|
||||
# in the new object we just created. If someone has preempted us, we
|
||||
# take that object and discard ours.
|
||||
# WARNING: We are relying on setdefault() being atomic. This is true
|
||||
# in CPython but we haven't investigated others. This warning appears
|
||||
# in several other locations in this file.
|
||||
field_value = self._fields.setdefault(field, field_value)
|
||||
return field_value</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>Methods</h3>
|
||||
<dl>
|
||||
<dt id="meshtastic.admin_pb2.AdminMessage.ByteSize"><code class="name flex">
|
||||
<span>def <span class="ident">ByteSize</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def ByteSize(self):
|
||||
if not self._cached_byte_size_dirty:
|
||||
return self._cached_byte_size
|
||||
|
||||
size = 0
|
||||
descriptor = self.DESCRIPTOR
|
||||
if descriptor.GetOptions().map_entry:
|
||||
# Fields of map entry should always be serialized.
|
||||
size = descriptor.fields_by_name['key']._sizer(self.key)
|
||||
size += descriptor.fields_by_name['value']._sizer(self.value)
|
||||
else:
|
||||
for field_descriptor, field_value in self.ListFields():
|
||||
size += field_descriptor._sizer(field_value)
|
||||
for tag_bytes, value_bytes in self._unknown_fields:
|
||||
size += len(tag_bytes) + len(value_bytes)
|
||||
|
||||
self._cached_byte_size = size
|
||||
self._cached_byte_size_dirty = False
|
||||
self._listener_for_children.dirty = False
|
||||
return size</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.admin_pb2.AdminMessage.Clear"><code class="name flex">
|
||||
<span>def <span class="ident">Clear</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def _Clear(self):
|
||||
# Clear fields.
|
||||
self._fields = {}
|
||||
self._unknown_fields = ()
|
||||
# pylint: disable=protected-access
|
||||
if self._unknown_field_set is not None:
|
||||
self._unknown_field_set._clear()
|
||||
self._unknown_field_set = None
|
||||
|
||||
self._oneofs = {}
|
||||
self._Modified()</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.admin_pb2.AdminMessage.ClearField"><code class="name flex">
|
||||
<span>def <span class="ident">ClearField</span></span>(<span>self, field_name)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def ClearField(self, field_name):
|
||||
try:
|
||||
field = message_descriptor.fields_by_name[field_name]
|
||||
except KeyError:
|
||||
try:
|
||||
field = message_descriptor.oneofs_by_name[field_name]
|
||||
if field in self._oneofs:
|
||||
field = self._oneofs[field]
|
||||
else:
|
||||
return
|
||||
except KeyError:
|
||||
raise ValueError('Protocol message %s has no "%s" field.' %
|
||||
(message_descriptor.name, field_name))
|
||||
|
||||
if field in self._fields:
|
||||
# To match the C++ implementation, we need to invalidate iterators
|
||||
# for map fields when ClearField() happens.
|
||||
if hasattr(self._fields[field], 'InvalidateIterators'):
|
||||
self._fields[field].InvalidateIterators()
|
||||
|
||||
# Note: If the field is a sub-message, its listener will still point
|
||||
# at us. That's fine, because the worst than can happen is that it
|
||||
# will call _Modified() and invalidate our byte size. Big deal.
|
||||
del self._fields[field]
|
||||
|
||||
if self._oneofs.get(field.containing_oneof, None) is field:
|
||||
del self._oneofs[field.containing_oneof]
|
||||
|
||||
# Always call _Modified() -- even if nothing was changed, this is
|
||||
# a mutating method, and thus calling it should cause the field to become
|
||||
# present in the parent message.
|
||||
self._Modified()</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.admin_pb2.AdminMessage.DiscardUnknownFields"><code class="name flex">
|
||||
<span>def <span class="ident">DiscardUnknownFields</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def _DiscardUnknownFields(self):
|
||||
self._unknown_fields = []
|
||||
self._unknown_field_set = None # pylint: disable=protected-access
|
||||
for field, value in self.ListFields():
|
||||
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
|
||||
if _IsMapField(field):
|
||||
if _IsMessageMapField(field):
|
||||
for key in value:
|
||||
value[key].DiscardUnknownFields()
|
||||
elif field.label == _FieldDescriptor.LABEL_REPEATED:
|
||||
for sub_message in value:
|
||||
sub_message.DiscardUnknownFields()
|
||||
else:
|
||||
value.DiscardUnknownFields()</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.admin_pb2.AdminMessage.FindInitializationErrors"><code class="name flex">
|
||||
<span>def <span class="ident">FindInitializationErrors</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Finds required fields which are not initialized.</p>
|
||||
<h2 id="returns">Returns</h2>
|
||||
<p>A list of strings.
|
||||
Each string is a path to an uninitialized field from
|
||||
the top-level message, e.g. "foo.bar[5].baz".</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def FindInitializationErrors(self):
|
||||
"""Finds required fields which are not initialized.
|
||||
|
||||
Returns:
|
||||
A list of strings. Each string is a path to an uninitialized field from
|
||||
the top-level message, e.g. "foo.bar[5].baz".
|
||||
"""
|
||||
|
||||
errors = [] # simplify things
|
||||
|
||||
for field in required_fields:
|
||||
if not self.HasField(field.name):
|
||||
errors.append(field.name)
|
||||
|
||||
for field, value in self.ListFields():
|
||||
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
|
||||
if field.is_extension:
|
||||
name = '(%s)' % field.full_name
|
||||
else:
|
||||
name = field.name
|
||||
|
||||
if _IsMapField(field):
|
||||
if _IsMessageMapField(field):
|
||||
for key in value:
|
||||
element = value[key]
|
||||
prefix = '%s[%s].' % (name, key)
|
||||
sub_errors = element.FindInitializationErrors()
|
||||
errors += [prefix + error for error in sub_errors]
|
||||
else:
|
||||
# ScalarMaps can't have any initialization errors.
|
||||
pass
|
||||
elif field.label == _FieldDescriptor.LABEL_REPEATED:
|
||||
for i in range(len(value)):
|
||||
element = value[i]
|
||||
prefix = '%s[%d].' % (name, i)
|
||||
sub_errors = element.FindInitializationErrors()
|
||||
errors += [prefix + error for error in sub_errors]
|
||||
else:
|
||||
prefix = name + '.'
|
||||
sub_errors = value.FindInitializationErrors()
|
||||
errors += [prefix + error for error in sub_errors]
|
||||
|
||||
return errors</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.admin_pb2.AdminMessage.HasField"><code class="name flex">
|
||||
<span>def <span class="ident">HasField</span></span>(<span>self, field_name)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def HasField(self, field_name):
|
||||
try:
|
||||
field = hassable_fields[field_name]
|
||||
except KeyError:
|
||||
raise ValueError(error_msg % (message_descriptor.full_name, field_name))
|
||||
|
||||
if isinstance(field, descriptor_mod.OneofDescriptor):
|
||||
try:
|
||||
return HasField(self, self._oneofs[field].name)
|
||||
except KeyError:
|
||||
return False
|
||||
else:
|
||||
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
|
||||
value = self._fields.get(field)
|
||||
return value is not None and value._is_present_in_parent
|
||||
else:
|
||||
return field in self._fields</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.admin_pb2.AdminMessage.IsInitialized"><code class="name flex">
|
||||
<span>def <span class="ident">IsInitialized</span></span>(<span>self, errors=None)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Checks if all required fields of a message are set.</p>
|
||||
<h2 id="args">Args</h2>
|
||||
<dl>
|
||||
<dt><strong><code>errors</code></strong></dt>
|
||||
<dd>A list which, if provided, will be populated with the field
|
||||
paths of all missing required fields.</dd>
|
||||
</dl>
|
||||
<h2 id="returns">Returns</h2>
|
||||
<p>True iff the specified message has all required fields set.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def IsInitialized(self, errors=None):
|
||||
"""Checks if all required fields of a message are set.
|
||||
|
||||
Args:
|
||||
errors: A list which, if provided, will be populated with the field
|
||||
paths of all missing required fields.
|
||||
|
||||
Returns:
|
||||
True iff the specified message has all required fields set.
|
||||
"""
|
||||
|
||||
# Performance is critical so we avoid HasField() and ListFields().
|
||||
|
||||
for field in required_fields:
|
||||
if (field not in self._fields or
|
||||
(field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE and
|
||||
not self._fields[field]._is_present_in_parent)):
|
||||
if errors is not None:
|
||||
errors.extend(self.FindInitializationErrors())
|
||||
return False
|
||||
|
||||
for field, value in list(self._fields.items()): # dict can change size!
|
||||
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
|
||||
if field.label == _FieldDescriptor.LABEL_REPEATED:
|
||||
if (field.message_type.has_options and
|
||||
field.message_type.GetOptions().map_entry):
|
||||
continue
|
||||
for element in value:
|
||||
if not element.IsInitialized():
|
||||
if errors is not None:
|
||||
errors.extend(self.FindInitializationErrors())
|
||||
return False
|
||||
elif value._is_present_in_parent and not value.IsInitialized():
|
||||
if errors is not None:
|
||||
errors.extend(self.FindInitializationErrors())
|
||||
return False
|
||||
|
||||
return True</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.admin_pb2.AdminMessage.ListFields"><code class="name flex">
|
||||
<span>def <span class="ident">ListFields</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def ListFields(self):
|
||||
all_fields = [item for item in self._fields.items() if _IsPresent(item)]
|
||||
all_fields.sort(key = lambda item: item[0].number)
|
||||
return all_fields</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.admin_pb2.AdminMessage.MergeFrom"><code class="name flex">
|
||||
<span>def <span class="ident">MergeFrom</span></span>(<span>self, msg)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def MergeFrom(self, msg):
|
||||
if not isinstance(msg, cls):
|
||||
raise TypeError(
|
||||
'Parameter to MergeFrom() must be instance of same class: '
|
||||
'expected %s got %s.' % (_FullyQualifiedClassName(cls),
|
||||
_FullyQualifiedClassName(msg.__class__)))
|
||||
|
||||
assert msg is not self
|
||||
self._Modified()
|
||||
|
||||
fields = self._fields
|
||||
|
||||
for field, value in msg._fields.items():
|
||||
if field.label == LABEL_REPEATED:
|
||||
field_value = fields.get(field)
|
||||
if field_value is None:
|
||||
# Construct a new object to represent this field.
|
||||
field_value = field._default_constructor(self)
|
||||
fields[field] = field_value
|
||||
field_value.MergeFrom(value)
|
||||
elif field.cpp_type == CPPTYPE_MESSAGE:
|
||||
if value._is_present_in_parent:
|
||||
field_value = fields.get(field)
|
||||
if field_value is None:
|
||||
# Construct a new object to represent this field.
|
||||
field_value = field._default_constructor(self)
|
||||
fields[field] = field_value
|
||||
field_value.MergeFrom(value)
|
||||
else:
|
||||
self._fields[field] = value
|
||||
if field.containing_oneof:
|
||||
self._UpdateOneofState(field)
|
||||
|
||||
if msg._unknown_fields:
|
||||
if not self._unknown_fields:
|
||||
self._unknown_fields = []
|
||||
self._unknown_fields.extend(msg._unknown_fields)
|
||||
# pylint: disable=protected-access
|
||||
if self._unknown_field_set is None:
|
||||
self._unknown_field_set = containers.UnknownFieldSet()
|
||||
self._unknown_field_set._extend(msg._unknown_field_set)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.admin_pb2.AdminMessage.MergeFromString"><code class="name flex">
|
||||
<span>def <span class="ident">MergeFromString</span></span>(<span>self, serialized)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def MergeFromString(self, serialized):
|
||||
serialized = memoryview(serialized)
|
||||
length = len(serialized)
|
||||
try:
|
||||
if self._InternalParse(serialized, 0, length) != length:
|
||||
# The only reason _InternalParse would return early is if it
|
||||
# encountered an end-group tag.
|
||||
raise message_mod.DecodeError('Unexpected end-group tag.')
|
||||
except (IndexError, TypeError):
|
||||
# Now ord(buf[p:p+1]) == ord('') gets TypeError.
|
||||
raise message_mod.DecodeError('Truncated message.')
|
||||
except struct.error as e:
|
||||
raise message_mod.DecodeError(e)
|
||||
return length # Return this for legacy reasons.</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.admin_pb2.AdminMessage.SerializePartialToString"><code class="name flex">
|
||||
<span>def <span class="ident">SerializePartialToString</span></span>(<span>self, **kwargs)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def SerializePartialToString(self, **kwargs):
|
||||
out = BytesIO()
|
||||
self._InternalSerialize(out.write, **kwargs)
|
||||
return out.getvalue()</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.admin_pb2.AdminMessage.SerializeToString"><code class="name flex">
|
||||
<span>def <span class="ident">SerializeToString</span></span>(<span>self, **kwargs)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def SerializeToString(self, **kwargs):
|
||||
# Check if the message has all of its required fields set.
|
||||
if not self.IsInitialized():
|
||||
raise message_mod.EncodeError(
|
||||
'Message %s is missing required fields: %s' % (
|
||||
self.DESCRIPTOR.full_name, ','.join(self.FindInitializationErrors())))
|
||||
return self.SerializePartialToString(**kwargs)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.admin_pb2.AdminMessage.SetInParent"><code class="name flex">
|
||||
<span>def <span class="ident">SetInParent</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Sets the _cached_byte_size_dirty bit to true,
|
||||
and propagates this to our listener iff this was a state change.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def Modified(self):
|
||||
"""Sets the _cached_byte_size_dirty bit to true,
|
||||
and propagates this to our listener iff this was a state change.
|
||||
"""
|
||||
|
||||
# Note: Some callers check _cached_byte_size_dirty before calling
|
||||
# _Modified() as an extra optimization. So, if this method is ever
|
||||
# changed such that it does stuff even when _cached_byte_size_dirty is
|
||||
# already true, the callers need to be updated.
|
||||
if not self._cached_byte_size_dirty:
|
||||
self._cached_byte_size_dirty = True
|
||||
self._listener_for_children.dirty = True
|
||||
self._is_present_in_parent = True
|
||||
self._listener.Modified()</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.admin_pb2.AdminMessage.UnknownFields"><code class="name flex">
|
||||
<span>def <span class="ident">UnknownFields</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def _UnknownFields(self):
|
||||
if self._unknown_field_set is None: # pylint: disable=protected-access
|
||||
# pylint: disable=protected-access
|
||||
self._unknown_field_set = containers.UnknownFieldSet()
|
||||
return self._unknown_field_set # pylint: disable=protected-access</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.admin_pb2.AdminMessage.WhichOneof"><code class="name flex">
|
||||
<span>def <span class="ident">WhichOneof</span></span>(<span>self, oneof_name)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Returns the name of the currently set field inside a oneof, or None.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def WhichOneof(self, oneof_name):
|
||||
"""Returns the name of the currently set field inside a oneof, or None."""
|
||||
try:
|
||||
field = message_descriptor.oneofs_by_name[oneof_name]
|
||||
except KeyError:
|
||||
raise ValueError(
|
||||
'Protocol message has no oneof "%s" field.' % oneof_name)
|
||||
|
||||
nested_field = self._oneofs.get(field, None)
|
||||
if nested_field is not None and self.HasField(nested_field.name):
|
||||
return nested_field.name
|
||||
else:
|
||||
return None</code></pre>
|
||||
</details>
|
||||
<div class="desc"><p>Field AdminMessage.set_radio</p></div>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
@@ -995,35 +306,7 @@ and propagates this to our listener iff this was a state change.</p></div>
|
||||
<li>
|
||||
<h4><code><a title="meshtastic.admin_pb2.AdminMessage" href="#meshtastic.admin_pb2.AdminMessage">AdminMessage</a></code></h4>
|
||||
<ul class="">
|
||||
<li><code><a title="meshtastic.admin_pb2.AdminMessage.ByteSize" href="#meshtastic.admin_pb2.AdminMessage.ByteSize">ByteSize</a></code></li>
|
||||
<li><code><a title="meshtastic.admin_pb2.AdminMessage.CONFIRM_SET_CHANNEL_FIELD_NUMBER" href="#meshtastic.admin_pb2.AdminMessage.CONFIRM_SET_CHANNEL_FIELD_NUMBER">CONFIRM_SET_CHANNEL_FIELD_NUMBER</a></code></li>
|
||||
<li><code><a title="meshtastic.admin_pb2.AdminMessage.CONFIRM_SET_RADIO_FIELD_NUMBER" href="#meshtastic.admin_pb2.AdminMessage.CONFIRM_SET_RADIO_FIELD_NUMBER">CONFIRM_SET_RADIO_FIELD_NUMBER</a></code></li>
|
||||
<li><code><a title="meshtastic.admin_pb2.AdminMessage.Clear" href="#meshtastic.admin_pb2.AdminMessage.Clear">Clear</a></code></li>
|
||||
<li><code><a title="meshtastic.admin_pb2.AdminMessage.ClearField" href="#meshtastic.admin_pb2.AdminMessage.ClearField">ClearField</a></code></li>
|
||||
<li><code><a title="meshtastic.admin_pb2.AdminMessage.DESCRIPTOR" href="#meshtastic.admin_pb2.AdminMessage.DESCRIPTOR">DESCRIPTOR</a></code></li>
|
||||
<li><code><a title="meshtastic.admin_pb2.AdminMessage.DiscardUnknownFields" href="#meshtastic.admin_pb2.AdminMessage.DiscardUnknownFields">DiscardUnknownFields</a></code></li>
|
||||
<li><code><a title="meshtastic.admin_pb2.AdminMessage.EXIT_SIMULATOR_FIELD_NUMBER" href="#meshtastic.admin_pb2.AdminMessage.EXIT_SIMULATOR_FIELD_NUMBER">EXIT_SIMULATOR_FIELD_NUMBER</a></code></li>
|
||||
<li><code><a title="meshtastic.admin_pb2.AdminMessage.FindInitializationErrors" href="#meshtastic.admin_pb2.AdminMessage.FindInitializationErrors">FindInitializationErrors</a></code></li>
|
||||
<li><code><a title="meshtastic.admin_pb2.AdminMessage.FromString" href="#meshtastic.admin_pb2.AdminMessage.FromString">FromString</a></code></li>
|
||||
<li><code><a title="meshtastic.admin_pb2.AdminMessage.GET_CHANNEL_REQUEST_FIELD_NUMBER" href="#meshtastic.admin_pb2.AdminMessage.GET_CHANNEL_REQUEST_FIELD_NUMBER">GET_CHANNEL_REQUEST_FIELD_NUMBER</a></code></li>
|
||||
<li><code><a title="meshtastic.admin_pb2.AdminMessage.GET_CHANNEL_RESPONSE_FIELD_NUMBER" href="#meshtastic.admin_pb2.AdminMessage.GET_CHANNEL_RESPONSE_FIELD_NUMBER">GET_CHANNEL_RESPONSE_FIELD_NUMBER</a></code></li>
|
||||
<li><code><a title="meshtastic.admin_pb2.AdminMessage.GET_RADIO_REQUEST_FIELD_NUMBER" href="#meshtastic.admin_pb2.AdminMessage.GET_RADIO_REQUEST_FIELD_NUMBER">GET_RADIO_REQUEST_FIELD_NUMBER</a></code></li>
|
||||
<li><code><a title="meshtastic.admin_pb2.AdminMessage.GET_RADIO_RESPONSE_FIELD_NUMBER" href="#meshtastic.admin_pb2.AdminMessage.GET_RADIO_RESPONSE_FIELD_NUMBER">GET_RADIO_RESPONSE_FIELD_NUMBER</a></code></li>
|
||||
<li><code><a title="meshtastic.admin_pb2.AdminMessage.HasField" href="#meshtastic.admin_pb2.AdminMessage.HasField">HasField</a></code></li>
|
||||
<li><code><a title="meshtastic.admin_pb2.AdminMessage.IsInitialized" href="#meshtastic.admin_pb2.AdminMessage.IsInitialized">IsInitialized</a></code></li>
|
||||
<li><code><a title="meshtastic.admin_pb2.AdminMessage.ListFields" href="#meshtastic.admin_pb2.AdminMessage.ListFields">ListFields</a></code></li>
|
||||
<li><code><a title="meshtastic.admin_pb2.AdminMessage.MergeFrom" href="#meshtastic.admin_pb2.AdminMessage.MergeFrom">MergeFrom</a></code></li>
|
||||
<li><code><a title="meshtastic.admin_pb2.AdminMessage.MergeFromString" href="#meshtastic.admin_pb2.AdminMessage.MergeFromString">MergeFromString</a></code></li>
|
||||
<li><code><a title="meshtastic.admin_pb2.AdminMessage.REBOOT_SECONDS_FIELD_NUMBER" href="#meshtastic.admin_pb2.AdminMessage.REBOOT_SECONDS_FIELD_NUMBER">REBOOT_SECONDS_FIELD_NUMBER</a></code></li>
|
||||
<li><code><a title="meshtastic.admin_pb2.AdminMessage.RegisterExtension" href="#meshtastic.admin_pb2.AdminMessage.RegisterExtension">RegisterExtension</a></code></li>
|
||||
<li><code><a title="meshtastic.admin_pb2.AdminMessage.SET_CHANNEL_FIELD_NUMBER" href="#meshtastic.admin_pb2.AdminMessage.SET_CHANNEL_FIELD_NUMBER">SET_CHANNEL_FIELD_NUMBER</a></code></li>
|
||||
<li><code><a title="meshtastic.admin_pb2.AdminMessage.SET_OWNER_FIELD_NUMBER" href="#meshtastic.admin_pb2.AdminMessage.SET_OWNER_FIELD_NUMBER">SET_OWNER_FIELD_NUMBER</a></code></li>
|
||||
<li><code><a title="meshtastic.admin_pb2.AdminMessage.SET_RADIO_FIELD_NUMBER" href="#meshtastic.admin_pb2.AdminMessage.SET_RADIO_FIELD_NUMBER">SET_RADIO_FIELD_NUMBER</a></code></li>
|
||||
<li><code><a title="meshtastic.admin_pb2.AdminMessage.SerializePartialToString" href="#meshtastic.admin_pb2.AdminMessage.SerializePartialToString">SerializePartialToString</a></code></li>
|
||||
<li><code><a title="meshtastic.admin_pb2.AdminMessage.SerializeToString" href="#meshtastic.admin_pb2.AdminMessage.SerializeToString">SerializeToString</a></code></li>
|
||||
<li><code><a title="meshtastic.admin_pb2.AdminMessage.SetInParent" href="#meshtastic.admin_pb2.AdminMessage.SetInParent">SetInParent</a></code></li>
|
||||
<li><code><a title="meshtastic.admin_pb2.AdminMessage.UnknownFields" href="#meshtastic.admin_pb2.AdminMessage.UnknownFields">UnknownFields</a></code></li>
|
||||
<li><code><a title="meshtastic.admin_pb2.AdminMessage.WhichOneof" href="#meshtastic.admin_pb2.AdminMessage.WhichOneof">WhichOneof</a></code></li>
|
||||
<li><code><a title="meshtastic.admin_pb2.AdminMessage.confirm_set_channel" href="#meshtastic.admin_pb2.AdminMessage.confirm_set_channel">confirm_set_channel</a></code></li>
|
||||
<li><code><a title="meshtastic.admin_pb2.AdminMessage.confirm_set_radio" href="#meshtastic.admin_pb2.AdminMessage.confirm_set_radio">confirm_set_radio</a></code></li>
|
||||
<li><code><a title="meshtastic.admin_pb2.AdminMessage.exit_simulator" href="#meshtastic.admin_pb2.AdminMessage.exit_simulator">exit_simulator</a></code></li>
|
||||
|
||||
@@ -111,16 +111,13 @@ DESCRIPTOR._options = None
|
||||
<dl>
|
||||
<dt id="meshtastic.apponly_pb2.ChannelSet"><code class="flex name class">
|
||||
<span>class <span class="ident">ChannelSet</span></span>
|
||||
<span>(</span><span>**kwargs)</span>
|
||||
<span>(</span><span>*args, **kwargs)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Abstract base class for protocol messages.</p>
|
||||
<p>Protocol message classes are almost always generated by the protocol
|
||||
compiler.
|
||||
These generated types subclass Message and implement the methods
|
||||
shown below.</p></div>
|
||||
<div class="desc"><p>A ProtocolMessage</p></div>
|
||||
<h3>Ancestors</h3>
|
||||
<ul class="hlist">
|
||||
<li>google.protobuf.pyext._message.CMessage</li>
|
||||
<li>google.protobuf.message.Message</li>
|
||||
</ul>
|
||||
<h3>Class variables</h3>
|
||||
@@ -129,528 +126,12 @@ shown below.</p></div>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.apponly_pb2.ChannelSet.SETTINGS_FIELD_NUMBER"><code class="name">var <span class="ident">SETTINGS_FIELD_NUMBER</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>Static methods</h3>
|
||||
<dl>
|
||||
<dt id="meshtastic.apponly_pb2.ChannelSet.FromString"><code class="name flex">
|
||||
<span>def <span class="ident">FromString</span></span>(<span>s)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def FromString(s):
|
||||
message = cls()
|
||||
message.MergeFromString(s)
|
||||
return message</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.apponly_pb2.ChannelSet.RegisterExtension"><code class="name flex">
|
||||
<span>def <span class="ident">RegisterExtension</span></span>(<span>extension_handle)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def RegisterExtension(extension_handle):
|
||||
extension_handle.containing_type = cls.DESCRIPTOR
|
||||
# TODO(amauryfa): Use cls.MESSAGE_FACTORY.pool when available.
|
||||
# pylint: disable=protected-access
|
||||
cls.DESCRIPTOR.file.pool._AddExtensionDescriptor(extension_handle)
|
||||
_AttachFieldHelpers(cls, extension_handle)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>Instance variables</h3>
|
||||
<dl>
|
||||
<dt id="meshtastic.apponly_pb2.ChannelSet.settings"><code class="name">var <span class="ident">settings</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Getter for settings.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def getter(self):
|
||||
field_value = self._fields.get(field)
|
||||
if field_value is None:
|
||||
# Construct a new object to represent this field.
|
||||
field_value = field._default_constructor(self)
|
||||
|
||||
# Atomically check if another thread has preempted us and, if not, swap
|
||||
# in the new object we just created. If someone has preempted us, we
|
||||
# take that object and discard ours.
|
||||
# WARNING: We are relying on setdefault() being atomic. This is true
|
||||
# in CPython but we haven't investigated others. This warning appears
|
||||
# in several other locations in this file.
|
||||
field_value = self._fields.setdefault(field, field_value)
|
||||
return field_value</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>Methods</h3>
|
||||
<dl>
|
||||
<dt id="meshtastic.apponly_pb2.ChannelSet.ByteSize"><code class="name flex">
|
||||
<span>def <span class="ident">ByteSize</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def ByteSize(self):
|
||||
if not self._cached_byte_size_dirty:
|
||||
return self._cached_byte_size
|
||||
|
||||
size = 0
|
||||
descriptor = self.DESCRIPTOR
|
||||
if descriptor.GetOptions().map_entry:
|
||||
# Fields of map entry should always be serialized.
|
||||
size = descriptor.fields_by_name['key']._sizer(self.key)
|
||||
size += descriptor.fields_by_name['value']._sizer(self.value)
|
||||
else:
|
||||
for field_descriptor, field_value in self.ListFields():
|
||||
size += field_descriptor._sizer(field_value)
|
||||
for tag_bytes, value_bytes in self._unknown_fields:
|
||||
size += len(tag_bytes) + len(value_bytes)
|
||||
|
||||
self._cached_byte_size = size
|
||||
self._cached_byte_size_dirty = False
|
||||
self._listener_for_children.dirty = False
|
||||
return size</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.apponly_pb2.ChannelSet.Clear"><code class="name flex">
|
||||
<span>def <span class="ident">Clear</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def _Clear(self):
|
||||
# Clear fields.
|
||||
self._fields = {}
|
||||
self._unknown_fields = ()
|
||||
# pylint: disable=protected-access
|
||||
if self._unknown_field_set is not None:
|
||||
self._unknown_field_set._clear()
|
||||
self._unknown_field_set = None
|
||||
|
||||
self._oneofs = {}
|
||||
self._Modified()</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.apponly_pb2.ChannelSet.ClearField"><code class="name flex">
|
||||
<span>def <span class="ident">ClearField</span></span>(<span>self, field_name)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def ClearField(self, field_name):
|
||||
try:
|
||||
field = message_descriptor.fields_by_name[field_name]
|
||||
except KeyError:
|
||||
try:
|
||||
field = message_descriptor.oneofs_by_name[field_name]
|
||||
if field in self._oneofs:
|
||||
field = self._oneofs[field]
|
||||
else:
|
||||
return
|
||||
except KeyError:
|
||||
raise ValueError('Protocol message %s has no "%s" field.' %
|
||||
(message_descriptor.name, field_name))
|
||||
|
||||
if field in self._fields:
|
||||
# To match the C++ implementation, we need to invalidate iterators
|
||||
# for map fields when ClearField() happens.
|
||||
if hasattr(self._fields[field], 'InvalidateIterators'):
|
||||
self._fields[field].InvalidateIterators()
|
||||
|
||||
# Note: If the field is a sub-message, its listener will still point
|
||||
# at us. That's fine, because the worst than can happen is that it
|
||||
# will call _Modified() and invalidate our byte size. Big deal.
|
||||
del self._fields[field]
|
||||
|
||||
if self._oneofs.get(field.containing_oneof, None) is field:
|
||||
del self._oneofs[field.containing_oneof]
|
||||
|
||||
# Always call _Modified() -- even if nothing was changed, this is
|
||||
# a mutating method, and thus calling it should cause the field to become
|
||||
# present in the parent message.
|
||||
self._Modified()</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.apponly_pb2.ChannelSet.DiscardUnknownFields"><code class="name flex">
|
||||
<span>def <span class="ident">DiscardUnknownFields</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def _DiscardUnknownFields(self):
|
||||
self._unknown_fields = []
|
||||
self._unknown_field_set = None # pylint: disable=protected-access
|
||||
for field, value in self.ListFields():
|
||||
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
|
||||
if _IsMapField(field):
|
||||
if _IsMessageMapField(field):
|
||||
for key in value:
|
||||
value[key].DiscardUnknownFields()
|
||||
elif field.label == _FieldDescriptor.LABEL_REPEATED:
|
||||
for sub_message in value:
|
||||
sub_message.DiscardUnknownFields()
|
||||
else:
|
||||
value.DiscardUnknownFields()</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.apponly_pb2.ChannelSet.FindInitializationErrors"><code class="name flex">
|
||||
<span>def <span class="ident">FindInitializationErrors</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Finds required fields which are not initialized.</p>
|
||||
<h2 id="returns">Returns</h2>
|
||||
<p>A list of strings.
|
||||
Each string is a path to an uninitialized field from
|
||||
the top-level message, e.g. "foo.bar[5].baz".</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def FindInitializationErrors(self):
|
||||
"""Finds required fields which are not initialized.
|
||||
|
||||
Returns:
|
||||
A list of strings. Each string is a path to an uninitialized field from
|
||||
the top-level message, e.g. "foo.bar[5].baz".
|
||||
"""
|
||||
|
||||
errors = [] # simplify things
|
||||
|
||||
for field in required_fields:
|
||||
if not self.HasField(field.name):
|
||||
errors.append(field.name)
|
||||
|
||||
for field, value in self.ListFields():
|
||||
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
|
||||
if field.is_extension:
|
||||
name = '(%s)' % field.full_name
|
||||
else:
|
||||
name = field.name
|
||||
|
||||
if _IsMapField(field):
|
||||
if _IsMessageMapField(field):
|
||||
for key in value:
|
||||
element = value[key]
|
||||
prefix = '%s[%s].' % (name, key)
|
||||
sub_errors = element.FindInitializationErrors()
|
||||
errors += [prefix + error for error in sub_errors]
|
||||
else:
|
||||
# ScalarMaps can't have any initialization errors.
|
||||
pass
|
||||
elif field.label == _FieldDescriptor.LABEL_REPEATED:
|
||||
for i in range(len(value)):
|
||||
element = value[i]
|
||||
prefix = '%s[%d].' % (name, i)
|
||||
sub_errors = element.FindInitializationErrors()
|
||||
errors += [prefix + error for error in sub_errors]
|
||||
else:
|
||||
prefix = name + '.'
|
||||
sub_errors = value.FindInitializationErrors()
|
||||
errors += [prefix + error for error in sub_errors]
|
||||
|
||||
return errors</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.apponly_pb2.ChannelSet.HasField"><code class="name flex">
|
||||
<span>def <span class="ident">HasField</span></span>(<span>self, field_name)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def HasField(self, field_name):
|
||||
try:
|
||||
field = hassable_fields[field_name]
|
||||
except KeyError:
|
||||
raise ValueError(error_msg % (message_descriptor.full_name, field_name))
|
||||
|
||||
if isinstance(field, descriptor_mod.OneofDescriptor):
|
||||
try:
|
||||
return HasField(self, self._oneofs[field].name)
|
||||
except KeyError:
|
||||
return False
|
||||
else:
|
||||
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
|
||||
value = self._fields.get(field)
|
||||
return value is not None and value._is_present_in_parent
|
||||
else:
|
||||
return field in self._fields</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.apponly_pb2.ChannelSet.IsInitialized"><code class="name flex">
|
||||
<span>def <span class="ident">IsInitialized</span></span>(<span>self, errors=None)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Checks if all required fields of a message are set.</p>
|
||||
<h2 id="args">Args</h2>
|
||||
<dl>
|
||||
<dt><strong><code>errors</code></strong></dt>
|
||||
<dd>A list which, if provided, will be populated with the field
|
||||
paths of all missing required fields.</dd>
|
||||
</dl>
|
||||
<h2 id="returns">Returns</h2>
|
||||
<p>True iff the specified message has all required fields set.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def IsInitialized(self, errors=None):
|
||||
"""Checks if all required fields of a message are set.
|
||||
|
||||
Args:
|
||||
errors: A list which, if provided, will be populated with the field
|
||||
paths of all missing required fields.
|
||||
|
||||
Returns:
|
||||
True iff the specified message has all required fields set.
|
||||
"""
|
||||
|
||||
# Performance is critical so we avoid HasField() and ListFields().
|
||||
|
||||
for field in required_fields:
|
||||
if (field not in self._fields or
|
||||
(field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE and
|
||||
not self._fields[field]._is_present_in_parent)):
|
||||
if errors is not None:
|
||||
errors.extend(self.FindInitializationErrors())
|
||||
return False
|
||||
|
||||
for field, value in list(self._fields.items()): # dict can change size!
|
||||
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
|
||||
if field.label == _FieldDescriptor.LABEL_REPEATED:
|
||||
if (field.message_type.has_options and
|
||||
field.message_type.GetOptions().map_entry):
|
||||
continue
|
||||
for element in value:
|
||||
if not element.IsInitialized():
|
||||
if errors is not None:
|
||||
errors.extend(self.FindInitializationErrors())
|
||||
return False
|
||||
elif value._is_present_in_parent and not value.IsInitialized():
|
||||
if errors is not None:
|
||||
errors.extend(self.FindInitializationErrors())
|
||||
return False
|
||||
|
||||
return True</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.apponly_pb2.ChannelSet.ListFields"><code class="name flex">
|
||||
<span>def <span class="ident">ListFields</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def ListFields(self):
|
||||
all_fields = [item for item in self._fields.items() if _IsPresent(item)]
|
||||
all_fields.sort(key = lambda item: item[0].number)
|
||||
return all_fields</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.apponly_pb2.ChannelSet.MergeFrom"><code class="name flex">
|
||||
<span>def <span class="ident">MergeFrom</span></span>(<span>self, msg)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def MergeFrom(self, msg):
|
||||
if not isinstance(msg, cls):
|
||||
raise TypeError(
|
||||
'Parameter to MergeFrom() must be instance of same class: '
|
||||
'expected %s got %s.' % (_FullyQualifiedClassName(cls),
|
||||
_FullyQualifiedClassName(msg.__class__)))
|
||||
|
||||
assert msg is not self
|
||||
self._Modified()
|
||||
|
||||
fields = self._fields
|
||||
|
||||
for field, value in msg._fields.items():
|
||||
if field.label == LABEL_REPEATED:
|
||||
field_value = fields.get(field)
|
||||
if field_value is None:
|
||||
# Construct a new object to represent this field.
|
||||
field_value = field._default_constructor(self)
|
||||
fields[field] = field_value
|
||||
field_value.MergeFrom(value)
|
||||
elif field.cpp_type == CPPTYPE_MESSAGE:
|
||||
if value._is_present_in_parent:
|
||||
field_value = fields.get(field)
|
||||
if field_value is None:
|
||||
# Construct a new object to represent this field.
|
||||
field_value = field._default_constructor(self)
|
||||
fields[field] = field_value
|
||||
field_value.MergeFrom(value)
|
||||
else:
|
||||
self._fields[field] = value
|
||||
if field.containing_oneof:
|
||||
self._UpdateOneofState(field)
|
||||
|
||||
if msg._unknown_fields:
|
||||
if not self._unknown_fields:
|
||||
self._unknown_fields = []
|
||||
self._unknown_fields.extend(msg._unknown_fields)
|
||||
# pylint: disable=protected-access
|
||||
if self._unknown_field_set is None:
|
||||
self._unknown_field_set = containers.UnknownFieldSet()
|
||||
self._unknown_field_set._extend(msg._unknown_field_set)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.apponly_pb2.ChannelSet.MergeFromString"><code class="name flex">
|
||||
<span>def <span class="ident">MergeFromString</span></span>(<span>self, serialized)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def MergeFromString(self, serialized):
|
||||
serialized = memoryview(serialized)
|
||||
length = len(serialized)
|
||||
try:
|
||||
if self._InternalParse(serialized, 0, length) != length:
|
||||
# The only reason _InternalParse would return early is if it
|
||||
# encountered an end-group tag.
|
||||
raise message_mod.DecodeError('Unexpected end-group tag.')
|
||||
except (IndexError, TypeError):
|
||||
# Now ord(buf[p:p+1]) == ord('') gets TypeError.
|
||||
raise message_mod.DecodeError('Truncated message.')
|
||||
except struct.error as e:
|
||||
raise message_mod.DecodeError(e)
|
||||
return length # Return this for legacy reasons.</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.apponly_pb2.ChannelSet.SerializePartialToString"><code class="name flex">
|
||||
<span>def <span class="ident">SerializePartialToString</span></span>(<span>self, **kwargs)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def SerializePartialToString(self, **kwargs):
|
||||
out = BytesIO()
|
||||
self._InternalSerialize(out.write, **kwargs)
|
||||
return out.getvalue()</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.apponly_pb2.ChannelSet.SerializeToString"><code class="name flex">
|
||||
<span>def <span class="ident">SerializeToString</span></span>(<span>self, **kwargs)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def SerializeToString(self, **kwargs):
|
||||
# Check if the message has all of its required fields set.
|
||||
if not self.IsInitialized():
|
||||
raise message_mod.EncodeError(
|
||||
'Message %s is missing required fields: %s' % (
|
||||
self.DESCRIPTOR.full_name, ','.join(self.FindInitializationErrors())))
|
||||
return self.SerializePartialToString(**kwargs)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.apponly_pb2.ChannelSet.SetInParent"><code class="name flex">
|
||||
<span>def <span class="ident">SetInParent</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Sets the _cached_byte_size_dirty bit to true,
|
||||
and propagates this to our listener iff this was a state change.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def Modified(self):
|
||||
"""Sets the _cached_byte_size_dirty bit to true,
|
||||
and propagates this to our listener iff this was a state change.
|
||||
"""
|
||||
|
||||
# Note: Some callers check _cached_byte_size_dirty before calling
|
||||
# _Modified() as an extra optimization. So, if this method is ever
|
||||
# changed such that it does stuff even when _cached_byte_size_dirty is
|
||||
# already true, the callers need to be updated.
|
||||
if not self._cached_byte_size_dirty:
|
||||
self._cached_byte_size_dirty = True
|
||||
self._listener_for_children.dirty = True
|
||||
self._is_present_in_parent = True
|
||||
self._listener.Modified()</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.apponly_pb2.ChannelSet.UnknownFields"><code class="name flex">
|
||||
<span>def <span class="ident">UnknownFields</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def _UnknownFields(self):
|
||||
if self._unknown_field_set is None: # pylint: disable=protected-access
|
||||
# pylint: disable=protected-access
|
||||
self._unknown_field_set = containers.UnknownFieldSet()
|
||||
return self._unknown_field_set # pylint: disable=protected-access</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.apponly_pb2.ChannelSet.WhichOneof"><code class="name flex">
|
||||
<span>def <span class="ident">WhichOneof</span></span>(<span>self, oneof_name)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Returns the name of the currently set field inside a oneof, or None.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def WhichOneof(self, oneof_name):
|
||||
"""Returns the name of the currently set field inside a oneof, or None."""
|
||||
try:
|
||||
field = message_descriptor.oneofs_by_name[oneof_name]
|
||||
except KeyError:
|
||||
raise ValueError(
|
||||
'Protocol message has no oneof "%s" field.' % oneof_name)
|
||||
|
||||
nested_field = self._oneofs.get(field, None)
|
||||
if nested_field is not None and self.HasField(nested_field.name):
|
||||
return nested_field.name
|
||||
else:
|
||||
return None</code></pre>
|
||||
</details>
|
||||
<div class="desc"><p>Field ChannelSet.settings</p></div>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
@@ -673,25 +154,7 @@ and propagates this to our listener iff this was a state change.</p></div>
|
||||
<li>
|
||||
<h4><code><a title="meshtastic.apponly_pb2.ChannelSet" href="#meshtastic.apponly_pb2.ChannelSet">ChannelSet</a></code></h4>
|
||||
<ul class="">
|
||||
<li><code><a title="meshtastic.apponly_pb2.ChannelSet.ByteSize" href="#meshtastic.apponly_pb2.ChannelSet.ByteSize">ByteSize</a></code></li>
|
||||
<li><code><a title="meshtastic.apponly_pb2.ChannelSet.Clear" href="#meshtastic.apponly_pb2.ChannelSet.Clear">Clear</a></code></li>
|
||||
<li><code><a title="meshtastic.apponly_pb2.ChannelSet.ClearField" href="#meshtastic.apponly_pb2.ChannelSet.ClearField">ClearField</a></code></li>
|
||||
<li><code><a title="meshtastic.apponly_pb2.ChannelSet.DESCRIPTOR" href="#meshtastic.apponly_pb2.ChannelSet.DESCRIPTOR">DESCRIPTOR</a></code></li>
|
||||
<li><code><a title="meshtastic.apponly_pb2.ChannelSet.DiscardUnknownFields" href="#meshtastic.apponly_pb2.ChannelSet.DiscardUnknownFields">DiscardUnknownFields</a></code></li>
|
||||
<li><code><a title="meshtastic.apponly_pb2.ChannelSet.FindInitializationErrors" href="#meshtastic.apponly_pb2.ChannelSet.FindInitializationErrors">FindInitializationErrors</a></code></li>
|
||||
<li><code><a title="meshtastic.apponly_pb2.ChannelSet.FromString" href="#meshtastic.apponly_pb2.ChannelSet.FromString">FromString</a></code></li>
|
||||
<li><code><a title="meshtastic.apponly_pb2.ChannelSet.HasField" href="#meshtastic.apponly_pb2.ChannelSet.HasField">HasField</a></code></li>
|
||||
<li><code><a title="meshtastic.apponly_pb2.ChannelSet.IsInitialized" href="#meshtastic.apponly_pb2.ChannelSet.IsInitialized">IsInitialized</a></code></li>
|
||||
<li><code><a title="meshtastic.apponly_pb2.ChannelSet.ListFields" href="#meshtastic.apponly_pb2.ChannelSet.ListFields">ListFields</a></code></li>
|
||||
<li><code><a title="meshtastic.apponly_pb2.ChannelSet.MergeFrom" href="#meshtastic.apponly_pb2.ChannelSet.MergeFrom">MergeFrom</a></code></li>
|
||||
<li><code><a title="meshtastic.apponly_pb2.ChannelSet.MergeFromString" href="#meshtastic.apponly_pb2.ChannelSet.MergeFromString">MergeFromString</a></code></li>
|
||||
<li><code><a title="meshtastic.apponly_pb2.ChannelSet.RegisterExtension" href="#meshtastic.apponly_pb2.ChannelSet.RegisterExtension">RegisterExtension</a></code></li>
|
||||
<li><code><a title="meshtastic.apponly_pb2.ChannelSet.SETTINGS_FIELD_NUMBER" href="#meshtastic.apponly_pb2.ChannelSet.SETTINGS_FIELD_NUMBER">SETTINGS_FIELD_NUMBER</a></code></li>
|
||||
<li><code><a title="meshtastic.apponly_pb2.ChannelSet.SerializePartialToString" href="#meshtastic.apponly_pb2.ChannelSet.SerializePartialToString">SerializePartialToString</a></code></li>
|
||||
<li><code><a title="meshtastic.apponly_pb2.ChannelSet.SerializeToString" href="#meshtastic.apponly_pb2.ChannelSet.SerializeToString">SerializeToString</a></code></li>
|
||||
<li><code><a title="meshtastic.apponly_pb2.ChannelSet.SetInParent" href="#meshtastic.apponly_pb2.ChannelSet.SetInParent">SetInParent</a></code></li>
|
||||
<li><code><a title="meshtastic.apponly_pb2.ChannelSet.UnknownFields" href="#meshtastic.apponly_pb2.ChannelSet.UnknownFields">UnknownFields</a></code></li>
|
||||
<li><code><a title="meshtastic.apponly_pb2.ChannelSet.WhichOneof" href="#meshtastic.apponly_pb2.ChannelSet.WhichOneof">WhichOneof</a></code></li>
|
||||
<li><code><a title="meshtastic.apponly_pb2.ChannelSet.settings" href="#meshtastic.apponly_pb2.ChannelSet.settings">settings</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
+22
-1254
File diff suppressed because it is too large.
Load diff
+22
-1799
File diff suppressed because it is too large.
Load diff
@@ -122,570 +122,35 @@ DESCRIPTOR._options = None
|
||||
<dl>
|
||||
<dt id="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement"><code class="flex name class">
|
||||
<span>class <span class="ident">EnvironmentalMeasurement</span></span>
|
||||
<span>(</span><span>**kwargs)</span>
|
||||
<span>(</span><span>*args, **kwargs)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Abstract base class for protocol messages.</p>
|
||||
<p>Protocol message classes are almost always generated by the protocol
|
||||
compiler.
|
||||
These generated types subclass Message and implement the methods
|
||||
shown below.</p></div>
|
||||
<div class="desc"><p>A ProtocolMessage</p></div>
|
||||
<h3>Ancestors</h3>
|
||||
<ul class="hlist">
|
||||
<li>google.protobuf.pyext._message.CMessage</li>
|
||||
<li>google.protobuf.message.Message</li>
|
||||
</ul>
|
||||
<h3>Class variables</h3>
|
||||
<dl>
|
||||
<dt id="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.BAROMETRIC_PRESSURE_FIELD_NUMBER"><code class="name">var <span class="ident">BAROMETRIC_PRESSURE_FIELD_NUMBER</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.DESCRIPTOR"><code class="name">var <span class="ident">DESCRIPTOR</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.RELATIVE_HUMIDITY_FIELD_NUMBER"><code class="name">var <span class="ident">RELATIVE_HUMIDITY_FIELD_NUMBER</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.TEMPERATURE_FIELD_NUMBER"><code class="name">var <span class="ident">TEMPERATURE_FIELD_NUMBER</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>Static methods</h3>
|
||||
<dl>
|
||||
<dt id="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.FromString"><code class="name flex">
|
||||
<span>def <span class="ident">FromString</span></span>(<span>s)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def FromString(s):
|
||||
message = cls()
|
||||
message.MergeFromString(s)
|
||||
return message</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.RegisterExtension"><code class="name flex">
|
||||
<span>def <span class="ident">RegisterExtension</span></span>(<span>extension_handle)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def RegisterExtension(extension_handle):
|
||||
extension_handle.containing_type = cls.DESCRIPTOR
|
||||
# TODO(amauryfa): Use cls.MESSAGE_FACTORY.pool when available.
|
||||
# pylint: disable=protected-access
|
||||
cls.DESCRIPTOR.file.pool._AddExtensionDescriptor(extension_handle)
|
||||
_AttachFieldHelpers(cls, extension_handle)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>Instance variables</h3>
|
||||
<dl>
|
||||
<dt id="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.barometric_pressure"><code class="name">var <span class="ident">barometric_pressure</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Getter for barometric_pressure.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def getter(self):
|
||||
# TODO(protobuf-team): This may be broken since there may not be
|
||||
# default_value. Combine with has_default_value somehow.
|
||||
return self._fields.get(field, default_value)</code></pre>
|
||||
</details>
|
||||
<div class="desc"><p>Field EnvironmentalMeasurement.barometric_pressure</p></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.relative_humidity"><code class="name">var <span class="ident">relative_humidity</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Getter for relative_humidity.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def getter(self):
|
||||
# TODO(protobuf-team): This may be broken since there may not be
|
||||
# default_value. Combine with has_default_value somehow.
|
||||
return self._fields.get(field, default_value)</code></pre>
|
||||
</details>
|
||||
<div class="desc"><p>Field EnvironmentalMeasurement.relative_humidity</p></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.temperature"><code class="name">var <span class="ident">temperature</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Getter for temperature.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def getter(self):
|
||||
# TODO(protobuf-team): This may be broken since there may not be
|
||||
# default_value. Combine with has_default_value somehow.
|
||||
return self._fields.get(field, default_value)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>Methods</h3>
|
||||
<dl>
|
||||
<dt id="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.ByteSize"><code class="name flex">
|
||||
<span>def <span class="ident">ByteSize</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def ByteSize(self):
|
||||
if not self._cached_byte_size_dirty:
|
||||
return self._cached_byte_size
|
||||
|
||||
size = 0
|
||||
descriptor = self.DESCRIPTOR
|
||||
if descriptor.GetOptions().map_entry:
|
||||
# Fields of map entry should always be serialized.
|
||||
size = descriptor.fields_by_name['key']._sizer(self.key)
|
||||
size += descriptor.fields_by_name['value']._sizer(self.value)
|
||||
else:
|
||||
for field_descriptor, field_value in self.ListFields():
|
||||
size += field_descriptor._sizer(field_value)
|
||||
for tag_bytes, value_bytes in self._unknown_fields:
|
||||
size += len(tag_bytes) + len(value_bytes)
|
||||
|
||||
self._cached_byte_size = size
|
||||
self._cached_byte_size_dirty = False
|
||||
self._listener_for_children.dirty = False
|
||||
return size</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.Clear"><code class="name flex">
|
||||
<span>def <span class="ident">Clear</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def _Clear(self):
|
||||
# Clear fields.
|
||||
self._fields = {}
|
||||
self._unknown_fields = ()
|
||||
# pylint: disable=protected-access
|
||||
if self._unknown_field_set is not None:
|
||||
self._unknown_field_set._clear()
|
||||
self._unknown_field_set = None
|
||||
|
||||
self._oneofs = {}
|
||||
self._Modified()</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.ClearField"><code class="name flex">
|
||||
<span>def <span class="ident">ClearField</span></span>(<span>self, field_name)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def ClearField(self, field_name):
|
||||
try:
|
||||
field = message_descriptor.fields_by_name[field_name]
|
||||
except KeyError:
|
||||
try:
|
||||
field = message_descriptor.oneofs_by_name[field_name]
|
||||
if field in self._oneofs:
|
||||
field = self._oneofs[field]
|
||||
else:
|
||||
return
|
||||
except KeyError:
|
||||
raise ValueError('Protocol message %s has no "%s" field.' %
|
||||
(message_descriptor.name, field_name))
|
||||
|
||||
if field in self._fields:
|
||||
# To match the C++ implementation, we need to invalidate iterators
|
||||
# for map fields when ClearField() happens.
|
||||
if hasattr(self._fields[field], 'InvalidateIterators'):
|
||||
self._fields[field].InvalidateIterators()
|
||||
|
||||
# Note: If the field is a sub-message, its listener will still point
|
||||
# at us. That's fine, because the worst than can happen is that it
|
||||
# will call _Modified() and invalidate our byte size. Big deal.
|
||||
del self._fields[field]
|
||||
|
||||
if self._oneofs.get(field.containing_oneof, None) is field:
|
||||
del self._oneofs[field.containing_oneof]
|
||||
|
||||
# Always call _Modified() -- even if nothing was changed, this is
|
||||
# a mutating method, and thus calling it should cause the field to become
|
||||
# present in the parent message.
|
||||
self._Modified()</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.DiscardUnknownFields"><code class="name flex">
|
||||
<span>def <span class="ident">DiscardUnknownFields</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def _DiscardUnknownFields(self):
|
||||
self._unknown_fields = []
|
||||
self._unknown_field_set = None # pylint: disable=protected-access
|
||||
for field, value in self.ListFields():
|
||||
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
|
||||
if _IsMapField(field):
|
||||
if _IsMessageMapField(field):
|
||||
for key in value:
|
||||
value[key].DiscardUnknownFields()
|
||||
elif field.label == _FieldDescriptor.LABEL_REPEATED:
|
||||
for sub_message in value:
|
||||
sub_message.DiscardUnknownFields()
|
||||
else:
|
||||
value.DiscardUnknownFields()</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.FindInitializationErrors"><code class="name flex">
|
||||
<span>def <span class="ident">FindInitializationErrors</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Finds required fields which are not initialized.</p>
|
||||
<h2 id="returns">Returns</h2>
|
||||
<p>A list of strings.
|
||||
Each string is a path to an uninitialized field from
|
||||
the top-level message, e.g. "foo.bar[5].baz".</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def FindInitializationErrors(self):
|
||||
"""Finds required fields which are not initialized.
|
||||
|
||||
Returns:
|
||||
A list of strings. Each string is a path to an uninitialized field from
|
||||
the top-level message, e.g. "foo.bar[5].baz".
|
||||
"""
|
||||
|
||||
errors = [] # simplify things
|
||||
|
||||
for field in required_fields:
|
||||
if not self.HasField(field.name):
|
||||
errors.append(field.name)
|
||||
|
||||
for field, value in self.ListFields():
|
||||
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
|
||||
if field.is_extension:
|
||||
name = '(%s)' % field.full_name
|
||||
else:
|
||||
name = field.name
|
||||
|
||||
if _IsMapField(field):
|
||||
if _IsMessageMapField(field):
|
||||
for key in value:
|
||||
element = value[key]
|
||||
prefix = '%s[%s].' % (name, key)
|
||||
sub_errors = element.FindInitializationErrors()
|
||||
errors += [prefix + error for error in sub_errors]
|
||||
else:
|
||||
# ScalarMaps can't have any initialization errors.
|
||||
pass
|
||||
elif field.label == _FieldDescriptor.LABEL_REPEATED:
|
||||
for i in range(len(value)):
|
||||
element = value[i]
|
||||
prefix = '%s[%d].' % (name, i)
|
||||
sub_errors = element.FindInitializationErrors()
|
||||
errors += [prefix + error for error in sub_errors]
|
||||
else:
|
||||
prefix = name + '.'
|
||||
sub_errors = value.FindInitializationErrors()
|
||||
errors += [prefix + error for error in sub_errors]
|
||||
|
||||
return errors</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.HasField"><code class="name flex">
|
||||
<span>def <span class="ident">HasField</span></span>(<span>self, field_name)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def HasField(self, field_name):
|
||||
try:
|
||||
field = hassable_fields[field_name]
|
||||
except KeyError:
|
||||
raise ValueError(error_msg % (message_descriptor.full_name, field_name))
|
||||
|
||||
if isinstance(field, descriptor_mod.OneofDescriptor):
|
||||
try:
|
||||
return HasField(self, self._oneofs[field].name)
|
||||
except KeyError:
|
||||
return False
|
||||
else:
|
||||
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
|
||||
value = self._fields.get(field)
|
||||
return value is not None and value._is_present_in_parent
|
||||
else:
|
||||
return field in self._fields</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.IsInitialized"><code class="name flex">
|
||||
<span>def <span class="ident">IsInitialized</span></span>(<span>self, errors=None)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Checks if all required fields of a message are set.</p>
|
||||
<h2 id="args">Args</h2>
|
||||
<dl>
|
||||
<dt><strong><code>errors</code></strong></dt>
|
||||
<dd>A list which, if provided, will be populated with the field
|
||||
paths of all missing required fields.</dd>
|
||||
</dl>
|
||||
<h2 id="returns">Returns</h2>
|
||||
<p>True iff the specified message has all required fields set.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def IsInitialized(self, errors=None):
|
||||
"""Checks if all required fields of a message are set.
|
||||
|
||||
Args:
|
||||
errors: A list which, if provided, will be populated with the field
|
||||
paths of all missing required fields.
|
||||
|
||||
Returns:
|
||||
True iff the specified message has all required fields set.
|
||||
"""
|
||||
|
||||
# Performance is critical so we avoid HasField() and ListFields().
|
||||
|
||||
for field in required_fields:
|
||||
if (field not in self._fields or
|
||||
(field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE and
|
||||
not self._fields[field]._is_present_in_parent)):
|
||||
if errors is not None:
|
||||
errors.extend(self.FindInitializationErrors())
|
||||
return False
|
||||
|
||||
for field, value in list(self._fields.items()): # dict can change size!
|
||||
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
|
||||
if field.label == _FieldDescriptor.LABEL_REPEATED:
|
||||
if (field.message_type.has_options and
|
||||
field.message_type.GetOptions().map_entry):
|
||||
continue
|
||||
for element in value:
|
||||
if not element.IsInitialized():
|
||||
if errors is not None:
|
||||
errors.extend(self.FindInitializationErrors())
|
||||
return False
|
||||
elif value._is_present_in_parent and not value.IsInitialized():
|
||||
if errors is not None:
|
||||
errors.extend(self.FindInitializationErrors())
|
||||
return False
|
||||
|
||||
return True</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.ListFields"><code class="name flex">
|
||||
<span>def <span class="ident">ListFields</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def ListFields(self):
|
||||
all_fields = [item for item in self._fields.items() if _IsPresent(item)]
|
||||
all_fields.sort(key = lambda item: item[0].number)
|
||||
return all_fields</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.MergeFrom"><code class="name flex">
|
||||
<span>def <span class="ident">MergeFrom</span></span>(<span>self, msg)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def MergeFrom(self, msg):
|
||||
if not isinstance(msg, cls):
|
||||
raise TypeError(
|
||||
'Parameter to MergeFrom() must be instance of same class: '
|
||||
'expected %s got %s.' % (_FullyQualifiedClassName(cls),
|
||||
_FullyQualifiedClassName(msg.__class__)))
|
||||
|
||||
assert msg is not self
|
||||
self._Modified()
|
||||
|
||||
fields = self._fields
|
||||
|
||||
for field, value in msg._fields.items():
|
||||
if field.label == LABEL_REPEATED:
|
||||
field_value = fields.get(field)
|
||||
if field_value is None:
|
||||
# Construct a new object to represent this field.
|
||||
field_value = field._default_constructor(self)
|
||||
fields[field] = field_value
|
||||
field_value.MergeFrom(value)
|
||||
elif field.cpp_type == CPPTYPE_MESSAGE:
|
||||
if value._is_present_in_parent:
|
||||
field_value = fields.get(field)
|
||||
if field_value is None:
|
||||
# Construct a new object to represent this field.
|
||||
field_value = field._default_constructor(self)
|
||||
fields[field] = field_value
|
||||
field_value.MergeFrom(value)
|
||||
else:
|
||||
self._fields[field] = value
|
||||
if field.containing_oneof:
|
||||
self._UpdateOneofState(field)
|
||||
|
||||
if msg._unknown_fields:
|
||||
if not self._unknown_fields:
|
||||
self._unknown_fields = []
|
||||
self._unknown_fields.extend(msg._unknown_fields)
|
||||
# pylint: disable=protected-access
|
||||
if self._unknown_field_set is None:
|
||||
self._unknown_field_set = containers.UnknownFieldSet()
|
||||
self._unknown_field_set._extend(msg._unknown_field_set)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.MergeFromString"><code class="name flex">
|
||||
<span>def <span class="ident">MergeFromString</span></span>(<span>self, serialized)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def MergeFromString(self, serialized):
|
||||
serialized = memoryview(serialized)
|
||||
length = len(serialized)
|
||||
try:
|
||||
if self._InternalParse(serialized, 0, length) != length:
|
||||
# The only reason _InternalParse would return early is if it
|
||||
# encountered an end-group tag.
|
||||
raise message_mod.DecodeError('Unexpected end-group tag.')
|
||||
except (IndexError, TypeError):
|
||||
# Now ord(buf[p:p+1]) == ord('') gets TypeError.
|
||||
raise message_mod.DecodeError('Truncated message.')
|
||||
except struct.error as e:
|
||||
raise message_mod.DecodeError(e)
|
||||
return length # Return this for legacy reasons.</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.SerializePartialToString"><code class="name flex">
|
||||
<span>def <span class="ident">SerializePartialToString</span></span>(<span>self, **kwargs)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def SerializePartialToString(self, **kwargs):
|
||||
out = BytesIO()
|
||||
self._InternalSerialize(out.write, **kwargs)
|
||||
return out.getvalue()</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.SerializeToString"><code class="name flex">
|
||||
<span>def <span class="ident">SerializeToString</span></span>(<span>self, **kwargs)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def SerializeToString(self, **kwargs):
|
||||
# Check if the message has all of its required fields set.
|
||||
if not self.IsInitialized():
|
||||
raise message_mod.EncodeError(
|
||||
'Message %s is missing required fields: %s' % (
|
||||
self.DESCRIPTOR.full_name, ','.join(self.FindInitializationErrors())))
|
||||
return self.SerializePartialToString(**kwargs)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.SetInParent"><code class="name flex">
|
||||
<span>def <span class="ident">SetInParent</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Sets the _cached_byte_size_dirty bit to true,
|
||||
and propagates this to our listener iff this was a state change.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def Modified(self):
|
||||
"""Sets the _cached_byte_size_dirty bit to true,
|
||||
and propagates this to our listener iff this was a state change.
|
||||
"""
|
||||
|
||||
# Note: Some callers check _cached_byte_size_dirty before calling
|
||||
# _Modified() as an extra optimization. So, if this method is ever
|
||||
# changed such that it does stuff even when _cached_byte_size_dirty is
|
||||
# already true, the callers need to be updated.
|
||||
if not self._cached_byte_size_dirty:
|
||||
self._cached_byte_size_dirty = True
|
||||
self._listener_for_children.dirty = True
|
||||
self._is_present_in_parent = True
|
||||
self._listener.Modified()</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.UnknownFields"><code class="name flex">
|
||||
<span>def <span class="ident">UnknownFields</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def _UnknownFields(self):
|
||||
if self._unknown_field_set is None: # pylint: disable=protected-access
|
||||
# pylint: disable=protected-access
|
||||
self._unknown_field_set = containers.UnknownFieldSet()
|
||||
return self._unknown_field_set # pylint: disable=protected-access</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.WhichOneof"><code class="name flex">
|
||||
<span>def <span class="ident">WhichOneof</span></span>(<span>self, oneof_name)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Returns the name of the currently set field inside a oneof, or None.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def WhichOneof(self, oneof_name):
|
||||
"""Returns the name of the currently set field inside a oneof, or None."""
|
||||
try:
|
||||
field = message_descriptor.oneofs_by_name[oneof_name]
|
||||
except KeyError:
|
||||
raise ValueError(
|
||||
'Protocol message has no oneof "%s" field.' % oneof_name)
|
||||
|
||||
nested_field = self._oneofs.get(field, None)
|
||||
if nested_field is not None and self.HasField(nested_field.name):
|
||||
return nested_field.name
|
||||
else:
|
||||
return None</code></pre>
|
||||
</details>
|
||||
<div class="desc"><p>Field EnvironmentalMeasurement.temperature</p></div>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
@@ -708,27 +173,7 @@ and propagates this to our listener iff this was a state change.</p></div>
|
||||
<li>
|
||||
<h4><code><a title="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement" href="#meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement">EnvironmentalMeasurement</a></code></h4>
|
||||
<ul class="">
|
||||
<li><code><a title="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.BAROMETRIC_PRESSURE_FIELD_NUMBER" href="#meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.BAROMETRIC_PRESSURE_FIELD_NUMBER">BAROMETRIC_PRESSURE_FIELD_NUMBER</a></code></li>
|
||||
<li><code><a title="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.ByteSize" href="#meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.ByteSize">ByteSize</a></code></li>
|
||||
<li><code><a title="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.Clear" href="#meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.Clear">Clear</a></code></li>
|
||||
<li><code><a title="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.ClearField" href="#meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.ClearField">ClearField</a></code></li>
|
||||
<li><code><a title="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.DESCRIPTOR" href="#meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.DESCRIPTOR">DESCRIPTOR</a></code></li>
|
||||
<li><code><a title="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.DiscardUnknownFields" href="#meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.DiscardUnknownFields">DiscardUnknownFields</a></code></li>
|
||||
<li><code><a title="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.FindInitializationErrors" href="#meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.FindInitializationErrors">FindInitializationErrors</a></code></li>
|
||||
<li><code><a title="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.FromString" href="#meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.FromString">FromString</a></code></li>
|
||||
<li><code><a title="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.HasField" href="#meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.HasField">HasField</a></code></li>
|
||||
<li><code><a title="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.IsInitialized" href="#meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.IsInitialized">IsInitialized</a></code></li>
|
||||
<li><code><a title="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.ListFields" href="#meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.ListFields">ListFields</a></code></li>
|
||||
<li><code><a title="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.MergeFrom" href="#meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.MergeFrom">MergeFrom</a></code></li>
|
||||
<li><code><a title="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.MergeFromString" href="#meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.MergeFromString">MergeFromString</a></code></li>
|
||||
<li><code><a title="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.RELATIVE_HUMIDITY_FIELD_NUMBER" href="#meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.RELATIVE_HUMIDITY_FIELD_NUMBER">RELATIVE_HUMIDITY_FIELD_NUMBER</a></code></li>
|
||||
<li><code><a title="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.RegisterExtension" href="#meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.RegisterExtension">RegisterExtension</a></code></li>
|
||||
<li><code><a title="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.SerializePartialToString" href="#meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.SerializePartialToString">SerializePartialToString</a></code></li>
|
||||
<li><code><a title="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.SerializeToString" href="#meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.SerializeToString">SerializeToString</a></code></li>
|
||||
<li><code><a title="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.SetInParent" href="#meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.SetInParent">SetInParent</a></code></li>
|
||||
<li><code><a title="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.TEMPERATURE_FIELD_NUMBER" href="#meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.TEMPERATURE_FIELD_NUMBER">TEMPERATURE_FIELD_NUMBER</a></code></li>
|
||||
<li><code><a title="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.UnknownFields" href="#meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.UnknownFields">UnknownFields</a></code></li>
|
||||
<li><code><a title="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.WhichOneof" href="#meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.WhichOneof">WhichOneof</a></code></li>
|
||||
<li><code><a title="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.barometric_pressure" href="#meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.barometric_pressure">barometric_pressure</a></code></li>
|
||||
<li><code><a title="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.relative_humidity" href="#meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.relative_humidity">relative_humidity</a></code></li>
|
||||
<li><code><a title="meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.temperature" href="#meshtastic.environmental_measurement_pb2.EnvironmentalMeasurement.temperature">temperature</a></code></li>
|
||||
|
||||
+28
-15
@@ -66,6 +66,7 @@ For ASCII these two strings will be the same, but for
|
||||
unicode scripts they can be different.</p>
|
||||
<h1 id="example-usage">Example Usage</h1>
|
||||
<pre><code>import meshtastic
|
||||
import meshtastic.serial_interface
|
||||
from pubsub import pub
|
||||
|
||||
def onReceive(packet, interface): # called when a packet arrives
|
||||
@@ -78,7 +79,7 @@ def onConnection(interface, topic=pub.AUTO_TOPIC): # called when we (re)connect
|
||||
pub.subscribe(onReceive, "meshtastic.receive")
|
||||
pub.subscribe(onConnection, "meshtastic.connection.established")
|
||||
# By default will try to find a meshtastic device, otherwise provide a device path like /dev/ttyUSB0
|
||||
interface = meshtastic.SerialInterface()
|
||||
interface = meshtastic.serial_interface.SerialInterface()
|
||||
|
||||
</code></pre>
|
||||
<details class="source">
|
||||
@@ -124,6 +125,7 @@ unicode scripts they can be different.
|
||||
# Example Usage
|
||||
```
|
||||
import meshtastic
|
||||
import meshtastic.serial_interface
|
||||
from pubsub import pub
|
||||
|
||||
def onReceive(packet, interface): # called when a packet arrives
|
||||
@@ -136,7 +138,7 @@ def onConnection(interface, topic=pub.AUTO_TOPIC): # called when we (re)connect
|
||||
pub.subscribe(onReceive, "meshtastic.receive")
|
||||
pub.subscribe(onConnection, "meshtastic.connection.established")
|
||||
# By default will try to find a meshtastic device, otherwise provide a device path like /dev/ttyUSB0
|
||||
interface = meshtastic.SerialInterface()
|
||||
interface = meshtastic.serial_interface.SerialInterface()
|
||||
|
||||
```
|
||||
|
||||
@@ -167,23 +169,23 @@ from .util import fixme, catchAndIgnore, stripnl, DeferredExecution, Timeout
|
||||
from .node import Node
|
||||
from . import mesh_pb2, portnums_pb2, apponly_pb2, admin_pb2, environmental_measurement_pb2, remote_hardware_pb2, channel_pb2, radioconfig_pb2, util
|
||||
|
||||
# Note: To follow PEP224, comments should be after the module variable.
|
||||
|
||||
"""A special ID that means the local node"""
|
||||
LOCAL_ADDR = "^local"
|
||||
"""A special ID that means the local node"""
|
||||
|
||||
# if using 8 bit nodenums this will be shortend on the target
|
||||
BROADCAST_NUM = 0xffffffff
|
||||
"""if using 8 bit nodenums this will be shortend on the target"""
|
||||
|
||||
"""A special ID that means broadcast"""
|
||||
BROADCAST_ADDR = "^all"
|
||||
"""A special ID that means broadcast"""
|
||||
|
||||
|
||||
OUR_APP_VERSION = 20200
|
||||
"""The numeric buildnumber (shared with android apps) specifying the
|
||||
level of device code we are guaranteed to understand
|
||||
|
||||
format is Mmmss (where M is 1+the numeric major number. i.e. 20120 means 1.1.20
|
||||
"""
|
||||
OUR_APP_VERSION = 20200
|
||||
|
||||
publishingThread = DeferredExecution("publishing")
|
||||
|
||||
@@ -242,10 +244,11 @@ def _onNodeInfoReceive(iface, asDict):
|
||||
|
||||
|
||||
def _receiveInfoUpdate(iface, asDict):
|
||||
iface._getOrCreateByNum(asDict["from"])["lastReceived"] = asDict
|
||||
iface._getOrCreateByNum(asDict["from"])["lastHeard"] = asDict.get("rxTime")
|
||||
iface._getOrCreateByNum(asDict["from"])["snr"] = asDict.get("rxSnr")
|
||||
iface._getOrCreateByNum(asDict["from"])["hopLimit"] = asDict.get("hopLimit")
|
||||
if "from" in asDict:
|
||||
iface._getOrCreateByNum(asDict["from"])["lastReceived"] = asDict
|
||||
iface._getOrCreateByNum(asDict["from"])["lastHeard"] = asDict.get("rxTime")
|
||||
iface._getOrCreateByNum(asDict["from"])["snr"] = asDict.get("rxSnr")
|
||||
iface._getOrCreateByNum(asDict["from"])["hopLimit"] = asDict.get("hopLimit")
|
||||
|
||||
|
||||
"""Well known message payloads can register decoders for automatic protobuf parsing"""
|
||||
@@ -368,13 +371,21 @@ messages and report back if successful.</p></div>
|
||||
<dl>
|
||||
<dt id="meshtastic.BROADCAST_ADDR"><code class="name">var <span class="ident">BROADCAST_ADDR</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>The numeric buildnumber (shared with android apps) specifying the
|
||||
level of device code we are guaranteed to understand</p>
|
||||
<p>format is Mmmss (where M is 1+the numeric major number. i.e. 20120 means 1.1.20</p></div>
|
||||
<div class="desc"><p>A special ID that means broadcast</p></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.BROADCAST_NUM"><code class="name">var <span class="ident">BROADCAST_NUM</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>A special ID that means broadcast</p></div>
|
||||
<div class="desc"><p>if using 8 bit nodenums this will be shortend on the target</p></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.LOCAL_ADDR"><code class="name">var <span class="ident">LOCAL_ADDR</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>A special ID that means the local node</p></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.OUR_APP_VERSION"><code class="name">var <span class="ident">OUR_APP_VERSION</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>The numeric buildnumber (shared with android apps) specifying the
|
||||
level of device code we are guaranteed to understand</p>
|
||||
<p>format is Mmmss (where M is 1+the numeric major number. i.e. 20120 means 1.1.20</p></div>
|
||||
</dd>
|
||||
</dl>
|
||||
</section>
|
||||
@@ -495,6 +506,8 @@ level of device code we are guaranteed to understand</p>
|
||||
<ul class="">
|
||||
<li><code><a title="meshtastic.BROADCAST_ADDR" href="#meshtastic.BROADCAST_ADDR">BROADCAST_ADDR</a></code></li>
|
||||
<li><code><a title="meshtastic.BROADCAST_NUM" href="#meshtastic.BROADCAST_NUM">BROADCAST_NUM</a></code></li>
|
||||
<li><code><a title="meshtastic.LOCAL_ADDR" href="#meshtastic.LOCAL_ADDR">LOCAL_ADDR</a></code></li>
|
||||
<li><code><a title="meshtastic.OUR_APP_VERSION" href="#meshtastic.OUR_APP_VERSION">OUR_APP_VERSION</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-classes">Classes</a></h3>
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">""" Mesh Interface class
|
||||
<pre><code class="python">"""Mesh Interface class
|
||||
"""
|
||||
import sys
|
||||
import random
|
||||
@@ -45,15 +45,11 @@ from pubsub import pub
|
||||
from google.protobuf.json_format import MessageToJson
|
||||
|
||||
|
||||
import meshtastic.node
|
||||
from . import portnums_pb2, mesh_pb2
|
||||
from .util import stripnl, Timeout, our_exit
|
||||
from .node import Node
|
||||
from .__init__ import LOCAL_ADDR, BROADCAST_NUM, BROADCAST_ADDR, ResponseHandler, publishingThread, OUR_APP_VERSION, protocols
|
||||
|
||||
|
||||
defaultHopLimit = 3
|
||||
|
||||
|
||||
class MeshInterface:
|
||||
"""Interface class for meshtastic devices
|
||||
|
||||
@@ -75,7 +71,7 @@ class MeshInterface:
|
||||
self.nodes = None # FIXME
|
||||
self.isConnected = threading.Event()
|
||||
self.noProto = noProto
|
||||
self.localNode = Node(self, -1) # We fixup nodenum later
|
||||
self.localNode = meshtastic.node.Node(self, -1) # We fixup nodenum later
|
||||
self.myInfo = None # We don't have device info yet
|
||||
self.responseHandlers = {} # A map from request ID to the handler
|
||||
self.failure = None # If we've encountered a fatal exception it will be kept here
|
||||
@@ -85,6 +81,9 @@ class MeshInterface:
|
||||
self.currentPacketId = random.randint(0, 0xffffffff)
|
||||
self.nodesByNum = None
|
||||
self.configId = None
|
||||
self.defaultHopLimit = 3
|
||||
self.gotResponse = False # used in gpio read
|
||||
self.mask = None # used in gpio read and gpio watch
|
||||
|
||||
def close(self):
|
||||
"""Shutdown this interface"""
|
||||
@@ -135,6 +134,7 @@ class MeshInterface:
|
||||
|
||||
rows = []
|
||||
if self.nodes:
|
||||
logging.debug(f'self.nodes:{self.nodes}')
|
||||
for node in self.nodes.values():
|
||||
if not includeSelf and node['num'] == self.localNode.nodeNum:
|
||||
continue
|
||||
@@ -180,7 +180,8 @@ class MeshInterface:
|
||||
if nodeId == LOCAL_ADDR:
|
||||
return self.localNode
|
||||
else:
|
||||
n = Node(self, nodeId)
|
||||
n = meshtastic.node.Node(self, nodeId)
|
||||
logging.debug("About to requestConfig")
|
||||
n.requestConfig()
|
||||
if not n.waitForConfig():
|
||||
our_exit("Error: Timed out waiting for node config")
|
||||
@@ -190,7 +191,7 @@ class MeshInterface:
|
||||
destinationId=BROADCAST_ADDR,
|
||||
wantAck=False,
|
||||
wantResponse=False,
|
||||
hopLimit=defaultHopLimit,
|
||||
hopLimit=None,
|
||||
onResponse=None,
|
||||
channelIndex=0):
|
||||
"""Send a utf8 string to some other node, if the node has a display it
|
||||
@@ -212,6 +213,9 @@ class MeshInterface:
|
||||
Returns the sent packet. The id field will be populated in this packet
|
||||
and can be used to track future message acks/naks.
|
||||
"""
|
||||
if hopLimit is None:
|
||||
hopLimit = self.defaultHopLimit
|
||||
|
||||
return self.sendData(text.encode("utf-8"), destinationId,
|
||||
portNum=portnums_pb2.PortNum.TEXT_MESSAGE_APP,
|
||||
wantAck=wantAck,
|
||||
@@ -223,7 +227,7 @@ class MeshInterface:
|
||||
def sendData(self, data, destinationId=BROADCAST_ADDR,
|
||||
portNum=portnums_pb2.PortNum.PRIVATE_APP, wantAck=False,
|
||||
wantResponse=False,
|
||||
hopLimit=defaultHopLimit,
|
||||
hopLimit=None,
|
||||
onResponse=None,
|
||||
channelIndex=0):
|
||||
"""Send a data packet to some other node
|
||||
@@ -243,16 +247,22 @@ class MeshInterface:
|
||||
onResponse -- A closure of the form funct(packet), that will be
|
||||
called when a response packet arrives (or the transaction
|
||||
is NAKed due to non receipt)
|
||||
channelIndex - channel number to use
|
||||
|
||||
Returns the sent packet. The id field will be populated in this packet
|
||||
and can be used to track future message acks/naks.
|
||||
"""
|
||||
if hopLimit is None:
|
||||
hopLimit = self.defaultHopLimit
|
||||
|
||||
if getattr(data, "SerializeToString", None):
|
||||
logging.debug(f"Serializing protobuf as data: {stripnl(data)}")
|
||||
data = data.SerializeToString()
|
||||
|
||||
logging.debug(f"len(data): {len(data)}")
|
||||
logging.debug(f"mesh_pb2.Constants.DATA_PAYLOAD_LEN: {mesh_pb2.Constants.DATA_PAYLOAD_LEN}")
|
||||
if len(data) > mesh_pb2.Constants.DATA_PAYLOAD_LEN:
|
||||
Exception("Data payload too big")
|
||||
raise Exception("Data payload too big")
|
||||
|
||||
if portNum == portnums_pb2.PortNum.UNKNOWN_APP: # we are now more strict wrt port numbers
|
||||
our_exit("Warning: A non-zero port number must be specified")
|
||||
@@ -285,16 +295,20 @@ class MeshInterface:
|
||||
p = mesh_pb2.Position()
|
||||
if latitude != 0.0:
|
||||
p.latitude_i = int(latitude / 1e-7)
|
||||
logging.debug(f'p.latitude_i:{p.latitude_i}')
|
||||
|
||||
if longitude != 0.0:
|
||||
p.longitude_i = int(longitude / 1e-7)
|
||||
logging.debug(f'p.longitude_i:{p.longitude_i}')
|
||||
|
||||
if altitude != 0:
|
||||
p.altitude = int(altitude)
|
||||
logging.debug(f'p.altitude:{p.altitude}')
|
||||
|
||||
if timeSec == 0:
|
||||
timeSec = time.time() # returns unix timestamp in seconds
|
||||
p.time = int(timeSec)
|
||||
logging.debug(f'p.time:{p.time}')
|
||||
|
||||
return self.sendData(p, destinationId,
|
||||
portNum=portnums_pb2.PortNum.POSITION_APP,
|
||||
@@ -306,13 +320,15 @@ class MeshInterface:
|
||||
|
||||
def _sendPacket(self, meshPacket,
|
||||
destinationId=BROADCAST_ADDR,
|
||||
wantAck=False, hopLimit=defaultHopLimit):
|
||||
wantAck=False, hopLimit=None):
|
||||
"""Send a MeshPacket to the specified node (or if unspecified, broadcast).
|
||||
You probably don't want this - use sendData instead.
|
||||
|
||||
Returns the sent packet. The id field will be populated in this packet and
|
||||
can be used to track future message acks/naks.
|
||||
"""
|
||||
if hopLimit is None:
|
||||
hopLimit = self.defaultHopLimit
|
||||
|
||||
# We allow users to talk to the local node before we've completed the full connection flow...
|
||||
if(self.myInfo is not None and destinationId != self.myInfo.my_node_num):
|
||||
@@ -320,6 +336,7 @@ class MeshInterface:
|
||||
|
||||
toRadio = mesh_pb2.ToRadio()
|
||||
|
||||
nodeNum = 0
|
||||
if destinationId is None:
|
||||
our_exit("Warning: destinationId must not be None")
|
||||
elif isinstance(destinationId, int):
|
||||
@@ -327,15 +344,21 @@ class MeshInterface:
|
||||
elif destinationId == BROADCAST_ADDR:
|
||||
nodeNum = BROADCAST_NUM
|
||||
elif destinationId == LOCAL_ADDR:
|
||||
nodeNum = self.myInfo.my_node_num
|
||||
if self.myInfo:
|
||||
nodeNum = self.myInfo.my_node_num
|
||||
else:
|
||||
our_exit("Warning: No myInfo found.")
|
||||
# A simple hex style nodeid - we can parse this without needing the DB
|
||||
elif destinationId.startswith("!"):
|
||||
nodeNum = int(destinationId[1:], 16)
|
||||
else:
|
||||
node = self.nodes.get(destinationId)
|
||||
if not node:
|
||||
our_exit(f"Warning: NodeId {destinationId} not found in DB")
|
||||
nodeNum = node['num']
|
||||
if self.nodes:
|
||||
node = self.nodes.get(destinationId)
|
||||
if not node:
|
||||
our_exit(f"Warning: NodeId {destinationId} not found in DB")
|
||||
nodeNum = node['num']
|
||||
else:
|
||||
logging.warning("Warning: There were no self.nodes.")
|
||||
|
||||
meshPacket.to = nodeNum
|
||||
meshPacket.want_ack = wantAck
|
||||
@@ -347,8 +370,11 @@ class MeshInterface:
|
||||
meshPacket.id = self._generatePacketId()
|
||||
|
||||
toRadio.packet.CopyFrom(meshPacket)
|
||||
#logging.debug(f"Sending packet: {stripnl(meshPacket)}")
|
||||
self._sendToRadio(toRadio)
|
||||
if self.noProto:
|
||||
logging.warning(f"Not sending packet because protocol use is disabled by noProto")
|
||||
else:
|
||||
logging.debug(f"Sending packet: {stripnl(meshPacket)}")
|
||||
self._sendToRadio(toRadio)
|
||||
return meshPacket
|
||||
|
||||
def waitForConfig(self):
|
||||
@@ -361,6 +387,7 @@ class MeshInterface:
|
||||
"""Get info about my node."""
|
||||
if self.myInfo is None:
|
||||
return None
|
||||
logging.debug(f'self.nodesByNum:{self.nodesByNum}')
|
||||
return self.nodesByNum.get(self.myInfo.my_node_num)
|
||||
|
||||
def getMyUser(self):
|
||||
@@ -387,8 +414,9 @@ class MeshInterface:
|
||||
def _waitConnected(self):
|
||||
"""Block until the initial node db download is complete, or timeout
|
||||
and raise an exception"""
|
||||
if not self.isConnected.wait(10.0): # timeout after 10 seconds
|
||||
raise Exception("Timed out waiting for connection completion")
|
||||
if not self.noProto:
|
||||
if not self.isConnected.wait(15.0): # timeout after x seconds
|
||||
raise Exception("Timed out waiting for connection completion")
|
||||
|
||||
# If we failed while connecting, raise the connection to the client
|
||||
if self.failure:
|
||||
@@ -478,8 +506,9 @@ class MeshInterface:
|
||||
Called by subclasses."""
|
||||
fromRadio = mesh_pb2.FromRadio()
|
||||
fromRadio.ParseFromString(fromRadioBytes)
|
||||
logging.debug(f"in mesh_interface.py _handleFromRadio() fromRadioBytes: {fromRadioBytes}")
|
||||
asDict = google.protobuf.json_format.MessageToDict(fromRadio)
|
||||
#logging.debug(f"Received from radio: {fromRadio}")
|
||||
logging.debug(f"Received from radio: {fromRadio}")
|
||||
if fromRadio.HasField("my_info"):
|
||||
self.myInfo = fromRadio.my_info
|
||||
self.localNode.nodeNum = self.myInfo.my_node_num
|
||||
@@ -512,7 +541,8 @@ class MeshInterface:
|
||||
|
||||
self.nodesByNum[node["num"]] = node
|
||||
if "user" in node: # Some nodes might not have user/ids assigned yet
|
||||
self.nodes[node["user"]["id"]] = node
|
||||
if "id" in node["user"]:
|
||||
self.nodes[node["user"]["id"]] = node
|
||||
publishingThread.queueWork(lambda: pub.sendMessage("meshtastic.node.updated",
|
||||
node=node, interface=self))
|
||||
elif fromRadio.config_complete_id == self.configId:
|
||||
@@ -572,16 +602,22 @@ class MeshInterface:
|
||||
self.nodesByNum[nodeNum] = n
|
||||
return n
|
||||
|
||||
def _handlePacketFromRadio(self, meshPacket):
|
||||
def _handlePacketFromRadio(self, meshPacket, hack=False):
|
||||
"""Handle a MeshPacket that just arrived from the radio
|
||||
|
||||
hack - well, since we used 'from', which is a python keyword,
|
||||
as an attribute to MeshPacket in protobufs,
|
||||
there really is no way to do something like this:
|
||||
meshPacket = mesh_pb2.MeshPacket()
|
||||
meshPacket.from = 123
|
||||
If hack is True, we can unit test this code.
|
||||
|
||||
Will publish one of the following events:
|
||||
- meshtastic.receive.text(packet = MeshPacket dictionary)
|
||||
- meshtastic.receive.position(packet = MeshPacket dictionary)
|
||||
- meshtastic.receive.user(packet = MeshPacket dictionary)
|
||||
- meshtastic.receive.data(packet = MeshPacket dictionary)
|
||||
"""
|
||||
|
||||
asDict = google.protobuf.json_format.MessageToDict(meshPacket)
|
||||
|
||||
# We normally decompose the payload into a dictionary so that the client
|
||||
@@ -590,10 +626,10 @@ class MeshInterface:
|
||||
asDict["raw"] = meshPacket
|
||||
|
||||
# from might be missing if the nodenum was zero.
|
||||
if "from" not in asDict:
|
||||
if not hack and "from" not in asDict:
|
||||
asDict["from"] = 0
|
||||
logging.error(
|
||||
f"Device returned a packet we sent, ignoring: {stripnl(asDict)}")
|
||||
logging.error(f"Device returned a packet we sent, ignoring: {stripnl(asDict)}")
|
||||
print(f"Error: Device returned a packet we sent, ignoring: {stripnl(asDict)}")
|
||||
return
|
||||
if "to" not in asDict:
|
||||
asDict["to"] = 0
|
||||
@@ -621,9 +657,10 @@ class MeshInterface:
|
||||
# UNKNOWN_APP is the default protobuf portnum value, and therefore if not
|
||||
# set it will not be populated at all to make API usage easier, set
|
||||
# it to prevent confusion
|
||||
if not "portnum" in decoded:
|
||||
decoded["portnum"] = portnums_pb2.PortNum.Name(
|
||||
portnums_pb2.PortNum.UNKNOWN_APP)
|
||||
if "portnum" not in decoded:
|
||||
new_portnum = portnums_pb2.PortNum.Name(portnums_pb2.PortNum.UNKNOWN_APP)
|
||||
decoded["portnum"] = new_portnum
|
||||
logging.warning(f"portnum was not in decoded. Setting to:{new_portnum}")
|
||||
|
||||
portnum = decoded["portnum"]
|
||||
|
||||
@@ -717,7 +754,7 @@ link - just be a dumb serial client.</p></div>
|
||||
self.nodes = None # FIXME
|
||||
self.isConnected = threading.Event()
|
||||
self.noProto = noProto
|
||||
self.localNode = Node(self, -1) # We fixup nodenum later
|
||||
self.localNode = meshtastic.node.Node(self, -1) # We fixup nodenum later
|
||||
self.myInfo = None # We don't have device info yet
|
||||
self.responseHandlers = {} # A map from request ID to the handler
|
||||
self.failure = None # If we've encountered a fatal exception it will be kept here
|
||||
@@ -727,6 +764,9 @@ link - just be a dumb serial client.</p></div>
|
||||
self.currentPacketId = random.randint(0, 0xffffffff)
|
||||
self.nodesByNum = None
|
||||
self.configId = None
|
||||
self.defaultHopLimit = 3
|
||||
self.gotResponse = False # used in gpio read
|
||||
self.mask = None # used in gpio read and gpio watch
|
||||
|
||||
def close(self):
|
||||
"""Shutdown this interface"""
|
||||
@@ -777,6 +817,7 @@ link - just be a dumb serial client.</p></div>
|
||||
|
||||
rows = []
|
||||
if self.nodes:
|
||||
logging.debug(f'self.nodes:{self.nodes}')
|
||||
for node in self.nodes.values():
|
||||
if not includeSelf and node['num'] == self.localNode.nodeNum:
|
||||
continue
|
||||
@@ -822,7 +863,8 @@ link - just be a dumb serial client.</p></div>
|
||||
if nodeId == LOCAL_ADDR:
|
||||
return self.localNode
|
||||
else:
|
||||
n = Node(self, nodeId)
|
||||
n = meshtastic.node.Node(self, nodeId)
|
||||
logging.debug("About to requestConfig")
|
||||
n.requestConfig()
|
||||
if not n.waitForConfig():
|
||||
our_exit("Error: Timed out waiting for node config")
|
||||
@@ -832,7 +874,7 @@ link - just be a dumb serial client.</p></div>
|
||||
destinationId=BROADCAST_ADDR,
|
||||
wantAck=False,
|
||||
wantResponse=False,
|
||||
hopLimit=defaultHopLimit,
|
||||
hopLimit=None,
|
||||
onResponse=None,
|
||||
channelIndex=0):
|
||||
"""Send a utf8 string to some other node, if the node has a display it
|
||||
@@ -854,6 +896,9 @@ link - just be a dumb serial client.</p></div>
|
||||
Returns the sent packet. The id field will be populated in this packet
|
||||
and can be used to track future message acks/naks.
|
||||
"""
|
||||
if hopLimit is None:
|
||||
hopLimit = self.defaultHopLimit
|
||||
|
||||
return self.sendData(text.encode("utf-8"), destinationId,
|
||||
portNum=portnums_pb2.PortNum.TEXT_MESSAGE_APP,
|
||||
wantAck=wantAck,
|
||||
@@ -865,7 +910,7 @@ link - just be a dumb serial client.</p></div>
|
||||
def sendData(self, data, destinationId=BROADCAST_ADDR,
|
||||
portNum=portnums_pb2.PortNum.PRIVATE_APP, wantAck=False,
|
||||
wantResponse=False,
|
||||
hopLimit=defaultHopLimit,
|
||||
hopLimit=None,
|
||||
onResponse=None,
|
||||
channelIndex=0):
|
||||
"""Send a data packet to some other node
|
||||
@@ -885,16 +930,22 @@ link - just be a dumb serial client.</p></div>
|
||||
onResponse -- A closure of the form funct(packet), that will be
|
||||
called when a response packet arrives (or the transaction
|
||||
is NAKed due to non receipt)
|
||||
channelIndex - channel number to use
|
||||
|
||||
Returns the sent packet. The id field will be populated in this packet
|
||||
and can be used to track future message acks/naks.
|
||||
"""
|
||||
if hopLimit is None:
|
||||
hopLimit = self.defaultHopLimit
|
||||
|
||||
if getattr(data, "SerializeToString", None):
|
||||
logging.debug(f"Serializing protobuf as data: {stripnl(data)}")
|
||||
data = data.SerializeToString()
|
||||
|
||||
logging.debug(f"len(data): {len(data)}")
|
||||
logging.debug(f"mesh_pb2.Constants.DATA_PAYLOAD_LEN: {mesh_pb2.Constants.DATA_PAYLOAD_LEN}")
|
||||
if len(data) > mesh_pb2.Constants.DATA_PAYLOAD_LEN:
|
||||
Exception("Data payload too big")
|
||||
raise Exception("Data payload too big")
|
||||
|
||||
if portNum == portnums_pb2.PortNum.UNKNOWN_APP: # we are now more strict wrt port numbers
|
||||
our_exit("Warning: A non-zero port number must be specified")
|
||||
@@ -927,16 +978,20 @@ link - just be a dumb serial client.</p></div>
|
||||
p = mesh_pb2.Position()
|
||||
if latitude != 0.0:
|
||||
p.latitude_i = int(latitude / 1e-7)
|
||||
logging.debug(f'p.latitude_i:{p.latitude_i}')
|
||||
|
||||
if longitude != 0.0:
|
||||
p.longitude_i = int(longitude / 1e-7)
|
||||
logging.debug(f'p.longitude_i:{p.longitude_i}')
|
||||
|
||||
if altitude != 0:
|
||||
p.altitude = int(altitude)
|
||||
logging.debug(f'p.altitude:{p.altitude}')
|
||||
|
||||
if timeSec == 0:
|
||||
timeSec = time.time() # returns unix timestamp in seconds
|
||||
p.time = int(timeSec)
|
||||
logging.debug(f'p.time:{p.time}')
|
||||
|
||||
return self.sendData(p, destinationId,
|
||||
portNum=portnums_pb2.PortNum.POSITION_APP,
|
||||
@@ -948,13 +1003,15 @@ link - just be a dumb serial client.</p></div>
|
||||
|
||||
def _sendPacket(self, meshPacket,
|
||||
destinationId=BROADCAST_ADDR,
|
||||
wantAck=False, hopLimit=defaultHopLimit):
|
||||
wantAck=False, hopLimit=None):
|
||||
"""Send a MeshPacket to the specified node (or if unspecified, broadcast).
|
||||
You probably don't want this - use sendData instead.
|
||||
|
||||
Returns the sent packet. The id field will be populated in this packet and
|
||||
can be used to track future message acks/naks.
|
||||
"""
|
||||
if hopLimit is None:
|
||||
hopLimit = self.defaultHopLimit
|
||||
|
||||
# We allow users to talk to the local node before we've completed the full connection flow...
|
||||
if(self.myInfo is not None and destinationId != self.myInfo.my_node_num):
|
||||
@@ -962,6 +1019,7 @@ link - just be a dumb serial client.</p></div>
|
||||
|
||||
toRadio = mesh_pb2.ToRadio()
|
||||
|
||||
nodeNum = 0
|
||||
if destinationId is None:
|
||||
our_exit("Warning: destinationId must not be None")
|
||||
elif isinstance(destinationId, int):
|
||||
@@ -969,15 +1027,21 @@ link - just be a dumb serial client.</p></div>
|
||||
elif destinationId == BROADCAST_ADDR:
|
||||
nodeNum = BROADCAST_NUM
|
||||
elif destinationId == LOCAL_ADDR:
|
||||
nodeNum = self.myInfo.my_node_num
|
||||
if self.myInfo:
|
||||
nodeNum = self.myInfo.my_node_num
|
||||
else:
|
||||
our_exit("Warning: No myInfo found.")
|
||||
# A simple hex style nodeid - we can parse this without needing the DB
|
||||
elif destinationId.startswith("!"):
|
||||
nodeNum = int(destinationId[1:], 16)
|
||||
else:
|
||||
node = self.nodes.get(destinationId)
|
||||
if not node:
|
||||
our_exit(f"Warning: NodeId {destinationId} not found in DB")
|
||||
nodeNum = node['num']
|
||||
if self.nodes:
|
||||
node = self.nodes.get(destinationId)
|
||||
if not node:
|
||||
our_exit(f"Warning: NodeId {destinationId} not found in DB")
|
||||
nodeNum = node['num']
|
||||
else:
|
||||
logging.warning("Warning: There were no self.nodes.")
|
||||
|
||||
meshPacket.to = nodeNum
|
||||
meshPacket.want_ack = wantAck
|
||||
@@ -989,8 +1053,11 @@ link - just be a dumb serial client.</p></div>
|
||||
meshPacket.id = self._generatePacketId()
|
||||
|
||||
toRadio.packet.CopyFrom(meshPacket)
|
||||
#logging.debug(f"Sending packet: {stripnl(meshPacket)}")
|
||||
self._sendToRadio(toRadio)
|
||||
if self.noProto:
|
||||
logging.warning(f"Not sending packet because protocol use is disabled by noProto")
|
||||
else:
|
||||
logging.debug(f"Sending packet: {stripnl(meshPacket)}")
|
||||
self._sendToRadio(toRadio)
|
||||
return meshPacket
|
||||
|
||||
def waitForConfig(self):
|
||||
@@ -1003,6 +1070,7 @@ link - just be a dumb serial client.</p></div>
|
||||
"""Get info about my node."""
|
||||
if self.myInfo is None:
|
||||
return None
|
||||
logging.debug(f'self.nodesByNum:{self.nodesByNum}')
|
||||
return self.nodesByNum.get(self.myInfo.my_node_num)
|
||||
|
||||
def getMyUser(self):
|
||||
@@ -1029,8 +1097,9 @@ link - just be a dumb serial client.</p></div>
|
||||
def _waitConnected(self):
|
||||
"""Block until the initial node db download is complete, or timeout
|
||||
and raise an exception"""
|
||||
if not self.isConnected.wait(10.0): # timeout after 10 seconds
|
||||
raise Exception("Timed out waiting for connection completion")
|
||||
if not self.noProto:
|
||||
if not self.isConnected.wait(15.0): # timeout after x seconds
|
||||
raise Exception("Timed out waiting for connection completion")
|
||||
|
||||
# If we failed while connecting, raise the connection to the client
|
||||
if self.failure:
|
||||
@@ -1120,8 +1189,9 @@ link - just be a dumb serial client.</p></div>
|
||||
Called by subclasses."""
|
||||
fromRadio = mesh_pb2.FromRadio()
|
||||
fromRadio.ParseFromString(fromRadioBytes)
|
||||
logging.debug(f"in mesh_interface.py _handleFromRadio() fromRadioBytes: {fromRadioBytes}")
|
||||
asDict = google.protobuf.json_format.MessageToDict(fromRadio)
|
||||
#logging.debug(f"Received from radio: {fromRadio}")
|
||||
logging.debug(f"Received from radio: {fromRadio}")
|
||||
if fromRadio.HasField("my_info"):
|
||||
self.myInfo = fromRadio.my_info
|
||||
self.localNode.nodeNum = self.myInfo.my_node_num
|
||||
@@ -1154,7 +1224,8 @@ link - just be a dumb serial client.</p></div>
|
||||
|
||||
self.nodesByNum[node["num"]] = node
|
||||
if "user" in node: # Some nodes might not have user/ids assigned yet
|
||||
self.nodes[node["user"]["id"]] = node
|
||||
if "id" in node["user"]:
|
||||
self.nodes[node["user"]["id"]] = node
|
||||
publishingThread.queueWork(lambda: pub.sendMessage("meshtastic.node.updated",
|
||||
node=node, interface=self))
|
||||
elif fromRadio.config_complete_id == self.configId:
|
||||
@@ -1214,16 +1285,22 @@ link - just be a dumb serial client.</p></div>
|
||||
self.nodesByNum[nodeNum] = n
|
||||
return n
|
||||
|
||||
def _handlePacketFromRadio(self, meshPacket):
|
||||
def _handlePacketFromRadio(self, meshPacket, hack=False):
|
||||
"""Handle a MeshPacket that just arrived from the radio
|
||||
|
||||
hack - well, since we used 'from', which is a python keyword,
|
||||
as an attribute to MeshPacket in protobufs,
|
||||
there really is no way to do something like this:
|
||||
meshPacket = mesh_pb2.MeshPacket()
|
||||
meshPacket.from = 123
|
||||
If hack is True, we can unit test this code.
|
||||
|
||||
Will publish one of the following events:
|
||||
- meshtastic.receive.text(packet = MeshPacket dictionary)
|
||||
- meshtastic.receive.position(packet = MeshPacket dictionary)
|
||||
- meshtastic.receive.user(packet = MeshPacket dictionary)
|
||||
- meshtastic.receive.data(packet = MeshPacket dictionary)
|
||||
"""
|
||||
|
||||
asDict = google.protobuf.json_format.MessageToDict(meshPacket)
|
||||
|
||||
# We normally decompose the payload into a dictionary so that the client
|
||||
@@ -1232,10 +1309,10 @@ link - just be a dumb serial client.</p></div>
|
||||
asDict["raw"] = meshPacket
|
||||
|
||||
# from might be missing if the nodenum was zero.
|
||||
if "from" not in asDict:
|
||||
if not hack and "from" not in asDict:
|
||||
asDict["from"] = 0
|
||||
logging.error(
|
||||
f"Device returned a packet we sent, ignoring: {stripnl(asDict)}")
|
||||
logging.error(f"Device returned a packet we sent, ignoring: {stripnl(asDict)}")
|
||||
print(f"Error: Device returned a packet we sent, ignoring: {stripnl(asDict)}")
|
||||
return
|
||||
if "to" not in asDict:
|
||||
asDict["to"] = 0
|
||||
@@ -1263,9 +1340,10 @@ link - just be a dumb serial client.</p></div>
|
||||
# UNKNOWN_APP is the default protobuf portnum value, and therefore if not
|
||||
# set it will not be populated at all to make API usage easier, set
|
||||
# it to prevent confusion
|
||||
if not "portnum" in decoded:
|
||||
decoded["portnum"] = portnums_pb2.PortNum.Name(
|
||||
portnums_pb2.PortNum.UNKNOWN_APP)
|
||||
if "portnum" not in decoded:
|
||||
new_portnum = portnums_pb2.PortNum.Name(portnums_pb2.PortNum.UNKNOWN_APP)
|
||||
decoded["portnum"] = new_portnum
|
||||
logging.warning(f"portnum was not in decoded. Setting to:{new_portnum}")
|
||||
|
||||
portnum = decoded["portnum"]
|
||||
|
||||
@@ -1364,6 +1442,7 @@ link - just be a dumb serial client.</p></div>
|
||||
"""Get info about my node."""
|
||||
if self.myInfo is None:
|
||||
return None
|
||||
logging.debug(f'self.nodesByNum:{self.nodesByNum}')
|
||||
return self.nodesByNum.get(self.myInfo.my_node_num)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
@@ -1398,7 +1477,8 @@ link - just be a dumb serial client.</p></div>
|
||||
if nodeId == LOCAL_ADDR:
|
||||
return self.localNode
|
||||
else:
|
||||
n = Node(self, nodeId)
|
||||
n = meshtastic.node.Node(self, nodeId)
|
||||
logging.debug("About to requestConfig")
|
||||
n.requestConfig()
|
||||
if not n.waitForConfig():
|
||||
our_exit("Error: Timed out waiting for node config")
|
||||
@@ -1423,7 +1503,7 @@ link - just be a dumb serial client.</p></div>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.mesh_interface.MeshInterface.sendData"><code class="name flex">
|
||||
<span>def <span class="ident">sendData</span></span>(<span>self, data, destinationId='^all', portNum=256, wantAck=False, wantResponse=False, hopLimit=3, onResponse=None, channelIndex=0)</span>
|
||||
<span>def <span class="ident">sendData</span></span>(<span>self, data, destinationId='^all', portNum=256, wantAck=False, wantResponse=False, hopLimit=None, onResponse=None, channelIndex=0)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Send a data packet to some other node</p>
|
||||
@@ -1441,7 +1521,8 @@ wantResponse – True if you want the service on the other
|
||||
side to send an application layer response
|
||||
onResponse – A closure of the form funct(packet), that will be
|
||||
called when a response packet arrives (or the transaction
|
||||
is NAKed due to non receipt)</p>
|
||||
is NAKed due to non receipt)
|
||||
channelIndex - channel number to use</p>
|
||||
<p>Returns the sent packet. The id field will be populated in this packet
|
||||
and can be used to track future message acks/naks.</p></div>
|
||||
<details class="source">
|
||||
@@ -1451,7 +1532,7 @@ and can be used to track future message acks/naks.</p></div>
|
||||
<pre><code class="python">def sendData(self, data, destinationId=BROADCAST_ADDR,
|
||||
portNum=portnums_pb2.PortNum.PRIVATE_APP, wantAck=False,
|
||||
wantResponse=False,
|
||||
hopLimit=defaultHopLimit,
|
||||
hopLimit=None,
|
||||
onResponse=None,
|
||||
channelIndex=0):
|
||||
"""Send a data packet to some other node
|
||||
@@ -1471,16 +1552,22 @@ and can be used to track future message acks/naks.</p></div>
|
||||
onResponse -- A closure of the form funct(packet), that will be
|
||||
called when a response packet arrives (or the transaction
|
||||
is NAKed due to non receipt)
|
||||
channelIndex - channel number to use
|
||||
|
||||
Returns the sent packet. The id field will be populated in this packet
|
||||
and can be used to track future message acks/naks.
|
||||
"""
|
||||
if hopLimit is None:
|
||||
hopLimit = self.defaultHopLimit
|
||||
|
||||
if getattr(data, "SerializeToString", None):
|
||||
logging.debug(f"Serializing protobuf as data: {stripnl(data)}")
|
||||
data = data.SerializeToString()
|
||||
|
||||
logging.debug(f"len(data): {len(data)}")
|
||||
logging.debug(f"mesh_pb2.Constants.DATA_PAYLOAD_LEN: {mesh_pb2.Constants.DATA_PAYLOAD_LEN}")
|
||||
if len(data) > mesh_pb2.Constants.DATA_PAYLOAD_LEN:
|
||||
Exception("Data payload too big")
|
||||
raise Exception("Data payload too big")
|
||||
|
||||
if portNum == portnums_pb2.PortNum.UNKNOWN_APP: # we are now more strict wrt port numbers
|
||||
our_exit("Warning: A non-zero port number must be specified")
|
||||
@@ -1528,16 +1615,20 @@ can be used to track future message acks/naks.</p></div>
|
||||
p = mesh_pb2.Position()
|
||||
if latitude != 0.0:
|
||||
p.latitude_i = int(latitude / 1e-7)
|
||||
logging.debug(f'p.latitude_i:{p.latitude_i}')
|
||||
|
||||
if longitude != 0.0:
|
||||
p.longitude_i = int(longitude / 1e-7)
|
||||
logging.debug(f'p.longitude_i:{p.longitude_i}')
|
||||
|
||||
if altitude != 0:
|
||||
p.altitude = int(altitude)
|
||||
logging.debug(f'p.altitude:{p.altitude}')
|
||||
|
||||
if timeSec == 0:
|
||||
timeSec = time.time() # returns unix timestamp in seconds
|
||||
p.time = int(timeSec)
|
||||
logging.debug(f'p.time:{p.time}')
|
||||
|
||||
return self.sendData(p, destinationId,
|
||||
portNum=portnums_pb2.PortNum.POSITION_APP,
|
||||
@@ -1546,7 +1637,7 @@ can be used to track future message acks/naks.</p></div>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.mesh_interface.MeshInterface.sendText"><code class="name flex">
|
||||
<span>def <span class="ident">sendText</span></span>(<span>self, text: ~AnyStr, destinationId='^all', wantAck=False, wantResponse=False, hopLimit=3, onResponse=None, channelIndex=0)</span>
|
||||
<span>def <span class="ident">sendText</span></span>(<span>self, text: ~AnyStr, destinationId='^all', wantAck=False, wantResponse=False, hopLimit=None, onResponse=None, channelIndex=0)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Send a utf8 string to some other node, if the node has a display it
|
||||
@@ -1572,7 +1663,7 @@ and can be used to track future message acks/naks.</p></div>
|
||||
destinationId=BROADCAST_ADDR,
|
||||
wantAck=False,
|
||||
wantResponse=False,
|
||||
hopLimit=defaultHopLimit,
|
||||
hopLimit=None,
|
||||
onResponse=None,
|
||||
channelIndex=0):
|
||||
"""Send a utf8 string to some other node, if the node has a display it
|
||||
@@ -1594,6 +1685,9 @@ and can be used to track future message acks/naks.</p></div>
|
||||
Returns the sent packet. The id field will be populated in this packet
|
||||
and can be used to track future message acks/naks.
|
||||
"""
|
||||
if hopLimit is None:
|
||||
hopLimit = self.defaultHopLimit
|
||||
|
||||
return self.sendData(text.encode("utf-8"), destinationId,
|
||||
portNum=portnums_pb2.PortNum.TEXT_MESSAGE_APP,
|
||||
wantAck=wantAck,
|
||||
@@ -1653,6 +1747,7 @@ and can be used to track future message acks/naks.</p></div>
|
||||
|
||||
rows = []
|
||||
if self.nodes:
|
||||
logging.debug(f'self.nodes:{self.nodes}')
|
||||
for node in self.nodes.values():
|
||||
if not includeSelf and node['num'] == self.localNode.nodeNum:
|
||||
continue
|
||||
|
||||
+134
-7195
File diff suppressed because it is too large.
Load diff
@@ -125,580 +125,35 @@ DESCRIPTOR._options = None
|
||||
<dl>
|
||||
<dt id="meshtastic.mqtt_pb2.ServiceEnvelope"><code class="flex name class">
|
||||
<span>class <span class="ident">ServiceEnvelope</span></span>
|
||||
<span>(</span><span>**kwargs)</span>
|
||||
<span>(</span><span>*args, **kwargs)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Abstract base class for protocol messages.</p>
|
||||
<p>Protocol message classes are almost always generated by the protocol
|
||||
compiler.
|
||||
These generated types subclass Message and implement the methods
|
||||
shown below.</p></div>
|
||||
<div class="desc"><p>A ProtocolMessage</p></div>
|
||||
<h3>Ancestors</h3>
|
||||
<ul class="hlist">
|
||||
<li>google.protobuf.pyext._message.CMessage</li>
|
||||
<li>google.protobuf.message.Message</li>
|
||||
</ul>
|
||||
<h3>Class variables</h3>
|
||||
<dl>
|
||||
<dt id="meshtastic.mqtt_pb2.ServiceEnvelope.CHANNEL_ID_FIELD_NUMBER"><code class="name">var <span class="ident">CHANNEL_ID_FIELD_NUMBER</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.mqtt_pb2.ServiceEnvelope.DESCRIPTOR"><code class="name">var <span class="ident">DESCRIPTOR</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.mqtt_pb2.ServiceEnvelope.GATEWAY_ID_FIELD_NUMBER"><code class="name">var <span class="ident">GATEWAY_ID_FIELD_NUMBER</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.mqtt_pb2.ServiceEnvelope.PACKET_FIELD_NUMBER"><code class="name">var <span class="ident">PACKET_FIELD_NUMBER</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>Static methods</h3>
|
||||
<dl>
|
||||
<dt id="meshtastic.mqtt_pb2.ServiceEnvelope.FromString"><code class="name flex">
|
||||
<span>def <span class="ident">FromString</span></span>(<span>s)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def FromString(s):
|
||||
message = cls()
|
||||
message.MergeFromString(s)
|
||||
return message</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.mqtt_pb2.ServiceEnvelope.RegisterExtension"><code class="name flex">
|
||||
<span>def <span class="ident">RegisterExtension</span></span>(<span>extension_handle)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def RegisterExtension(extension_handle):
|
||||
extension_handle.containing_type = cls.DESCRIPTOR
|
||||
# TODO(amauryfa): Use cls.MESSAGE_FACTORY.pool when available.
|
||||
# pylint: disable=protected-access
|
||||
cls.DESCRIPTOR.file.pool._AddExtensionDescriptor(extension_handle)
|
||||
_AttachFieldHelpers(cls, extension_handle)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>Instance variables</h3>
|
||||
<dl>
|
||||
<dt id="meshtastic.mqtt_pb2.ServiceEnvelope.channel_id"><code class="name">var <span class="ident">channel_id</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Getter for channel_id.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def getter(self):
|
||||
# TODO(protobuf-team): This may be broken since there may not be
|
||||
# default_value. Combine with has_default_value somehow.
|
||||
return self._fields.get(field, default_value)</code></pre>
|
||||
</details>
|
||||
<div class="desc"><p>Field ServiceEnvelope.channel_id</p></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.mqtt_pb2.ServiceEnvelope.gateway_id"><code class="name">var <span class="ident">gateway_id</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Getter for gateway_id.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def getter(self):
|
||||
# TODO(protobuf-team): This may be broken since there may not be
|
||||
# default_value. Combine with has_default_value somehow.
|
||||
return self._fields.get(field, default_value)</code></pre>
|
||||
</details>
|
||||
<div class="desc"><p>Field ServiceEnvelope.gateway_id</p></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.mqtt_pb2.ServiceEnvelope.packet"><code class="name">var <span class="ident">packet</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Getter for packet.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def getter(self):
|
||||
field_value = self._fields.get(field)
|
||||
if field_value is None:
|
||||
# Construct a new object to represent this field.
|
||||
field_value = field._default_constructor(self)
|
||||
|
||||
# Atomically check if another thread has preempted us and, if not, swap
|
||||
# in the new object we just created. If someone has preempted us, we
|
||||
# take that object and discard ours.
|
||||
# WARNING: We are relying on setdefault() being atomic. This is true
|
||||
# in CPython but we haven't investigated others. This warning appears
|
||||
# in several other locations in this file.
|
||||
field_value = self._fields.setdefault(field, field_value)
|
||||
return field_value</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>Methods</h3>
|
||||
<dl>
|
||||
<dt id="meshtastic.mqtt_pb2.ServiceEnvelope.ByteSize"><code class="name flex">
|
||||
<span>def <span class="ident">ByteSize</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def ByteSize(self):
|
||||
if not self._cached_byte_size_dirty:
|
||||
return self._cached_byte_size
|
||||
|
||||
size = 0
|
||||
descriptor = self.DESCRIPTOR
|
||||
if descriptor.GetOptions().map_entry:
|
||||
# Fields of map entry should always be serialized.
|
||||
size = descriptor.fields_by_name['key']._sizer(self.key)
|
||||
size += descriptor.fields_by_name['value']._sizer(self.value)
|
||||
else:
|
||||
for field_descriptor, field_value in self.ListFields():
|
||||
size += field_descriptor._sizer(field_value)
|
||||
for tag_bytes, value_bytes in self._unknown_fields:
|
||||
size += len(tag_bytes) + len(value_bytes)
|
||||
|
||||
self._cached_byte_size = size
|
||||
self._cached_byte_size_dirty = False
|
||||
self._listener_for_children.dirty = False
|
||||
return size</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.mqtt_pb2.ServiceEnvelope.Clear"><code class="name flex">
|
||||
<span>def <span class="ident">Clear</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def _Clear(self):
|
||||
# Clear fields.
|
||||
self._fields = {}
|
||||
self._unknown_fields = ()
|
||||
# pylint: disable=protected-access
|
||||
if self._unknown_field_set is not None:
|
||||
self._unknown_field_set._clear()
|
||||
self._unknown_field_set = None
|
||||
|
||||
self._oneofs = {}
|
||||
self._Modified()</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.mqtt_pb2.ServiceEnvelope.ClearField"><code class="name flex">
|
||||
<span>def <span class="ident">ClearField</span></span>(<span>self, field_name)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def ClearField(self, field_name):
|
||||
try:
|
||||
field = message_descriptor.fields_by_name[field_name]
|
||||
except KeyError:
|
||||
try:
|
||||
field = message_descriptor.oneofs_by_name[field_name]
|
||||
if field in self._oneofs:
|
||||
field = self._oneofs[field]
|
||||
else:
|
||||
return
|
||||
except KeyError:
|
||||
raise ValueError('Protocol message %s has no "%s" field.' %
|
||||
(message_descriptor.name, field_name))
|
||||
|
||||
if field in self._fields:
|
||||
# To match the C++ implementation, we need to invalidate iterators
|
||||
# for map fields when ClearField() happens.
|
||||
if hasattr(self._fields[field], 'InvalidateIterators'):
|
||||
self._fields[field].InvalidateIterators()
|
||||
|
||||
# Note: If the field is a sub-message, its listener will still point
|
||||
# at us. That's fine, because the worst than can happen is that it
|
||||
# will call _Modified() and invalidate our byte size. Big deal.
|
||||
del self._fields[field]
|
||||
|
||||
if self._oneofs.get(field.containing_oneof, None) is field:
|
||||
del self._oneofs[field.containing_oneof]
|
||||
|
||||
# Always call _Modified() -- even if nothing was changed, this is
|
||||
# a mutating method, and thus calling it should cause the field to become
|
||||
# present in the parent message.
|
||||
self._Modified()</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.mqtt_pb2.ServiceEnvelope.DiscardUnknownFields"><code class="name flex">
|
||||
<span>def <span class="ident">DiscardUnknownFields</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def _DiscardUnknownFields(self):
|
||||
self._unknown_fields = []
|
||||
self._unknown_field_set = None # pylint: disable=protected-access
|
||||
for field, value in self.ListFields():
|
||||
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
|
||||
if _IsMapField(field):
|
||||
if _IsMessageMapField(field):
|
||||
for key in value:
|
||||
value[key].DiscardUnknownFields()
|
||||
elif field.label == _FieldDescriptor.LABEL_REPEATED:
|
||||
for sub_message in value:
|
||||
sub_message.DiscardUnknownFields()
|
||||
else:
|
||||
value.DiscardUnknownFields()</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.mqtt_pb2.ServiceEnvelope.FindInitializationErrors"><code class="name flex">
|
||||
<span>def <span class="ident">FindInitializationErrors</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Finds required fields which are not initialized.</p>
|
||||
<h2 id="returns">Returns</h2>
|
||||
<p>A list of strings.
|
||||
Each string is a path to an uninitialized field from
|
||||
the top-level message, e.g. "foo.bar[5].baz".</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def FindInitializationErrors(self):
|
||||
"""Finds required fields which are not initialized.
|
||||
|
||||
Returns:
|
||||
A list of strings. Each string is a path to an uninitialized field from
|
||||
the top-level message, e.g. "foo.bar[5].baz".
|
||||
"""
|
||||
|
||||
errors = [] # simplify things
|
||||
|
||||
for field in required_fields:
|
||||
if not self.HasField(field.name):
|
||||
errors.append(field.name)
|
||||
|
||||
for field, value in self.ListFields():
|
||||
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
|
||||
if field.is_extension:
|
||||
name = '(%s)' % field.full_name
|
||||
else:
|
||||
name = field.name
|
||||
|
||||
if _IsMapField(field):
|
||||
if _IsMessageMapField(field):
|
||||
for key in value:
|
||||
element = value[key]
|
||||
prefix = '%s[%s].' % (name, key)
|
||||
sub_errors = element.FindInitializationErrors()
|
||||
errors += [prefix + error for error in sub_errors]
|
||||
else:
|
||||
# ScalarMaps can't have any initialization errors.
|
||||
pass
|
||||
elif field.label == _FieldDescriptor.LABEL_REPEATED:
|
||||
for i in range(len(value)):
|
||||
element = value[i]
|
||||
prefix = '%s[%d].' % (name, i)
|
||||
sub_errors = element.FindInitializationErrors()
|
||||
errors += [prefix + error for error in sub_errors]
|
||||
else:
|
||||
prefix = name + '.'
|
||||
sub_errors = value.FindInitializationErrors()
|
||||
errors += [prefix + error for error in sub_errors]
|
||||
|
||||
return errors</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.mqtt_pb2.ServiceEnvelope.HasField"><code class="name flex">
|
||||
<span>def <span class="ident">HasField</span></span>(<span>self, field_name)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def HasField(self, field_name):
|
||||
try:
|
||||
field = hassable_fields[field_name]
|
||||
except KeyError:
|
||||
raise ValueError(error_msg % (message_descriptor.full_name, field_name))
|
||||
|
||||
if isinstance(field, descriptor_mod.OneofDescriptor):
|
||||
try:
|
||||
return HasField(self, self._oneofs[field].name)
|
||||
except KeyError:
|
||||
return False
|
||||
else:
|
||||
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
|
||||
value = self._fields.get(field)
|
||||
return value is not None and value._is_present_in_parent
|
||||
else:
|
||||
return field in self._fields</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.mqtt_pb2.ServiceEnvelope.IsInitialized"><code class="name flex">
|
||||
<span>def <span class="ident">IsInitialized</span></span>(<span>self, errors=None)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Checks if all required fields of a message are set.</p>
|
||||
<h2 id="args">Args</h2>
|
||||
<dl>
|
||||
<dt><strong><code>errors</code></strong></dt>
|
||||
<dd>A list which, if provided, will be populated with the field
|
||||
paths of all missing required fields.</dd>
|
||||
</dl>
|
||||
<h2 id="returns">Returns</h2>
|
||||
<p>True iff the specified message has all required fields set.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def IsInitialized(self, errors=None):
|
||||
"""Checks if all required fields of a message are set.
|
||||
|
||||
Args:
|
||||
errors: A list which, if provided, will be populated with the field
|
||||
paths of all missing required fields.
|
||||
|
||||
Returns:
|
||||
True iff the specified message has all required fields set.
|
||||
"""
|
||||
|
||||
# Performance is critical so we avoid HasField() and ListFields().
|
||||
|
||||
for field in required_fields:
|
||||
if (field not in self._fields or
|
||||
(field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE and
|
||||
not self._fields[field]._is_present_in_parent)):
|
||||
if errors is not None:
|
||||
errors.extend(self.FindInitializationErrors())
|
||||
return False
|
||||
|
||||
for field, value in list(self._fields.items()): # dict can change size!
|
||||
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
|
||||
if field.label == _FieldDescriptor.LABEL_REPEATED:
|
||||
if (field.message_type.has_options and
|
||||
field.message_type.GetOptions().map_entry):
|
||||
continue
|
||||
for element in value:
|
||||
if not element.IsInitialized():
|
||||
if errors is not None:
|
||||
errors.extend(self.FindInitializationErrors())
|
||||
return False
|
||||
elif value._is_present_in_parent and not value.IsInitialized():
|
||||
if errors is not None:
|
||||
errors.extend(self.FindInitializationErrors())
|
||||
return False
|
||||
|
||||
return True</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.mqtt_pb2.ServiceEnvelope.ListFields"><code class="name flex">
|
||||
<span>def <span class="ident">ListFields</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def ListFields(self):
|
||||
all_fields = [item for item in self._fields.items() if _IsPresent(item)]
|
||||
all_fields.sort(key = lambda item: item[0].number)
|
||||
return all_fields</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.mqtt_pb2.ServiceEnvelope.MergeFrom"><code class="name flex">
|
||||
<span>def <span class="ident">MergeFrom</span></span>(<span>self, msg)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def MergeFrom(self, msg):
|
||||
if not isinstance(msg, cls):
|
||||
raise TypeError(
|
||||
'Parameter to MergeFrom() must be instance of same class: '
|
||||
'expected %s got %s.' % (_FullyQualifiedClassName(cls),
|
||||
_FullyQualifiedClassName(msg.__class__)))
|
||||
|
||||
assert msg is not self
|
||||
self._Modified()
|
||||
|
||||
fields = self._fields
|
||||
|
||||
for field, value in msg._fields.items():
|
||||
if field.label == LABEL_REPEATED:
|
||||
field_value = fields.get(field)
|
||||
if field_value is None:
|
||||
# Construct a new object to represent this field.
|
||||
field_value = field._default_constructor(self)
|
||||
fields[field] = field_value
|
||||
field_value.MergeFrom(value)
|
||||
elif field.cpp_type == CPPTYPE_MESSAGE:
|
||||
if value._is_present_in_parent:
|
||||
field_value = fields.get(field)
|
||||
if field_value is None:
|
||||
# Construct a new object to represent this field.
|
||||
field_value = field._default_constructor(self)
|
||||
fields[field] = field_value
|
||||
field_value.MergeFrom(value)
|
||||
else:
|
||||
self._fields[field] = value
|
||||
if field.containing_oneof:
|
||||
self._UpdateOneofState(field)
|
||||
|
||||
if msg._unknown_fields:
|
||||
if not self._unknown_fields:
|
||||
self._unknown_fields = []
|
||||
self._unknown_fields.extend(msg._unknown_fields)
|
||||
# pylint: disable=protected-access
|
||||
if self._unknown_field_set is None:
|
||||
self._unknown_field_set = containers.UnknownFieldSet()
|
||||
self._unknown_field_set._extend(msg._unknown_field_set)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.mqtt_pb2.ServiceEnvelope.MergeFromString"><code class="name flex">
|
||||
<span>def <span class="ident">MergeFromString</span></span>(<span>self, serialized)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def MergeFromString(self, serialized):
|
||||
serialized = memoryview(serialized)
|
||||
length = len(serialized)
|
||||
try:
|
||||
if self._InternalParse(serialized, 0, length) != length:
|
||||
# The only reason _InternalParse would return early is if it
|
||||
# encountered an end-group tag.
|
||||
raise message_mod.DecodeError('Unexpected end-group tag.')
|
||||
except (IndexError, TypeError):
|
||||
# Now ord(buf[p:p+1]) == ord('') gets TypeError.
|
||||
raise message_mod.DecodeError('Truncated message.')
|
||||
except struct.error as e:
|
||||
raise message_mod.DecodeError(e)
|
||||
return length # Return this for legacy reasons.</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.mqtt_pb2.ServiceEnvelope.SerializePartialToString"><code class="name flex">
|
||||
<span>def <span class="ident">SerializePartialToString</span></span>(<span>self, **kwargs)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def SerializePartialToString(self, **kwargs):
|
||||
out = BytesIO()
|
||||
self._InternalSerialize(out.write, **kwargs)
|
||||
return out.getvalue()</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.mqtt_pb2.ServiceEnvelope.SerializeToString"><code class="name flex">
|
||||
<span>def <span class="ident">SerializeToString</span></span>(<span>self, **kwargs)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def SerializeToString(self, **kwargs):
|
||||
# Check if the message has all of its required fields set.
|
||||
if not self.IsInitialized():
|
||||
raise message_mod.EncodeError(
|
||||
'Message %s is missing required fields: %s' % (
|
||||
self.DESCRIPTOR.full_name, ','.join(self.FindInitializationErrors())))
|
||||
return self.SerializePartialToString(**kwargs)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.mqtt_pb2.ServiceEnvelope.SetInParent"><code class="name flex">
|
||||
<span>def <span class="ident">SetInParent</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Sets the _cached_byte_size_dirty bit to true,
|
||||
and propagates this to our listener iff this was a state change.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def Modified(self):
|
||||
"""Sets the _cached_byte_size_dirty bit to true,
|
||||
and propagates this to our listener iff this was a state change.
|
||||
"""
|
||||
|
||||
# Note: Some callers check _cached_byte_size_dirty before calling
|
||||
# _Modified() as an extra optimization. So, if this method is ever
|
||||
# changed such that it does stuff even when _cached_byte_size_dirty is
|
||||
# already true, the callers need to be updated.
|
||||
if not self._cached_byte_size_dirty:
|
||||
self._cached_byte_size_dirty = True
|
||||
self._listener_for_children.dirty = True
|
||||
self._is_present_in_parent = True
|
||||
self._listener.Modified()</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.mqtt_pb2.ServiceEnvelope.UnknownFields"><code class="name flex">
|
||||
<span>def <span class="ident">UnknownFields</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def _UnknownFields(self):
|
||||
if self._unknown_field_set is None: # pylint: disable=protected-access
|
||||
# pylint: disable=protected-access
|
||||
self._unknown_field_set = containers.UnknownFieldSet()
|
||||
return self._unknown_field_set # pylint: disable=protected-access</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.mqtt_pb2.ServiceEnvelope.WhichOneof"><code class="name flex">
|
||||
<span>def <span class="ident">WhichOneof</span></span>(<span>self, oneof_name)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Returns the name of the currently set field inside a oneof, or None.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def WhichOneof(self, oneof_name):
|
||||
"""Returns the name of the currently set field inside a oneof, or None."""
|
||||
try:
|
||||
field = message_descriptor.oneofs_by_name[oneof_name]
|
||||
except KeyError:
|
||||
raise ValueError(
|
||||
'Protocol message has no oneof "%s" field.' % oneof_name)
|
||||
|
||||
nested_field = self._oneofs.get(field, None)
|
||||
if nested_field is not None and self.HasField(nested_field.name):
|
||||
return nested_field.name
|
||||
else:
|
||||
return None</code></pre>
|
||||
</details>
|
||||
<div class="desc"><p>Field ServiceEnvelope.packet</p></div>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
@@ -721,27 +176,7 @@ and propagates this to our listener iff this was a state change.</p></div>
|
||||
<li>
|
||||
<h4><code><a title="meshtastic.mqtt_pb2.ServiceEnvelope" href="#meshtastic.mqtt_pb2.ServiceEnvelope">ServiceEnvelope</a></code></h4>
|
||||
<ul class="">
|
||||
<li><code><a title="meshtastic.mqtt_pb2.ServiceEnvelope.ByteSize" href="#meshtastic.mqtt_pb2.ServiceEnvelope.ByteSize">ByteSize</a></code></li>
|
||||
<li><code><a title="meshtastic.mqtt_pb2.ServiceEnvelope.CHANNEL_ID_FIELD_NUMBER" href="#meshtastic.mqtt_pb2.ServiceEnvelope.CHANNEL_ID_FIELD_NUMBER">CHANNEL_ID_FIELD_NUMBER</a></code></li>
|
||||
<li><code><a title="meshtastic.mqtt_pb2.ServiceEnvelope.Clear" href="#meshtastic.mqtt_pb2.ServiceEnvelope.Clear">Clear</a></code></li>
|
||||
<li><code><a title="meshtastic.mqtt_pb2.ServiceEnvelope.ClearField" href="#meshtastic.mqtt_pb2.ServiceEnvelope.ClearField">ClearField</a></code></li>
|
||||
<li><code><a title="meshtastic.mqtt_pb2.ServiceEnvelope.DESCRIPTOR" href="#meshtastic.mqtt_pb2.ServiceEnvelope.DESCRIPTOR">DESCRIPTOR</a></code></li>
|
||||
<li><code><a title="meshtastic.mqtt_pb2.ServiceEnvelope.DiscardUnknownFields" href="#meshtastic.mqtt_pb2.ServiceEnvelope.DiscardUnknownFields">DiscardUnknownFields</a></code></li>
|
||||
<li><code><a title="meshtastic.mqtt_pb2.ServiceEnvelope.FindInitializationErrors" href="#meshtastic.mqtt_pb2.ServiceEnvelope.FindInitializationErrors">FindInitializationErrors</a></code></li>
|
||||
<li><code><a title="meshtastic.mqtt_pb2.ServiceEnvelope.FromString" href="#meshtastic.mqtt_pb2.ServiceEnvelope.FromString">FromString</a></code></li>
|
||||
<li><code><a title="meshtastic.mqtt_pb2.ServiceEnvelope.GATEWAY_ID_FIELD_NUMBER" href="#meshtastic.mqtt_pb2.ServiceEnvelope.GATEWAY_ID_FIELD_NUMBER">GATEWAY_ID_FIELD_NUMBER</a></code></li>
|
||||
<li><code><a title="meshtastic.mqtt_pb2.ServiceEnvelope.HasField" href="#meshtastic.mqtt_pb2.ServiceEnvelope.HasField">HasField</a></code></li>
|
||||
<li><code><a title="meshtastic.mqtt_pb2.ServiceEnvelope.IsInitialized" href="#meshtastic.mqtt_pb2.ServiceEnvelope.IsInitialized">IsInitialized</a></code></li>
|
||||
<li><code><a title="meshtastic.mqtt_pb2.ServiceEnvelope.ListFields" href="#meshtastic.mqtt_pb2.ServiceEnvelope.ListFields">ListFields</a></code></li>
|
||||
<li><code><a title="meshtastic.mqtt_pb2.ServiceEnvelope.MergeFrom" href="#meshtastic.mqtt_pb2.ServiceEnvelope.MergeFrom">MergeFrom</a></code></li>
|
||||
<li><code><a title="meshtastic.mqtt_pb2.ServiceEnvelope.MergeFromString" href="#meshtastic.mqtt_pb2.ServiceEnvelope.MergeFromString">MergeFromString</a></code></li>
|
||||
<li><code><a title="meshtastic.mqtt_pb2.ServiceEnvelope.PACKET_FIELD_NUMBER" href="#meshtastic.mqtt_pb2.ServiceEnvelope.PACKET_FIELD_NUMBER">PACKET_FIELD_NUMBER</a></code></li>
|
||||
<li><code><a title="meshtastic.mqtt_pb2.ServiceEnvelope.RegisterExtension" href="#meshtastic.mqtt_pb2.ServiceEnvelope.RegisterExtension">RegisterExtension</a></code></li>
|
||||
<li><code><a title="meshtastic.mqtt_pb2.ServiceEnvelope.SerializePartialToString" href="#meshtastic.mqtt_pb2.ServiceEnvelope.SerializePartialToString">SerializePartialToString</a></code></li>
|
||||
<li><code><a title="meshtastic.mqtt_pb2.ServiceEnvelope.SerializeToString" href="#meshtastic.mqtt_pb2.ServiceEnvelope.SerializeToString">SerializeToString</a></code></li>
|
||||
<li><code><a title="meshtastic.mqtt_pb2.ServiceEnvelope.SetInParent" href="#meshtastic.mqtt_pb2.ServiceEnvelope.SetInParent">SetInParent</a></code></li>
|
||||
<li><code><a title="meshtastic.mqtt_pb2.ServiceEnvelope.UnknownFields" href="#meshtastic.mqtt_pb2.ServiceEnvelope.UnknownFields">UnknownFields</a></code></li>
|
||||
<li><code><a title="meshtastic.mqtt_pb2.ServiceEnvelope.WhichOneof" href="#meshtastic.mqtt_pb2.ServiceEnvelope.WhichOneof">WhichOneof</a></code></li>
|
||||
<li><code><a title="meshtastic.mqtt_pb2.ServiceEnvelope.channel_id" href="#meshtastic.mqtt_pb2.ServiceEnvelope.channel_id">channel_id</a></code></li>
|
||||
<li><code><a title="meshtastic.mqtt_pb2.ServiceEnvelope.gateway_id" href="#meshtastic.mqtt_pb2.ServiceEnvelope.gateway_id">gateway_id</a></code></li>
|
||||
<li><code><a title="meshtastic.mqtt_pb2.ServiceEnvelope.packet" href="#meshtastic.mqtt_pb2.ServiceEnvelope.packet">packet</a></code></li>
|
||||
|
||||
+293
-108
@@ -37,26 +37,31 @@ from . import portnums_pb2, apponly_pb2, admin_pb2, channel_pb2
|
||||
from .util import pskToString, stripnl, Timeout, our_exit, fromPSK
|
||||
|
||||
|
||||
|
||||
|
||||
class Node:
|
||||
"""A model of a (local or remote) node in the mesh
|
||||
|
||||
Includes methods for radioConfig and channels
|
||||
"""
|
||||
|
||||
def __init__(self, iface, nodeNum):
|
||||
def __init__(self, iface, nodeNum, noProto=False):
|
||||
"""Constructor"""
|
||||
self.iface = iface
|
||||
self.nodeNum = nodeNum
|
||||
self.radioConfig = None
|
||||
self.channels = None
|
||||
self._timeout = Timeout(maxSecs=60)
|
||||
self._timeout = Timeout(maxSecs=300)
|
||||
self.partialChannels = None
|
||||
self.noProto = noProto
|
||||
|
||||
def showChannels(self):
|
||||
"""Show human readable description of our channels."""
|
||||
print("Channels:")
|
||||
if self.channels:
|
||||
logging.debug(f'self.channels:{self.channels}')
|
||||
for c in self.channels:
|
||||
#print('c.settings.psk:', c.settings.psk)
|
||||
cStr = stripnl(MessageToJson(c.settings))
|
||||
# only show if there is no psk (meaning disabled channel)
|
||||
if c.settings.psk:
|
||||
@@ -77,6 +82,7 @@ class Node:
|
||||
|
||||
def requestConfig(self):
|
||||
"""Send regular MeshPackets to ask for settings and channels."""
|
||||
logging.debug(f"requestConfig for nodeNum:{self.nodeNum}")
|
||||
self.radioConfig = None
|
||||
self.channels = None
|
||||
self.partialChannels = [] # We keep our channels in a temp array until finished
|
||||
@@ -113,6 +119,16 @@ class Node:
|
||||
self._sendAdmin(p, adminIndex=adminIndex)
|
||||
logging.debug(f"Wrote channel {channelIndex}")
|
||||
|
||||
def getChannelByChannelIndex(self, channelIndex):
|
||||
"""Get channel by channelIndex
|
||||
channelIndex: number, typically 0-7; based on max number channels
|
||||
returns: None if there is no channel found
|
||||
"""
|
||||
ch = None
|
||||
if self.channels and 0 <= channelIndex < len(self.channels):
|
||||
ch = self.channels[channelIndex]
|
||||
return ch
|
||||
|
||||
def deleteChannel(self, channelIndex):
|
||||
"""Delete the specifed channelIndex and shift other channels up"""
|
||||
ch = self.channels[channelIndex]
|
||||
@@ -135,7 +151,7 @@ class Node:
|
||||
# *moving* the admin channel index as we are writing
|
||||
if (self.iface.localNode == self) and index >= adminIndex:
|
||||
# We've now passed the old location for admin index
|
||||
# (and writen it), so we can start finding it by name again
|
||||
# (and written it), so we can start finding it by name again
|
||||
adminIndex = 0
|
||||
|
||||
def getChannelByName(self, name):
|
||||
@@ -162,6 +178,7 @@ class Node:
|
||||
|
||||
def setOwner(self, long_name=None, short_name=None, is_licensed=False, team=None):
|
||||
"""Set device owner name"""
|
||||
logging.debug(f"in setOwner nodeNum:{self.nodeNum}")
|
||||
nChars = 3
|
||||
minChars = 2
|
||||
if long_name is not None:
|
||||
@@ -191,6 +208,11 @@ class Node:
|
||||
if team is not None:
|
||||
p.set_owner.team = team
|
||||
|
||||
# Note: These debug lines are used in unit tests
|
||||
logging.debug(f'p.set_owner.long_name:{p.set_owner.long_name}:')
|
||||
logging.debug(f'p.set_owner.short_name:{p.set_owner.short_name}:')
|
||||
logging.debug(f'p.set_owner.is_licensed:{p.set_owner.is_licensed}')
|
||||
logging.debug(f'p.set_owner.team:{p.set_owner.team}')
|
||||
return self._sendAdmin(p)
|
||||
|
||||
def getURL(self, includeAll: bool = True):
|
||||
@@ -226,6 +248,7 @@ class Node:
|
||||
channelSet = apponly_pb2.ChannelSet()
|
||||
channelSet.ParseFromString(decodedURL)
|
||||
|
||||
|
||||
if len(channelSet.settings) == 0:
|
||||
our_exit("Warning: There were no settings.")
|
||||
|
||||
@@ -236,39 +259,51 @@ class Node:
|
||||
ch.index = i
|
||||
ch.settings.CopyFrom(chs)
|
||||
self.channels[ch.index] = ch
|
||||
logging.debug(f'Channel i:{i} ch:{ch}')
|
||||
self.writeChannel(ch.index)
|
||||
i = i + 1
|
||||
|
||||
|
||||
def onResponseRequestSettings(self, p):
|
||||
"""Handle the response packet for requesting settings _requestSettings()"""
|
||||
logging.debug(f'onResponseRequestSetting() p:{p}')
|
||||
errorFound = False
|
||||
if 'routing' in p["decoded"]:
|
||||
if p["decoded"]["routing"]["errorReason"] != "NONE":
|
||||
errorFound = True
|
||||
print(f'Error on response: {p["decoded"]["routing"]["errorReason"]}')
|
||||
if errorFound is False:
|
||||
self.radioConfig = p["decoded"]["admin"]["raw"].get_radio_response
|
||||
logging.debug(f'self.radioConfig:{self.radioConfig}')
|
||||
logging.debug("Received radio config, now fetching channels...")
|
||||
self._timeout.reset() # We made foreward progress
|
||||
self._requestChannel(0) # now start fetching channels
|
||||
|
||||
|
||||
def _requestSettings(self):
|
||||
"""Done with initial config messages, now send regular
|
||||
MeshPackets to ask for settings."""
|
||||
p = admin_pb2.AdminMessage()
|
||||
p.get_radio_request = True
|
||||
|
||||
def onResponse(p):
|
||||
"""A closure to handle the response packet"""
|
||||
errorFound = False
|
||||
if 'routing' in p["decoded"]:
|
||||
if p["decoded"]["routing"]["errorReason"] != "NONE":
|
||||
errorFound = True
|
||||
print(f'Error on response: {p["decoded"]["routing"]["errorReason"]}')
|
||||
if errorFound is False:
|
||||
self.radioConfig = p["decoded"]["admin"]["raw"].get_radio_response
|
||||
logging.debug("Received radio config, now fetching channels...")
|
||||
self._timeout.reset() # We made foreward progress
|
||||
self._requestChannel(0) # now start fetching channels
|
||||
|
||||
# Show progress message for super slow operations
|
||||
if self != self.iface.localNode:
|
||||
print("Requesting preferences from remote node (this could take a while)")
|
||||
print("Requesting preferences from remote node.")
|
||||
print("Be sure:")
|
||||
print(" 1. There is a SECONDARY channel named 'admin'.")
|
||||
print(" 2. The '--seturl' was used to configure.")
|
||||
print(" 3. All devices have the same modem config. (i.e., '--ch-longfast')")
|
||||
print(" 4. All devices have been rebooted after all of the above. (optional, but recommended)")
|
||||
print("Note: This could take a while (it requests remote channel configs, then writes config)")
|
||||
|
||||
return self._sendAdmin(p, wantResponse=True, onResponse=onResponse)
|
||||
return self._sendAdmin(p, wantResponse=True, onResponse=self.onResponseRequestSettings)
|
||||
|
||||
def exitSimulator(self):
|
||||
"""Tell a simulator node to exit (this message
|
||||
is ignored for other nodes)"""
|
||||
p = admin_pb2.AdminMessage()
|
||||
p.exit_simulator = True
|
||||
logging.debug('in exitSimulator()')
|
||||
|
||||
return self._sendAdmin(p)
|
||||
|
||||
@@ -302,6 +337,34 @@ class Node:
|
||||
self.channels.append(ch)
|
||||
index += 1
|
||||
|
||||
|
||||
def onResponseRequestChannel(self, p):
|
||||
"""Handle the response packet for requesting a channel _requestChannel()"""
|
||||
logging.debug(f'onResponseRequestChannel() p:{p}')
|
||||
c = p["decoded"]["admin"]["raw"].get_channel_response
|
||||
self.partialChannels.append(c)
|
||||
self._timeout.reset() # We made foreward progress
|
||||
logging.debug(f"Received channel {stripnl(c)}")
|
||||
index = c.index
|
||||
|
||||
# for stress testing, we can always download all channels
|
||||
fastChannelDownload = True
|
||||
|
||||
# Once we see a response that has NO settings, assume
|
||||
# we are at the end of channels and stop fetching
|
||||
quitEarly = (c.role == channel_pb2.Channel.Role.DISABLED) and fastChannelDownload
|
||||
|
||||
if quitEarly or index >= self.iface.myInfo.max_channels - 1:
|
||||
logging.debug("Finished downloading channels")
|
||||
|
||||
self.channels = self.partialChannels
|
||||
self._fixupChannels()
|
||||
|
||||
# FIXME, the following should only be called after we have settings and channels
|
||||
self.iface._connected() # Tell everyone else we are ready to go
|
||||
else:
|
||||
self._requestChannel(index + 1)
|
||||
|
||||
def _requestChannel(self, channelNum: int):
|
||||
"""Done with initial config messages, now send regular
|
||||
MeshPackets to ask for settings"""
|
||||
@@ -310,51 +373,32 @@ class Node:
|
||||
|
||||
# Show progress message for super slow operations
|
||||
if self != self.iface.localNode:
|
||||
logging.info(f"Requesting channel {channelNum} info from remote node (this could take a while)")
|
||||
print(f"Requesting channel {channelNum} info from remote node (this could take a while)")
|
||||
logging.debug(f"Requesting channel {channelNum} info from remote node (this could take a while)")
|
||||
else:
|
||||
logging.debug(f"Requesting channel {channelNum}")
|
||||
|
||||
def onResponse(p):
|
||||
"""A closure to handle the response packet for requesting a channel"""
|
||||
c = p["decoded"]["admin"]["raw"].get_channel_response
|
||||
self.partialChannels.append(c)
|
||||
self._timeout.reset() # We made foreward progress
|
||||
logging.debug(f"Received channel {stripnl(c)}")
|
||||
index = c.index
|
||||
return self._sendAdmin(p, wantResponse=True, onResponse=self.onResponseRequestChannel)
|
||||
|
||||
# for stress testing, we can always download all channels
|
||||
fastChannelDownload = True
|
||||
|
||||
# Once we see a response that has NO settings, assume
|
||||
# we are at the end of channels and stop fetching
|
||||
quitEarly = (c.role == channel_pb2.Channel.Role.DISABLED) and fastChannelDownload
|
||||
|
||||
if quitEarly or index >= self.iface.myInfo.max_channels - 1:
|
||||
logging.debug("Finished downloading channels")
|
||||
|
||||
self.channels = self.partialChannels
|
||||
self._fixupChannels()
|
||||
|
||||
# FIXME, the following should only be called after we have settings and channels
|
||||
self.iface._connected() # Tell everone else we are ready to go
|
||||
else:
|
||||
self._requestChannel(index + 1)
|
||||
|
||||
return self._sendAdmin(p, wantResponse=True, onResponse=onResponse)
|
||||
|
||||
# pylint: disable=R1710
|
||||
def _sendAdmin(self, p: admin_pb2.AdminMessage, wantResponse=False,
|
||||
onResponse=None, adminIndex=0):
|
||||
"""Send an admin message to the specified node (or the local node if destNodeNum is zero)"""
|
||||
|
||||
if adminIndex == 0: # unless a special channel index was used, we want to use the admin index
|
||||
adminIndex = self.iface.localNode._getAdminChannelIndex()
|
||||
if self.noProto:
|
||||
logging.warning(f"Not sending packet because protocol use is disabled by noProto")
|
||||
else:
|
||||
if adminIndex == 0: # unless a special channel index was used, we want to use the admin index
|
||||
adminIndex = self.iface.localNode._getAdminChannelIndex()
|
||||
logging.debug(f'adminIndex:{adminIndex}')
|
||||
|
||||
return self.iface.sendData(p, self.nodeNum,
|
||||
portNum=portnums_pb2.PortNum.ADMIN_APP,
|
||||
wantAck=True,
|
||||
wantResponse=wantResponse,
|
||||
onResponse=onResponse,
|
||||
channelIndex=adminIndex)</code></pre>
|
||||
return self.iface.sendData(p, self.nodeNum,
|
||||
portNum=portnums_pb2.PortNum.ADMIN_APP,
|
||||
wantAck=True,
|
||||
wantResponse=wantResponse,
|
||||
onResponse=onResponse,
|
||||
channelIndex=adminIndex)</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
@@ -368,7 +412,7 @@ class Node:
|
||||
<dl>
|
||||
<dt id="meshtastic.node.Node"><code class="flex name class">
|
||||
<span>class <span class="ident">Node</span></span>
|
||||
<span>(</span><span>iface, nodeNum)</span>
|
||||
<span>(</span><span>iface, nodeNum, noProto=False)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>A model of a (local or remote) node in the mesh</p>
|
||||
@@ -384,20 +428,23 @@ class Node:
|
||||
Includes methods for radioConfig and channels
|
||||
"""
|
||||
|
||||
def __init__(self, iface, nodeNum):
|
||||
def __init__(self, iface, nodeNum, noProto=False):
|
||||
"""Constructor"""
|
||||
self.iface = iface
|
||||
self.nodeNum = nodeNum
|
||||
self.radioConfig = None
|
||||
self.channels = None
|
||||
self._timeout = Timeout(maxSecs=60)
|
||||
self._timeout = Timeout(maxSecs=300)
|
||||
self.partialChannels = None
|
||||
self.noProto = noProto
|
||||
|
||||
def showChannels(self):
|
||||
"""Show human readable description of our channels."""
|
||||
print("Channels:")
|
||||
if self.channels:
|
||||
logging.debug(f'self.channels:{self.channels}')
|
||||
for c in self.channels:
|
||||
#print('c.settings.psk:', c.settings.psk)
|
||||
cStr = stripnl(MessageToJson(c.settings))
|
||||
# only show if there is no psk (meaning disabled channel)
|
||||
if c.settings.psk:
|
||||
@@ -418,6 +465,7 @@ class Node:
|
||||
|
||||
def requestConfig(self):
|
||||
"""Send regular MeshPackets to ask for settings and channels."""
|
||||
logging.debug(f"requestConfig for nodeNum:{self.nodeNum}")
|
||||
self.radioConfig = None
|
||||
self.channels = None
|
||||
self.partialChannels = [] # We keep our channels in a temp array until finished
|
||||
@@ -454,6 +502,16 @@ class Node:
|
||||
self._sendAdmin(p, adminIndex=adminIndex)
|
||||
logging.debug(f"Wrote channel {channelIndex}")
|
||||
|
||||
def getChannelByChannelIndex(self, channelIndex):
|
||||
"""Get channel by channelIndex
|
||||
channelIndex: number, typically 0-7; based on max number channels
|
||||
returns: None if there is no channel found
|
||||
"""
|
||||
ch = None
|
||||
if self.channels and 0 <= channelIndex < len(self.channels):
|
||||
ch = self.channels[channelIndex]
|
||||
return ch
|
||||
|
||||
def deleteChannel(self, channelIndex):
|
||||
"""Delete the specifed channelIndex and shift other channels up"""
|
||||
ch = self.channels[channelIndex]
|
||||
@@ -476,7 +534,7 @@ class Node:
|
||||
# *moving* the admin channel index as we are writing
|
||||
if (self.iface.localNode == self) and index >= adminIndex:
|
||||
# We've now passed the old location for admin index
|
||||
# (and writen it), so we can start finding it by name again
|
||||
# (and written it), so we can start finding it by name again
|
||||
adminIndex = 0
|
||||
|
||||
def getChannelByName(self, name):
|
||||
@@ -503,6 +561,7 @@ class Node:
|
||||
|
||||
def setOwner(self, long_name=None, short_name=None, is_licensed=False, team=None):
|
||||
"""Set device owner name"""
|
||||
logging.debug(f"in setOwner nodeNum:{self.nodeNum}")
|
||||
nChars = 3
|
||||
minChars = 2
|
||||
if long_name is not None:
|
||||
@@ -532,6 +591,11 @@ class Node:
|
||||
if team is not None:
|
||||
p.set_owner.team = team
|
||||
|
||||
# Note: These debug lines are used in unit tests
|
||||
logging.debug(f'p.set_owner.long_name:{p.set_owner.long_name}:')
|
||||
logging.debug(f'p.set_owner.short_name:{p.set_owner.short_name}:')
|
||||
logging.debug(f'p.set_owner.is_licensed:{p.set_owner.is_licensed}')
|
||||
logging.debug(f'p.set_owner.team:{p.set_owner.team}')
|
||||
return self._sendAdmin(p)
|
||||
|
||||
def getURL(self, includeAll: bool = True):
|
||||
@@ -567,6 +631,7 @@ class Node:
|
||||
channelSet = apponly_pb2.ChannelSet()
|
||||
channelSet.ParseFromString(decodedURL)
|
||||
|
||||
|
||||
if len(channelSet.settings) == 0:
|
||||
our_exit("Warning: There were no settings.")
|
||||
|
||||
@@ -577,39 +642,51 @@ class Node:
|
||||
ch.index = i
|
||||
ch.settings.CopyFrom(chs)
|
||||
self.channels[ch.index] = ch
|
||||
logging.debug(f'Channel i:{i} ch:{ch}')
|
||||
self.writeChannel(ch.index)
|
||||
i = i + 1
|
||||
|
||||
|
||||
def onResponseRequestSettings(self, p):
|
||||
"""Handle the response packet for requesting settings _requestSettings()"""
|
||||
logging.debug(f'onResponseRequestSetting() p:{p}')
|
||||
errorFound = False
|
||||
if 'routing' in p["decoded"]:
|
||||
if p["decoded"]["routing"]["errorReason"] != "NONE":
|
||||
errorFound = True
|
||||
print(f'Error on response: {p["decoded"]["routing"]["errorReason"]}')
|
||||
if errorFound is False:
|
||||
self.radioConfig = p["decoded"]["admin"]["raw"].get_radio_response
|
||||
logging.debug(f'self.radioConfig:{self.radioConfig}')
|
||||
logging.debug("Received radio config, now fetching channels...")
|
||||
self._timeout.reset() # We made foreward progress
|
||||
self._requestChannel(0) # now start fetching channels
|
||||
|
||||
|
||||
def _requestSettings(self):
|
||||
"""Done with initial config messages, now send regular
|
||||
MeshPackets to ask for settings."""
|
||||
p = admin_pb2.AdminMessage()
|
||||
p.get_radio_request = True
|
||||
|
||||
def onResponse(p):
|
||||
"""A closure to handle the response packet"""
|
||||
errorFound = False
|
||||
if 'routing' in p["decoded"]:
|
||||
if p["decoded"]["routing"]["errorReason"] != "NONE":
|
||||
errorFound = True
|
||||
print(f'Error on response: {p["decoded"]["routing"]["errorReason"]}')
|
||||
if errorFound is False:
|
||||
self.radioConfig = p["decoded"]["admin"]["raw"].get_radio_response
|
||||
logging.debug("Received radio config, now fetching channels...")
|
||||
self._timeout.reset() # We made foreward progress
|
||||
self._requestChannel(0) # now start fetching channels
|
||||
|
||||
# Show progress message for super slow operations
|
||||
if self != self.iface.localNode:
|
||||
print("Requesting preferences from remote node (this could take a while)")
|
||||
print("Requesting preferences from remote node.")
|
||||
print("Be sure:")
|
||||
print(" 1. There is a SECONDARY channel named 'admin'.")
|
||||
print(" 2. The '--seturl' was used to configure.")
|
||||
print(" 3. All devices have the same modem config. (i.e., '--ch-longfast')")
|
||||
print(" 4. All devices have been rebooted after all of the above. (optional, but recommended)")
|
||||
print("Note: This could take a while (it requests remote channel configs, then writes config)")
|
||||
|
||||
return self._sendAdmin(p, wantResponse=True, onResponse=onResponse)
|
||||
return self._sendAdmin(p, wantResponse=True, onResponse=self.onResponseRequestSettings)
|
||||
|
||||
def exitSimulator(self):
|
||||
"""Tell a simulator node to exit (this message
|
||||
is ignored for other nodes)"""
|
||||
p = admin_pb2.AdminMessage()
|
||||
p.exit_simulator = True
|
||||
logging.debug('in exitSimulator()')
|
||||
|
||||
return self._sendAdmin(p)
|
||||
|
||||
@@ -643,6 +720,34 @@ class Node:
|
||||
self.channels.append(ch)
|
||||
index += 1
|
||||
|
||||
|
||||
def onResponseRequestChannel(self, p):
|
||||
"""Handle the response packet for requesting a channel _requestChannel()"""
|
||||
logging.debug(f'onResponseRequestChannel() p:{p}')
|
||||
c = p["decoded"]["admin"]["raw"].get_channel_response
|
||||
self.partialChannels.append(c)
|
||||
self._timeout.reset() # We made foreward progress
|
||||
logging.debug(f"Received channel {stripnl(c)}")
|
||||
index = c.index
|
||||
|
||||
# for stress testing, we can always download all channels
|
||||
fastChannelDownload = True
|
||||
|
||||
# Once we see a response that has NO settings, assume
|
||||
# we are at the end of channels and stop fetching
|
||||
quitEarly = (c.role == channel_pb2.Channel.Role.DISABLED) and fastChannelDownload
|
||||
|
||||
if quitEarly or index >= self.iface.myInfo.max_channels - 1:
|
||||
logging.debug("Finished downloading channels")
|
||||
|
||||
self.channels = self.partialChannels
|
||||
self._fixupChannels()
|
||||
|
||||
# FIXME, the following should only be called after we have settings and channels
|
||||
self.iface._connected() # Tell everyone else we are ready to go
|
||||
else:
|
||||
self._requestChannel(index + 1)
|
||||
|
||||
def _requestChannel(self, channelNum: int):
|
||||
"""Done with initial config messages, now send regular
|
||||
MeshPackets to ask for settings"""
|
||||
@@ -651,51 +756,32 @@ class Node:
|
||||
|
||||
# Show progress message for super slow operations
|
||||
if self != self.iface.localNode:
|
||||
logging.info(f"Requesting channel {channelNum} info from remote node (this could take a while)")
|
||||
print(f"Requesting channel {channelNum} info from remote node (this could take a while)")
|
||||
logging.debug(f"Requesting channel {channelNum} info from remote node (this could take a while)")
|
||||
else:
|
||||
logging.debug(f"Requesting channel {channelNum}")
|
||||
|
||||
def onResponse(p):
|
||||
"""A closure to handle the response packet for requesting a channel"""
|
||||
c = p["decoded"]["admin"]["raw"].get_channel_response
|
||||
self.partialChannels.append(c)
|
||||
self._timeout.reset() # We made foreward progress
|
||||
logging.debug(f"Received channel {stripnl(c)}")
|
||||
index = c.index
|
||||
return self._sendAdmin(p, wantResponse=True, onResponse=self.onResponseRequestChannel)
|
||||
|
||||
# for stress testing, we can always download all channels
|
||||
fastChannelDownload = True
|
||||
|
||||
# Once we see a response that has NO settings, assume
|
||||
# we are at the end of channels and stop fetching
|
||||
quitEarly = (c.role == channel_pb2.Channel.Role.DISABLED) and fastChannelDownload
|
||||
|
||||
if quitEarly or index >= self.iface.myInfo.max_channels - 1:
|
||||
logging.debug("Finished downloading channels")
|
||||
|
||||
self.channels = self.partialChannels
|
||||
self._fixupChannels()
|
||||
|
||||
# FIXME, the following should only be called after we have settings and channels
|
||||
self.iface._connected() # Tell everone else we are ready to go
|
||||
else:
|
||||
self._requestChannel(index + 1)
|
||||
|
||||
return self._sendAdmin(p, wantResponse=True, onResponse=onResponse)
|
||||
|
||||
# pylint: disable=R1710
|
||||
def _sendAdmin(self, p: admin_pb2.AdminMessage, wantResponse=False,
|
||||
onResponse=None, adminIndex=0):
|
||||
"""Send an admin message to the specified node (or the local node if destNodeNum is zero)"""
|
||||
|
||||
if adminIndex == 0: # unless a special channel index was used, we want to use the admin index
|
||||
adminIndex = self.iface.localNode._getAdminChannelIndex()
|
||||
if self.noProto:
|
||||
logging.warning(f"Not sending packet because protocol use is disabled by noProto")
|
||||
else:
|
||||
if adminIndex == 0: # unless a special channel index was used, we want to use the admin index
|
||||
adminIndex = self.iface.localNode._getAdminChannelIndex()
|
||||
logging.debug(f'adminIndex:{adminIndex}')
|
||||
|
||||
return self.iface.sendData(p, self.nodeNum,
|
||||
portNum=portnums_pb2.PortNum.ADMIN_APP,
|
||||
wantAck=True,
|
||||
wantResponse=wantResponse,
|
||||
onResponse=onResponse,
|
||||
channelIndex=adminIndex)</code></pre>
|
||||
return self.iface.sendData(p, self.nodeNum,
|
||||
portNum=portnums_pb2.PortNum.ADMIN_APP,
|
||||
wantAck=True,
|
||||
wantResponse=wantResponse,
|
||||
onResponse=onResponse,
|
||||
channelIndex=adminIndex)</code></pre>
|
||||
</details>
|
||||
<h3>Methods</h3>
|
||||
<dl>
|
||||
@@ -730,7 +816,7 @@ class Node:
|
||||
# *moving* the admin channel index as we are writing
|
||||
if (self.iface.localNode == self) and index >= adminIndex:
|
||||
# We've now passed the old location for admin index
|
||||
# (and writen it), so we can start finding it by name again
|
||||
# (and written it), so we can start finding it by name again
|
||||
adminIndex = 0</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
@@ -749,10 +835,33 @@ is ignored for other nodes)</p></div>
|
||||
is ignored for other nodes)"""
|
||||
p = admin_pb2.AdminMessage()
|
||||
p.exit_simulator = True
|
||||
logging.debug('in exitSimulator()')
|
||||
|
||||
return self._sendAdmin(p)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.node.Node.getChannelByChannelIndex"><code class="name flex">
|
||||
<span>def <span class="ident">getChannelByChannelIndex</span></span>(<span>self, channelIndex)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Get channel by channelIndex
|
||||
channelIndex: number, typically 0-7; based on max number channels
|
||||
returns: None if there is no channel found</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def getChannelByChannelIndex(self, channelIndex):
|
||||
"""Get channel by channelIndex
|
||||
channelIndex: number, typically 0-7; based on max number channels
|
||||
returns: None if there is no channel found
|
||||
"""
|
||||
ch = None
|
||||
if self.channels and 0 <= channelIndex < len(self.channels):
|
||||
ch = self.channels[channelIndex]
|
||||
return ch</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.node.Node.getChannelByName"><code class="name flex">
|
||||
<span>def <span class="ident">getChannelByName</span></span>(<span>self, name)</span>
|
||||
</code></dt>
|
||||
@@ -809,6 +918,68 @@ is ignored for other nodes)</p></div>
|
||||
return f"https://www.meshtastic.org/d/#{s}".replace("=", "")</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.node.Node.onResponseRequestChannel"><code class="name flex">
|
||||
<span>def <span class="ident">onResponseRequestChannel</span></span>(<span>self, p)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Handle the response packet for requesting a channel _requestChannel()</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def onResponseRequestChannel(self, p):
|
||||
"""Handle the response packet for requesting a channel _requestChannel()"""
|
||||
logging.debug(f'onResponseRequestChannel() p:{p}')
|
||||
c = p["decoded"]["admin"]["raw"].get_channel_response
|
||||
self.partialChannels.append(c)
|
||||
self._timeout.reset() # We made foreward progress
|
||||
logging.debug(f"Received channel {stripnl(c)}")
|
||||
index = c.index
|
||||
|
||||
# for stress testing, we can always download all channels
|
||||
fastChannelDownload = True
|
||||
|
||||
# Once we see a response that has NO settings, assume
|
||||
# we are at the end of channels and stop fetching
|
||||
quitEarly = (c.role == channel_pb2.Channel.Role.DISABLED) and fastChannelDownload
|
||||
|
||||
if quitEarly or index >= self.iface.myInfo.max_channels - 1:
|
||||
logging.debug("Finished downloading channels")
|
||||
|
||||
self.channels = self.partialChannels
|
||||
self._fixupChannels()
|
||||
|
||||
# FIXME, the following should only be called after we have settings and channels
|
||||
self.iface._connected() # Tell everyone else we are ready to go
|
||||
else:
|
||||
self._requestChannel(index + 1)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.node.Node.onResponseRequestSettings"><code class="name flex">
|
||||
<span>def <span class="ident">onResponseRequestSettings</span></span>(<span>self, p)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Handle the response packet for requesting settings _requestSettings()</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def onResponseRequestSettings(self, p):
|
||||
"""Handle the response packet for requesting settings _requestSettings()"""
|
||||
logging.debug(f'onResponseRequestSetting() p:{p}')
|
||||
errorFound = False
|
||||
if 'routing' in p["decoded"]:
|
||||
if p["decoded"]["routing"]["errorReason"] != "NONE":
|
||||
errorFound = True
|
||||
print(f'Error on response: {p["decoded"]["routing"]["errorReason"]}')
|
||||
if errorFound is False:
|
||||
self.radioConfig = p["decoded"]["admin"]["raw"].get_radio_response
|
||||
logging.debug(f'self.radioConfig:{self.radioConfig}')
|
||||
logging.debug("Received radio config, now fetching channels...")
|
||||
self._timeout.reset() # We made foreward progress
|
||||
self._requestChannel(0) # now start fetching channels</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.node.Node.reboot"><code class="name flex">
|
||||
<span>def <span class="ident">reboot</span></span>(<span>self, secs: int = 10)</span>
|
||||
</code></dt>
|
||||
@@ -838,6 +1009,7 @@ is ignored for other nodes)</p></div>
|
||||
</summary>
|
||||
<pre><code class="python">def requestConfig(self):
|
||||
"""Send regular MeshPackets to ask for settings and channels."""
|
||||
logging.debug(f"requestConfig for nodeNum:{self.nodeNum}")
|
||||
self.radioConfig = None
|
||||
self.channels = None
|
||||
self.partialChannels = [] # We keep our channels in a temp array until finished
|
||||
@@ -856,6 +1028,7 @@ is ignored for other nodes)</p></div>
|
||||
</summary>
|
||||
<pre><code class="python">def setOwner(self, long_name=None, short_name=None, is_licensed=False, team=None):
|
||||
"""Set device owner name"""
|
||||
logging.debug(f"in setOwner nodeNum:{self.nodeNum}")
|
||||
nChars = 3
|
||||
minChars = 2
|
||||
if long_name is not None:
|
||||
@@ -885,6 +1058,11 @@ is ignored for other nodes)</p></div>
|
||||
if team is not None:
|
||||
p.set_owner.team = team
|
||||
|
||||
# Note: These debug lines are used in unit tests
|
||||
logging.debug(f'p.set_owner.long_name:{p.set_owner.long_name}:')
|
||||
logging.debug(f'p.set_owner.short_name:{p.set_owner.short_name}:')
|
||||
logging.debug(f'p.set_owner.is_licensed:{p.set_owner.is_licensed}')
|
||||
logging.debug(f'p.set_owner.team:{p.set_owner.team}')
|
||||
return self._sendAdmin(p)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
@@ -918,6 +1096,7 @@ is ignored for other nodes)</p></div>
|
||||
channelSet = apponly_pb2.ChannelSet()
|
||||
channelSet.ParseFromString(decodedURL)
|
||||
|
||||
|
||||
if len(channelSet.settings) == 0:
|
||||
our_exit("Warning: There were no settings.")
|
||||
|
||||
@@ -928,6 +1107,7 @@ is ignored for other nodes)</p></div>
|
||||
ch.index = i
|
||||
ch.settings.CopyFrom(chs)
|
||||
self.channels[ch.index] = ch
|
||||
logging.debug(f'Channel i:{i} ch:{ch}')
|
||||
self.writeChannel(ch.index)
|
||||
i = i + 1</code></pre>
|
||||
</details>
|
||||
@@ -945,7 +1125,9 @@ is ignored for other nodes)</p></div>
|
||||
"""Show human readable description of our channels."""
|
||||
print("Channels:")
|
||||
if self.channels:
|
||||
logging.debug(f'self.channels:{self.channels}')
|
||||
for c in self.channels:
|
||||
#print('c.settings.psk:', c.settings.psk)
|
||||
cStr = stripnl(MessageToJson(c.settings))
|
||||
# only show if there is no psk (meaning disabled channel)
|
||||
if c.settings.psk:
|
||||
@@ -1068,9 +1250,12 @@ is ignored for other nodes)</p></div>
|
||||
<ul class="">
|
||||
<li><code><a title="meshtastic.node.Node.deleteChannel" href="#meshtastic.node.Node.deleteChannel">deleteChannel</a></code></li>
|
||||
<li><code><a title="meshtastic.node.Node.exitSimulator" href="#meshtastic.node.Node.exitSimulator">exitSimulator</a></code></li>
|
||||
<li><code><a title="meshtastic.node.Node.getChannelByChannelIndex" href="#meshtastic.node.Node.getChannelByChannelIndex">getChannelByChannelIndex</a></code></li>
|
||||
<li><code><a title="meshtastic.node.Node.getChannelByName" href="#meshtastic.node.Node.getChannelByName">getChannelByName</a></code></li>
|
||||
<li><code><a title="meshtastic.node.Node.getDisabledChannel" href="#meshtastic.node.Node.getDisabledChannel">getDisabledChannel</a></code></li>
|
||||
<li><code><a title="meshtastic.node.Node.getURL" href="#meshtastic.node.Node.getURL">getURL</a></code></li>
|
||||
<li><code><a title="meshtastic.node.Node.onResponseRequestChannel" href="#meshtastic.node.Node.onResponseRequestChannel">onResponseRequestChannel</a></code></li>
|
||||
<li><code><a title="meshtastic.node.Node.onResponseRequestSettings" href="#meshtastic.node.Node.onResponseRequestSettings">onResponseRequestSettings</a></code></li>
|
||||
<li><code><a title="meshtastic.node.Node.reboot" href="#meshtastic.node.Node.reboot">reboot</a></code></li>
|
||||
<li><code><a title="meshtastic.node.Node.requestConfig" href="#meshtastic.node.Node.requestConfig">requestConfig</a></code></li>
|
||||
<li><code><a title="meshtastic.node.Node.setOwner" href="#meshtastic.node.Node.setOwner">setOwner</a></code></li>
|
||||
|
||||
@@ -978,16 +978,13 @@ DESCRIPTOR._options = None
|
||||
<dl>
|
||||
<dt id="meshtastic.radioconfig_pb2.RadioConfig"><code class="flex name class">
|
||||
<span>class <span class="ident">RadioConfig</span></span>
|
||||
<span>(</span><span>**kwargs)</span>
|
||||
<span>(</span><span>*args, **kwargs)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Abstract base class for protocol messages.</p>
|
||||
<p>Protocol message classes are almost always generated by the protocol
|
||||
compiler.
|
||||
These generated types subclass Message and implement the methods
|
||||
shown below.</p></div>
|
||||
<div class="desc"><p>A ProtocolMessage</p></div>
|
||||
<h3>Ancestors</h3>
|
||||
<ul class="hlist">
|
||||
<li>google.protobuf.pyext._message.CMessage</li>
|
||||
<li>google.protobuf.message.Message</li>
|
||||
</ul>
|
||||
<h3>Class variables</h3>
|
||||
@@ -996,536 +993,16 @@ shown below.</p></div>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.radioconfig_pb2.RadioConfig.PREFERENCES_FIELD_NUMBER"><code class="name">var <span class="ident">PREFERENCES_FIELD_NUMBER</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.radioconfig_pb2.RadioConfig.UserPreferences"><code class="name">var <span class="ident">UserPreferences</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Abstract base class for protocol messages.</p>
|
||||
<p>Protocol message classes are almost always generated by the protocol
|
||||
compiler.
|
||||
These generated types subclass Message and implement the methods
|
||||
shown below.</p></div>
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>Static methods</h3>
|
||||
<dl>
|
||||
<dt id="meshtastic.radioconfig_pb2.RadioConfig.FromString"><code class="name flex">
|
||||
<span>def <span class="ident">FromString</span></span>(<span>s)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def FromString(s):
|
||||
message = cls()
|
||||
message.MergeFromString(s)
|
||||
return message</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.radioconfig_pb2.RadioConfig.RegisterExtension"><code class="name flex">
|
||||
<span>def <span class="ident">RegisterExtension</span></span>(<span>extension_handle)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def RegisterExtension(extension_handle):
|
||||
extension_handle.containing_type = cls.DESCRIPTOR
|
||||
# TODO(amauryfa): Use cls.MESSAGE_FACTORY.pool when available.
|
||||
# pylint: disable=protected-access
|
||||
cls.DESCRIPTOR.file.pool._AddExtensionDescriptor(extension_handle)
|
||||
_AttachFieldHelpers(cls, extension_handle)</code></pre>
|
||||
</details>
|
||||
<div class="desc"><p>A ProtocolMessage</p></div>
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>Instance variables</h3>
|
||||
<dl>
|
||||
<dt id="meshtastic.radioconfig_pb2.RadioConfig.preferences"><code class="name">var <span class="ident">preferences</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Getter for preferences.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def getter(self):
|
||||
field_value = self._fields.get(field)
|
||||
if field_value is None:
|
||||
# Construct a new object to represent this field.
|
||||
field_value = field._default_constructor(self)
|
||||
|
||||
# Atomically check if another thread has preempted us and, if not, swap
|
||||
# in the new object we just created. If someone has preempted us, we
|
||||
# take that object and discard ours.
|
||||
# WARNING: We are relying on setdefault() being atomic. This is true
|
||||
# in CPython but we haven't investigated others. This warning appears
|
||||
# in several other locations in this file.
|
||||
field_value = self._fields.setdefault(field, field_value)
|
||||
return field_value</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>Methods</h3>
|
||||
<dl>
|
||||
<dt id="meshtastic.radioconfig_pb2.RadioConfig.ByteSize"><code class="name flex">
|
||||
<span>def <span class="ident">ByteSize</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def ByteSize(self):
|
||||
if not self._cached_byte_size_dirty:
|
||||
return self._cached_byte_size
|
||||
|
||||
size = 0
|
||||
descriptor = self.DESCRIPTOR
|
||||
if descriptor.GetOptions().map_entry:
|
||||
# Fields of map entry should always be serialized.
|
||||
size = descriptor.fields_by_name['key']._sizer(self.key)
|
||||
size += descriptor.fields_by_name['value']._sizer(self.value)
|
||||
else:
|
||||
for field_descriptor, field_value in self.ListFields():
|
||||
size += field_descriptor._sizer(field_value)
|
||||
for tag_bytes, value_bytes in self._unknown_fields:
|
||||
size += len(tag_bytes) + len(value_bytes)
|
||||
|
||||
self._cached_byte_size = size
|
||||
self._cached_byte_size_dirty = False
|
||||
self._listener_for_children.dirty = False
|
||||
return size</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.radioconfig_pb2.RadioConfig.Clear"><code class="name flex">
|
||||
<span>def <span class="ident">Clear</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def _Clear(self):
|
||||
# Clear fields.
|
||||
self._fields = {}
|
||||
self._unknown_fields = ()
|
||||
# pylint: disable=protected-access
|
||||
if self._unknown_field_set is not None:
|
||||
self._unknown_field_set._clear()
|
||||
self._unknown_field_set = None
|
||||
|
||||
self._oneofs = {}
|
||||
self._Modified()</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.radioconfig_pb2.RadioConfig.ClearField"><code class="name flex">
|
||||
<span>def <span class="ident">ClearField</span></span>(<span>self, field_name)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def ClearField(self, field_name):
|
||||
try:
|
||||
field = message_descriptor.fields_by_name[field_name]
|
||||
except KeyError:
|
||||
try:
|
||||
field = message_descriptor.oneofs_by_name[field_name]
|
||||
if field in self._oneofs:
|
||||
field = self._oneofs[field]
|
||||
else:
|
||||
return
|
||||
except KeyError:
|
||||
raise ValueError('Protocol message %s has no "%s" field.' %
|
||||
(message_descriptor.name, field_name))
|
||||
|
||||
if field in self._fields:
|
||||
# To match the C++ implementation, we need to invalidate iterators
|
||||
# for map fields when ClearField() happens.
|
||||
if hasattr(self._fields[field], 'InvalidateIterators'):
|
||||
self._fields[field].InvalidateIterators()
|
||||
|
||||
# Note: If the field is a sub-message, its listener will still point
|
||||
# at us. That's fine, because the worst than can happen is that it
|
||||
# will call _Modified() and invalidate our byte size. Big deal.
|
||||
del self._fields[field]
|
||||
|
||||
if self._oneofs.get(field.containing_oneof, None) is field:
|
||||
del self._oneofs[field.containing_oneof]
|
||||
|
||||
# Always call _Modified() -- even if nothing was changed, this is
|
||||
# a mutating method, and thus calling it should cause the field to become
|
||||
# present in the parent message.
|
||||
self._Modified()</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.radioconfig_pb2.RadioConfig.DiscardUnknownFields"><code class="name flex">
|
||||
<span>def <span class="ident">DiscardUnknownFields</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def _DiscardUnknownFields(self):
|
||||
self._unknown_fields = []
|
||||
self._unknown_field_set = None # pylint: disable=protected-access
|
||||
for field, value in self.ListFields():
|
||||
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
|
||||
if _IsMapField(field):
|
||||
if _IsMessageMapField(field):
|
||||
for key in value:
|
||||
value[key].DiscardUnknownFields()
|
||||
elif field.label == _FieldDescriptor.LABEL_REPEATED:
|
||||
for sub_message in value:
|
||||
sub_message.DiscardUnknownFields()
|
||||
else:
|
||||
value.DiscardUnknownFields()</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.radioconfig_pb2.RadioConfig.FindInitializationErrors"><code class="name flex">
|
||||
<span>def <span class="ident">FindInitializationErrors</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Finds required fields which are not initialized.</p>
|
||||
<h2 id="returns">Returns</h2>
|
||||
<p>A list of strings.
|
||||
Each string is a path to an uninitialized field from
|
||||
the top-level message, e.g. "foo.bar[5].baz".</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def FindInitializationErrors(self):
|
||||
"""Finds required fields which are not initialized.
|
||||
|
||||
Returns:
|
||||
A list of strings. Each string is a path to an uninitialized field from
|
||||
the top-level message, e.g. "foo.bar[5].baz".
|
||||
"""
|
||||
|
||||
errors = [] # simplify things
|
||||
|
||||
for field in required_fields:
|
||||
if not self.HasField(field.name):
|
||||
errors.append(field.name)
|
||||
|
||||
for field, value in self.ListFields():
|
||||
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
|
||||
if field.is_extension:
|
||||
name = '(%s)' % field.full_name
|
||||
else:
|
||||
name = field.name
|
||||
|
||||
if _IsMapField(field):
|
||||
if _IsMessageMapField(field):
|
||||
for key in value:
|
||||
element = value[key]
|
||||
prefix = '%s[%s].' % (name, key)
|
||||
sub_errors = element.FindInitializationErrors()
|
||||
errors += [prefix + error for error in sub_errors]
|
||||
else:
|
||||
# ScalarMaps can't have any initialization errors.
|
||||
pass
|
||||
elif field.label == _FieldDescriptor.LABEL_REPEATED:
|
||||
for i in range(len(value)):
|
||||
element = value[i]
|
||||
prefix = '%s[%d].' % (name, i)
|
||||
sub_errors = element.FindInitializationErrors()
|
||||
errors += [prefix + error for error in sub_errors]
|
||||
else:
|
||||
prefix = name + '.'
|
||||
sub_errors = value.FindInitializationErrors()
|
||||
errors += [prefix + error for error in sub_errors]
|
||||
|
||||
return errors</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.radioconfig_pb2.RadioConfig.HasField"><code class="name flex">
|
||||
<span>def <span class="ident">HasField</span></span>(<span>self, field_name)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def HasField(self, field_name):
|
||||
try:
|
||||
field = hassable_fields[field_name]
|
||||
except KeyError:
|
||||
raise ValueError(error_msg % (message_descriptor.full_name, field_name))
|
||||
|
||||
if isinstance(field, descriptor_mod.OneofDescriptor):
|
||||
try:
|
||||
return HasField(self, self._oneofs[field].name)
|
||||
except KeyError:
|
||||
return False
|
||||
else:
|
||||
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
|
||||
value = self._fields.get(field)
|
||||
return value is not None and value._is_present_in_parent
|
||||
else:
|
||||
return field in self._fields</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.radioconfig_pb2.RadioConfig.IsInitialized"><code class="name flex">
|
||||
<span>def <span class="ident">IsInitialized</span></span>(<span>self, errors=None)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Checks if all required fields of a message are set.</p>
|
||||
<h2 id="args">Args</h2>
|
||||
<dl>
|
||||
<dt><strong><code>errors</code></strong></dt>
|
||||
<dd>A list which, if provided, will be populated with the field
|
||||
paths of all missing required fields.</dd>
|
||||
</dl>
|
||||
<h2 id="returns">Returns</h2>
|
||||
<p>True iff the specified message has all required fields set.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def IsInitialized(self, errors=None):
|
||||
"""Checks if all required fields of a message are set.
|
||||
|
||||
Args:
|
||||
errors: A list which, if provided, will be populated with the field
|
||||
paths of all missing required fields.
|
||||
|
||||
Returns:
|
||||
True iff the specified message has all required fields set.
|
||||
"""
|
||||
|
||||
# Performance is critical so we avoid HasField() and ListFields().
|
||||
|
||||
for field in required_fields:
|
||||
if (field not in self._fields or
|
||||
(field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE and
|
||||
not self._fields[field]._is_present_in_parent)):
|
||||
if errors is not None:
|
||||
errors.extend(self.FindInitializationErrors())
|
||||
return False
|
||||
|
||||
for field, value in list(self._fields.items()): # dict can change size!
|
||||
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
|
||||
if field.label == _FieldDescriptor.LABEL_REPEATED:
|
||||
if (field.message_type.has_options and
|
||||
field.message_type.GetOptions().map_entry):
|
||||
continue
|
||||
for element in value:
|
||||
if not element.IsInitialized():
|
||||
if errors is not None:
|
||||
errors.extend(self.FindInitializationErrors())
|
||||
return False
|
||||
elif value._is_present_in_parent and not value.IsInitialized():
|
||||
if errors is not None:
|
||||
errors.extend(self.FindInitializationErrors())
|
||||
return False
|
||||
|
||||
return True</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.radioconfig_pb2.RadioConfig.ListFields"><code class="name flex">
|
||||
<span>def <span class="ident">ListFields</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def ListFields(self):
|
||||
all_fields = [item for item in self._fields.items() if _IsPresent(item)]
|
||||
all_fields.sort(key = lambda item: item[0].number)
|
||||
return all_fields</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.radioconfig_pb2.RadioConfig.MergeFrom"><code class="name flex">
|
||||
<span>def <span class="ident">MergeFrom</span></span>(<span>self, msg)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def MergeFrom(self, msg):
|
||||
if not isinstance(msg, cls):
|
||||
raise TypeError(
|
||||
'Parameter to MergeFrom() must be instance of same class: '
|
||||
'expected %s got %s.' % (_FullyQualifiedClassName(cls),
|
||||
_FullyQualifiedClassName(msg.__class__)))
|
||||
|
||||
assert msg is not self
|
||||
self._Modified()
|
||||
|
||||
fields = self._fields
|
||||
|
||||
for field, value in msg._fields.items():
|
||||
if field.label == LABEL_REPEATED:
|
||||
field_value = fields.get(field)
|
||||
if field_value is None:
|
||||
# Construct a new object to represent this field.
|
||||
field_value = field._default_constructor(self)
|
||||
fields[field] = field_value
|
||||
field_value.MergeFrom(value)
|
||||
elif field.cpp_type == CPPTYPE_MESSAGE:
|
||||
if value._is_present_in_parent:
|
||||
field_value = fields.get(field)
|
||||
if field_value is None:
|
||||
# Construct a new object to represent this field.
|
||||
field_value = field._default_constructor(self)
|
||||
fields[field] = field_value
|
||||
field_value.MergeFrom(value)
|
||||
else:
|
||||
self._fields[field] = value
|
||||
if field.containing_oneof:
|
||||
self._UpdateOneofState(field)
|
||||
|
||||
if msg._unknown_fields:
|
||||
if not self._unknown_fields:
|
||||
self._unknown_fields = []
|
||||
self._unknown_fields.extend(msg._unknown_fields)
|
||||
# pylint: disable=protected-access
|
||||
if self._unknown_field_set is None:
|
||||
self._unknown_field_set = containers.UnknownFieldSet()
|
||||
self._unknown_field_set._extend(msg._unknown_field_set)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.radioconfig_pb2.RadioConfig.MergeFromString"><code class="name flex">
|
||||
<span>def <span class="ident">MergeFromString</span></span>(<span>self, serialized)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def MergeFromString(self, serialized):
|
||||
serialized = memoryview(serialized)
|
||||
length = len(serialized)
|
||||
try:
|
||||
if self._InternalParse(serialized, 0, length) != length:
|
||||
# The only reason _InternalParse would return early is if it
|
||||
# encountered an end-group tag.
|
||||
raise message_mod.DecodeError('Unexpected end-group tag.')
|
||||
except (IndexError, TypeError):
|
||||
# Now ord(buf[p:p+1]) == ord('') gets TypeError.
|
||||
raise message_mod.DecodeError('Truncated message.')
|
||||
except struct.error as e:
|
||||
raise message_mod.DecodeError(e)
|
||||
return length # Return this for legacy reasons.</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.radioconfig_pb2.RadioConfig.SerializePartialToString"><code class="name flex">
|
||||
<span>def <span class="ident">SerializePartialToString</span></span>(<span>self, **kwargs)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def SerializePartialToString(self, **kwargs):
|
||||
out = BytesIO()
|
||||
self._InternalSerialize(out.write, **kwargs)
|
||||
return out.getvalue()</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.radioconfig_pb2.RadioConfig.SerializeToString"><code class="name flex">
|
||||
<span>def <span class="ident">SerializeToString</span></span>(<span>self, **kwargs)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def SerializeToString(self, **kwargs):
|
||||
# Check if the message has all of its required fields set.
|
||||
if not self.IsInitialized():
|
||||
raise message_mod.EncodeError(
|
||||
'Message %s is missing required fields: %s' % (
|
||||
self.DESCRIPTOR.full_name, ','.join(self.FindInitializationErrors())))
|
||||
return self.SerializePartialToString(**kwargs)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.radioconfig_pb2.RadioConfig.SetInParent"><code class="name flex">
|
||||
<span>def <span class="ident">SetInParent</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Sets the _cached_byte_size_dirty bit to true,
|
||||
and propagates this to our listener iff this was a state change.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def Modified(self):
|
||||
"""Sets the _cached_byte_size_dirty bit to true,
|
||||
and propagates this to our listener iff this was a state change.
|
||||
"""
|
||||
|
||||
# Note: Some callers check _cached_byte_size_dirty before calling
|
||||
# _Modified() as an extra optimization. So, if this method is ever
|
||||
# changed such that it does stuff even when _cached_byte_size_dirty is
|
||||
# already true, the callers need to be updated.
|
||||
if not self._cached_byte_size_dirty:
|
||||
self._cached_byte_size_dirty = True
|
||||
self._listener_for_children.dirty = True
|
||||
self._is_present_in_parent = True
|
||||
self._listener.Modified()</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.radioconfig_pb2.RadioConfig.UnknownFields"><code class="name flex">
|
||||
<span>def <span class="ident">UnknownFields</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def _UnknownFields(self):
|
||||
if self._unknown_field_set is None: # pylint: disable=protected-access
|
||||
# pylint: disable=protected-access
|
||||
self._unknown_field_set = containers.UnknownFieldSet()
|
||||
return self._unknown_field_set # pylint: disable=protected-access</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.radioconfig_pb2.RadioConfig.WhichOneof"><code class="name flex">
|
||||
<span>def <span class="ident">WhichOneof</span></span>(<span>self, oneof_name)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Returns the name of the currently set field inside a oneof, or None.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def WhichOneof(self, oneof_name):
|
||||
"""Returns the name of the currently set field inside a oneof, or None."""
|
||||
try:
|
||||
field = message_descriptor.oneofs_by_name[oneof_name]
|
||||
except KeyError:
|
||||
raise ValueError(
|
||||
'Protocol message has no oneof "%s" field.' % oneof_name)
|
||||
|
||||
nested_field = self._oneofs.get(field, None)
|
||||
if nested_field is not None and self.HasField(nested_field.name):
|
||||
return nested_field.name
|
||||
else:
|
||||
return None</code></pre>
|
||||
</details>
|
||||
<div class="desc"><p>Field RadioConfig.preferences</p></div>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
@@ -1548,26 +1025,8 @@ and propagates this to our listener iff this was a state change.</p></div>
|
||||
<li>
|
||||
<h4><code><a title="meshtastic.radioconfig_pb2.RadioConfig" href="#meshtastic.radioconfig_pb2.RadioConfig">RadioConfig</a></code></h4>
|
||||
<ul class="">
|
||||
<li><code><a title="meshtastic.radioconfig_pb2.RadioConfig.ByteSize" href="#meshtastic.radioconfig_pb2.RadioConfig.ByteSize">ByteSize</a></code></li>
|
||||
<li><code><a title="meshtastic.radioconfig_pb2.RadioConfig.Clear" href="#meshtastic.radioconfig_pb2.RadioConfig.Clear">Clear</a></code></li>
|
||||
<li><code><a title="meshtastic.radioconfig_pb2.RadioConfig.ClearField" href="#meshtastic.radioconfig_pb2.RadioConfig.ClearField">ClearField</a></code></li>
|
||||
<li><code><a title="meshtastic.radioconfig_pb2.RadioConfig.DESCRIPTOR" href="#meshtastic.radioconfig_pb2.RadioConfig.DESCRIPTOR">DESCRIPTOR</a></code></li>
|
||||
<li><code><a title="meshtastic.radioconfig_pb2.RadioConfig.DiscardUnknownFields" href="#meshtastic.radioconfig_pb2.RadioConfig.DiscardUnknownFields">DiscardUnknownFields</a></code></li>
|
||||
<li><code><a title="meshtastic.radioconfig_pb2.RadioConfig.FindInitializationErrors" href="#meshtastic.radioconfig_pb2.RadioConfig.FindInitializationErrors">FindInitializationErrors</a></code></li>
|
||||
<li><code><a title="meshtastic.radioconfig_pb2.RadioConfig.FromString" href="#meshtastic.radioconfig_pb2.RadioConfig.FromString">FromString</a></code></li>
|
||||
<li><code><a title="meshtastic.radioconfig_pb2.RadioConfig.HasField" href="#meshtastic.radioconfig_pb2.RadioConfig.HasField">HasField</a></code></li>
|
||||
<li><code><a title="meshtastic.radioconfig_pb2.RadioConfig.IsInitialized" href="#meshtastic.radioconfig_pb2.RadioConfig.IsInitialized">IsInitialized</a></code></li>
|
||||
<li><code><a title="meshtastic.radioconfig_pb2.RadioConfig.ListFields" href="#meshtastic.radioconfig_pb2.RadioConfig.ListFields">ListFields</a></code></li>
|
||||
<li><code><a title="meshtastic.radioconfig_pb2.RadioConfig.MergeFrom" href="#meshtastic.radioconfig_pb2.RadioConfig.MergeFrom">MergeFrom</a></code></li>
|
||||
<li><code><a title="meshtastic.radioconfig_pb2.RadioConfig.MergeFromString" href="#meshtastic.radioconfig_pb2.RadioConfig.MergeFromString">MergeFromString</a></code></li>
|
||||
<li><code><a title="meshtastic.radioconfig_pb2.RadioConfig.PREFERENCES_FIELD_NUMBER" href="#meshtastic.radioconfig_pb2.RadioConfig.PREFERENCES_FIELD_NUMBER">PREFERENCES_FIELD_NUMBER</a></code></li>
|
||||
<li><code><a title="meshtastic.radioconfig_pb2.RadioConfig.RegisterExtension" href="#meshtastic.radioconfig_pb2.RadioConfig.RegisterExtension">RegisterExtension</a></code></li>
|
||||
<li><code><a title="meshtastic.radioconfig_pb2.RadioConfig.SerializePartialToString" href="#meshtastic.radioconfig_pb2.RadioConfig.SerializePartialToString">SerializePartialToString</a></code></li>
|
||||
<li><code><a title="meshtastic.radioconfig_pb2.RadioConfig.SerializeToString" href="#meshtastic.radioconfig_pb2.RadioConfig.SerializeToString">SerializeToString</a></code></li>
|
||||
<li><code><a title="meshtastic.radioconfig_pb2.RadioConfig.SetInParent" href="#meshtastic.radioconfig_pb2.RadioConfig.SetInParent">SetInParent</a></code></li>
|
||||
<li><code><a title="meshtastic.radioconfig_pb2.RadioConfig.UnknownFields" href="#meshtastic.radioconfig_pb2.RadioConfig.UnknownFields">UnknownFields</a></code></li>
|
||||
<li><code><a title="meshtastic.radioconfig_pb2.RadioConfig.UserPreferences" href="#meshtastic.radioconfig_pb2.RadioConfig.UserPreferences">UserPreferences</a></code></li>
|
||||
<li><code><a title="meshtastic.radioconfig_pb2.RadioConfig.WhichOneof" href="#meshtastic.radioconfig_pb2.RadioConfig.WhichOneof">WhichOneof</a></code></li>
|
||||
<li><code><a title="meshtastic.radioconfig_pb2.RadioConfig.preferences" href="#meshtastic.radioconfig_pb2.RadioConfig.preferences">preferences</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
@@ -27,18 +27,24 @@
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">""" Remote hardware
|
||||
<pre><code class="python">"""Remote hardware
|
||||
"""
|
||||
import logging
|
||||
from pubsub import pub
|
||||
from . import portnums_pb2, remote_hardware_pb2
|
||||
from .util import our_exit
|
||||
|
||||
|
||||
def onGPIOreceive(packet, interface):
|
||||
"""Callback for received GPIO responses
|
||||
|
||||
FIXME figure out how to do closures with methods in python"""
|
||||
"""
|
||||
logging.debug(f"packet:{packet} interface:{interface}")
|
||||
hw = packet["decoded"]["remotehw"]
|
||||
print(f'Received RemoteHardware typ={hw["typ"]}, gpio_value={hw["gpioValue"]}')
|
||||
gpioValue = hw["gpioValue"]
|
||||
#print(f'mask:{interface.mask}')
|
||||
value = int(gpioValue) & int(interface.mask)
|
||||
print(f'Received RemoteHardware typ={hw["typ"]}, gpio_value={gpioValue} value={value}')
|
||||
interface.gotResponse = True
|
||||
|
||||
|
||||
class RemoteHardwareClient:
|
||||
@@ -57,26 +63,28 @@ class RemoteHardwareClient:
|
||||
self.iface = iface
|
||||
ch = iface.localNode.getChannelByName("gpio")
|
||||
if not ch:
|
||||
raise Exception(
|
||||
"No gpio channel found, please create on the sending and receive nodes "\
|
||||
"to use this (secured) service (--ch-add gpio --info then --seturl)")
|
||||
our_exit(
|
||||
"Warning: No channel named 'gpio' was found.\n"\
|
||||
"On the sending and receive nodes create a channel named 'gpio'.\n"\
|
||||
"For example, run '--ch-add gpio' on one device, then '--seturl' on\n"\
|
||||
"the other devices using the url from the device where the channel was added.")
|
||||
self.channelIndex = ch.index
|
||||
|
||||
pub.subscribe(
|
||||
onGPIOreceive, "meshtastic.receive.remotehw")
|
||||
pub.subscribe(onGPIOreceive, "meshtastic.receive.remotehw")
|
||||
|
||||
def _sendHardware(self, nodeid, r, wantResponse=False, onResponse=None):
|
||||
if not nodeid:
|
||||
raise Exception(
|
||||
r"You must set a destination node ID for this operation (use --dest \!xxxxxxxxx)")
|
||||
our_exit(r"Warning: Must use a destination node ID for this operation (use --dest \!xxxxxxxxx)")
|
||||
return self.iface.sendData(r, nodeid, portnums_pb2.REMOTE_HARDWARE_APP,
|
||||
wantAck=True, channelIndex=self.channelIndex, wantResponse=wantResponse, onResponse=onResponse)
|
||||
wantAck=True, channelIndex=self.channelIndex,
|
||||
wantResponse=wantResponse, onResponse=onResponse)
|
||||
|
||||
def writeGPIOs(self, nodeid, mask, vals):
|
||||
"""
|
||||
Write the specified vals bits to the device GPIOs. Only bits in mask that
|
||||
are 1 will be changed
|
||||
"""
|
||||
logging.debug(f'writeGPIOs nodeid:{nodeid} mask:{mask} vals:{vals}')
|
||||
r = remote_hardware_pb2.HardwareMessage()
|
||||
r.typ = remote_hardware_pb2.HardwareMessage.Type.WRITE_GPIOS
|
||||
r.gpio_mask = mask
|
||||
@@ -85,6 +93,7 @@ class RemoteHardwareClient:
|
||||
|
||||
def readGPIOs(self, nodeid, mask, onResponse = None):
|
||||
"""Read the specified bits from GPIO inputs on the device"""
|
||||
logging.debug(f'readGPIOs nodeid:{nodeid} mask:{mask}')
|
||||
r = remote_hardware_pb2.HardwareMessage()
|
||||
r.typ = remote_hardware_pb2.HardwareMessage.Type.READ_GPIOS
|
||||
r.gpio_mask = mask
|
||||
@@ -92,9 +101,11 @@ class RemoteHardwareClient:
|
||||
|
||||
def watchGPIOs(self, nodeid, mask):
|
||||
"""Watch the specified bits from GPIO inputs on the device for changes"""
|
||||
logging.debug(f'watchGPIOs nodeid:{nodeid} mask:{mask}')
|
||||
r = remote_hardware_pb2.HardwareMessage()
|
||||
r.typ = remote_hardware_pb2.HardwareMessage.Type.WATCH_GPIOS
|
||||
r.gpio_mask = mask
|
||||
self.iface.mask = mask
|
||||
return self._sendHardware(nodeid, r)</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
@@ -109,18 +120,21 @@ class RemoteHardwareClient:
|
||||
<span>def <span class="ident">onGPIOreceive</span></span>(<span>packet, interface)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Callback for received GPIO responses</p>
|
||||
<p>FIXME figure out how to do closures with methods in python</p></div>
|
||||
<div class="desc"><p>Callback for received GPIO responses</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def onGPIOreceive(packet, interface):
|
||||
"""Callback for received GPIO responses
|
||||
|
||||
FIXME figure out how to do closures with methods in python"""
|
||||
"""
|
||||
logging.debug(f"packet:{packet} interface:{interface}")
|
||||
hw = packet["decoded"]["remotehw"]
|
||||
print(f'Received RemoteHardware typ={hw["typ"]}, gpio_value={hw["gpioValue"]}')</code></pre>
|
||||
gpioValue = hw["gpioValue"]
|
||||
#print(f'mask:{interface.mask}')
|
||||
value = int(gpioValue) & int(interface.mask)
|
||||
print(f'Received RemoteHardware typ={hw["typ"]}, gpio_value={gpioValue} value={value}')
|
||||
interface.gotResponse = True</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
@@ -159,26 +173,28 @@ code for how you can connect to your own custom meshtastic services</p>
|
||||
self.iface = iface
|
||||
ch = iface.localNode.getChannelByName("gpio")
|
||||
if not ch:
|
||||
raise Exception(
|
||||
"No gpio channel found, please create on the sending and receive nodes "\
|
||||
"to use this (secured) service (--ch-add gpio --info then --seturl)")
|
||||
our_exit(
|
||||
"Warning: No channel named 'gpio' was found.\n"\
|
||||
"On the sending and receive nodes create a channel named 'gpio'.\n"\
|
||||
"For example, run '--ch-add gpio' on one device, then '--seturl' on\n"\
|
||||
"the other devices using the url from the device where the channel was added.")
|
||||
self.channelIndex = ch.index
|
||||
|
||||
pub.subscribe(
|
||||
onGPIOreceive, "meshtastic.receive.remotehw")
|
||||
pub.subscribe(onGPIOreceive, "meshtastic.receive.remotehw")
|
||||
|
||||
def _sendHardware(self, nodeid, r, wantResponse=False, onResponse=None):
|
||||
if not nodeid:
|
||||
raise Exception(
|
||||
r"You must set a destination node ID for this operation (use --dest \!xxxxxxxxx)")
|
||||
our_exit(r"Warning: Must use a destination node ID for this operation (use --dest \!xxxxxxxxx)")
|
||||
return self.iface.sendData(r, nodeid, portnums_pb2.REMOTE_HARDWARE_APP,
|
||||
wantAck=True, channelIndex=self.channelIndex, wantResponse=wantResponse, onResponse=onResponse)
|
||||
wantAck=True, channelIndex=self.channelIndex,
|
||||
wantResponse=wantResponse, onResponse=onResponse)
|
||||
|
||||
def writeGPIOs(self, nodeid, mask, vals):
|
||||
"""
|
||||
Write the specified vals bits to the device GPIOs. Only bits in mask that
|
||||
are 1 will be changed
|
||||
"""
|
||||
logging.debug(f'writeGPIOs nodeid:{nodeid} mask:{mask} vals:{vals}')
|
||||
r = remote_hardware_pb2.HardwareMessage()
|
||||
r.typ = remote_hardware_pb2.HardwareMessage.Type.WRITE_GPIOS
|
||||
r.gpio_mask = mask
|
||||
@@ -187,6 +203,7 @@ code for how you can connect to your own custom meshtastic services</p>
|
||||
|
||||
def readGPIOs(self, nodeid, mask, onResponse = None):
|
||||
"""Read the specified bits from GPIO inputs on the device"""
|
||||
logging.debug(f'readGPIOs nodeid:{nodeid} mask:{mask}')
|
||||
r = remote_hardware_pb2.HardwareMessage()
|
||||
r.typ = remote_hardware_pb2.HardwareMessage.Type.READ_GPIOS
|
||||
r.gpio_mask = mask
|
||||
@@ -194,9 +211,11 @@ code for how you can connect to your own custom meshtastic services</p>
|
||||
|
||||
def watchGPIOs(self, nodeid, mask):
|
||||
"""Watch the specified bits from GPIO inputs on the device for changes"""
|
||||
logging.debug(f'watchGPIOs nodeid:{nodeid} mask:{mask}')
|
||||
r = remote_hardware_pb2.HardwareMessage()
|
||||
r.typ = remote_hardware_pb2.HardwareMessage.Type.WATCH_GPIOS
|
||||
r.gpio_mask = mask
|
||||
self.iface.mask = mask
|
||||
return self._sendHardware(nodeid, r)</code></pre>
|
||||
</details>
|
||||
<h3>Methods</h3>
|
||||
@@ -212,6 +231,7 @@ code for how you can connect to your own custom meshtastic services</p>
|
||||
</summary>
|
||||
<pre><code class="python">def readGPIOs(self, nodeid, mask, onResponse = None):
|
||||
"""Read the specified bits from GPIO inputs on the device"""
|
||||
logging.debug(f'readGPIOs nodeid:{nodeid} mask:{mask}')
|
||||
r = remote_hardware_pb2.HardwareMessage()
|
||||
r.typ = remote_hardware_pb2.HardwareMessage.Type.READ_GPIOS
|
||||
r.gpio_mask = mask
|
||||
@@ -229,9 +249,11 @@ code for how you can connect to your own custom meshtastic services</p>
|
||||
</summary>
|
||||
<pre><code class="python">def watchGPIOs(self, nodeid, mask):
|
||||
"""Watch the specified bits from GPIO inputs on the device for changes"""
|
||||
logging.debug(f'watchGPIOs nodeid:{nodeid} mask:{mask}')
|
||||
r = remote_hardware_pb2.HardwareMessage()
|
||||
r.typ = remote_hardware_pb2.HardwareMessage.Type.WATCH_GPIOS
|
||||
r.gpio_mask = mask
|
||||
self.iface.mask = mask
|
||||
return self._sendHardware(nodeid, r)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
@@ -251,6 +273,7 @@ are 1 will be changed</p></div>
|
||||
Write the specified vals bits to the device GPIOs. Only bits in mask that
|
||||
are 1 will be changed
|
||||
"""
|
||||
logging.debug(f'writeGPIOs nodeid:{nodeid} mask:{mask} vals:{vals}')
|
||||
r = remote_hardware_pb2.HardwareMessage()
|
||||
r.typ = remote_hardware_pb2.HardwareMessage.Type.WRITE_GPIOS
|
||||
r.gpio_mask = mask
|
||||
|
||||
@@ -163,16 +163,13 @@ DESCRIPTOR._options = None
|
||||
<dl>
|
||||
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage"><code class="flex name class">
|
||||
<span>class <span class="ident">HardwareMessage</span></span>
|
||||
<span>(</span><span>**kwargs)</span>
|
||||
<span>(</span><span>*args, **kwargs)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Abstract base class for protocol messages.</p>
|
||||
<p>Protocol message classes are almost always generated by the protocol
|
||||
compiler.
|
||||
These generated types subclass Message and implement the methods
|
||||
shown below.</p></div>
|
||||
<div class="desc"><p>A ProtocolMessage</p></div>
|
||||
<h3>Ancestors</h3>
|
||||
<ul class="hlist">
|
||||
<li>google.protobuf.pyext._message.CMessage</li>
|
||||
<li>google.protobuf.message.Message</li>
|
||||
</ul>
|
||||
<h3>Class variables</h3>
|
||||
@@ -185,14 +182,6 @@ shown below.</p></div>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.GPIO_MASK_FIELD_NUMBER"><code class="name">var <span class="ident">GPIO_MASK_FIELD_NUMBER</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.GPIO_VALUE_FIELD_NUMBER"><code class="name">var <span class="ident">GPIO_VALUE_FIELD_NUMBER</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.READ_GPIOS"><code class="name">var <span class="ident">READ_GPIOS</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
@@ -201,10 +190,6 @@ shown below.</p></div>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.TYP_FIELD_NUMBER"><code class="name">var <span class="ident">TYP_FIELD_NUMBER</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.Type"><code class="name">var <span class="ident">Type</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
@@ -222,539 +207,19 @@ shown below.</p></div>
|
||||
<div class="desc"></div>
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>Static methods</h3>
|
||||
<dl>
|
||||
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.FromString"><code class="name flex">
|
||||
<span>def <span class="ident">FromString</span></span>(<span>s)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def FromString(s):
|
||||
message = cls()
|
||||
message.MergeFromString(s)
|
||||
return message</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.RegisterExtension"><code class="name flex">
|
||||
<span>def <span class="ident">RegisterExtension</span></span>(<span>extension_handle)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def RegisterExtension(extension_handle):
|
||||
extension_handle.containing_type = cls.DESCRIPTOR
|
||||
# TODO(amauryfa): Use cls.MESSAGE_FACTORY.pool when available.
|
||||
# pylint: disable=protected-access
|
||||
cls.DESCRIPTOR.file.pool._AddExtensionDescriptor(extension_handle)
|
||||
_AttachFieldHelpers(cls, extension_handle)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>Instance variables</h3>
|
||||
<dl>
|
||||
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.gpio_mask"><code class="name">var <span class="ident">gpio_mask</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Getter for gpio_mask.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def getter(self):
|
||||
# TODO(protobuf-team): This may be broken since there may not be
|
||||
# default_value. Combine with has_default_value somehow.
|
||||
return self._fields.get(field, default_value)</code></pre>
|
||||
</details>
|
||||
<div class="desc"><p>Field HardwareMessage.gpio_mask</p></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.gpio_value"><code class="name">var <span class="ident">gpio_value</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Getter for gpio_value.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def getter(self):
|
||||
# TODO(protobuf-team): This may be broken since there may not be
|
||||
# default_value. Combine with has_default_value somehow.
|
||||
return self._fields.get(field, default_value)</code></pre>
|
||||
</details>
|
||||
<div class="desc"><p>Field HardwareMessage.gpio_value</p></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.typ"><code class="name">var <span class="ident">typ</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Getter for typ.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def getter(self):
|
||||
# TODO(protobuf-team): This may be broken since there may not be
|
||||
# default_value. Combine with has_default_value somehow.
|
||||
return self._fields.get(field, default_value)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>Methods</h3>
|
||||
<dl>
|
||||
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.ByteSize"><code class="name flex">
|
||||
<span>def <span class="ident">ByteSize</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def ByteSize(self):
|
||||
if not self._cached_byte_size_dirty:
|
||||
return self._cached_byte_size
|
||||
|
||||
size = 0
|
||||
descriptor = self.DESCRIPTOR
|
||||
if descriptor.GetOptions().map_entry:
|
||||
# Fields of map entry should always be serialized.
|
||||
size = descriptor.fields_by_name['key']._sizer(self.key)
|
||||
size += descriptor.fields_by_name['value']._sizer(self.value)
|
||||
else:
|
||||
for field_descriptor, field_value in self.ListFields():
|
||||
size += field_descriptor._sizer(field_value)
|
||||
for tag_bytes, value_bytes in self._unknown_fields:
|
||||
size += len(tag_bytes) + len(value_bytes)
|
||||
|
||||
self._cached_byte_size = size
|
||||
self._cached_byte_size_dirty = False
|
||||
self._listener_for_children.dirty = False
|
||||
return size</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.Clear"><code class="name flex">
|
||||
<span>def <span class="ident">Clear</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def _Clear(self):
|
||||
# Clear fields.
|
||||
self._fields = {}
|
||||
self._unknown_fields = ()
|
||||
# pylint: disable=protected-access
|
||||
if self._unknown_field_set is not None:
|
||||
self._unknown_field_set._clear()
|
||||
self._unknown_field_set = None
|
||||
|
||||
self._oneofs = {}
|
||||
self._Modified()</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.ClearField"><code class="name flex">
|
||||
<span>def <span class="ident">ClearField</span></span>(<span>self, field_name)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def ClearField(self, field_name):
|
||||
try:
|
||||
field = message_descriptor.fields_by_name[field_name]
|
||||
except KeyError:
|
||||
try:
|
||||
field = message_descriptor.oneofs_by_name[field_name]
|
||||
if field in self._oneofs:
|
||||
field = self._oneofs[field]
|
||||
else:
|
||||
return
|
||||
except KeyError:
|
||||
raise ValueError('Protocol message %s has no "%s" field.' %
|
||||
(message_descriptor.name, field_name))
|
||||
|
||||
if field in self._fields:
|
||||
# To match the C++ implementation, we need to invalidate iterators
|
||||
# for map fields when ClearField() happens.
|
||||
if hasattr(self._fields[field], 'InvalidateIterators'):
|
||||
self._fields[field].InvalidateIterators()
|
||||
|
||||
# Note: If the field is a sub-message, its listener will still point
|
||||
# at us. That's fine, because the worst than can happen is that it
|
||||
# will call _Modified() and invalidate our byte size. Big deal.
|
||||
del self._fields[field]
|
||||
|
||||
if self._oneofs.get(field.containing_oneof, None) is field:
|
||||
del self._oneofs[field.containing_oneof]
|
||||
|
||||
# Always call _Modified() -- even if nothing was changed, this is
|
||||
# a mutating method, and thus calling it should cause the field to become
|
||||
# present in the parent message.
|
||||
self._Modified()</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.DiscardUnknownFields"><code class="name flex">
|
||||
<span>def <span class="ident">DiscardUnknownFields</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def _DiscardUnknownFields(self):
|
||||
self._unknown_fields = []
|
||||
self._unknown_field_set = None # pylint: disable=protected-access
|
||||
for field, value in self.ListFields():
|
||||
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
|
||||
if _IsMapField(field):
|
||||
if _IsMessageMapField(field):
|
||||
for key in value:
|
||||
value[key].DiscardUnknownFields()
|
||||
elif field.label == _FieldDescriptor.LABEL_REPEATED:
|
||||
for sub_message in value:
|
||||
sub_message.DiscardUnknownFields()
|
||||
else:
|
||||
value.DiscardUnknownFields()</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.FindInitializationErrors"><code class="name flex">
|
||||
<span>def <span class="ident">FindInitializationErrors</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Finds required fields which are not initialized.</p>
|
||||
<h2 id="returns">Returns</h2>
|
||||
<p>A list of strings.
|
||||
Each string is a path to an uninitialized field from
|
||||
the top-level message, e.g. "foo.bar[5].baz".</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def FindInitializationErrors(self):
|
||||
"""Finds required fields which are not initialized.
|
||||
|
||||
Returns:
|
||||
A list of strings. Each string is a path to an uninitialized field from
|
||||
the top-level message, e.g. "foo.bar[5].baz".
|
||||
"""
|
||||
|
||||
errors = [] # simplify things
|
||||
|
||||
for field in required_fields:
|
||||
if not self.HasField(field.name):
|
||||
errors.append(field.name)
|
||||
|
||||
for field, value in self.ListFields():
|
||||
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
|
||||
if field.is_extension:
|
||||
name = '(%s)' % field.full_name
|
||||
else:
|
||||
name = field.name
|
||||
|
||||
if _IsMapField(field):
|
||||
if _IsMessageMapField(field):
|
||||
for key in value:
|
||||
element = value[key]
|
||||
prefix = '%s[%s].' % (name, key)
|
||||
sub_errors = element.FindInitializationErrors()
|
||||
errors += [prefix + error for error in sub_errors]
|
||||
else:
|
||||
# ScalarMaps can't have any initialization errors.
|
||||
pass
|
||||
elif field.label == _FieldDescriptor.LABEL_REPEATED:
|
||||
for i in range(len(value)):
|
||||
element = value[i]
|
||||
prefix = '%s[%d].' % (name, i)
|
||||
sub_errors = element.FindInitializationErrors()
|
||||
errors += [prefix + error for error in sub_errors]
|
||||
else:
|
||||
prefix = name + '.'
|
||||
sub_errors = value.FindInitializationErrors()
|
||||
errors += [prefix + error for error in sub_errors]
|
||||
|
||||
return errors</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.HasField"><code class="name flex">
|
||||
<span>def <span class="ident">HasField</span></span>(<span>self, field_name)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def HasField(self, field_name):
|
||||
try:
|
||||
field = hassable_fields[field_name]
|
||||
except KeyError:
|
||||
raise ValueError(error_msg % (message_descriptor.full_name, field_name))
|
||||
|
||||
if isinstance(field, descriptor_mod.OneofDescriptor):
|
||||
try:
|
||||
return HasField(self, self._oneofs[field].name)
|
||||
except KeyError:
|
||||
return False
|
||||
else:
|
||||
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
|
||||
value = self._fields.get(field)
|
||||
return value is not None and value._is_present_in_parent
|
||||
else:
|
||||
return field in self._fields</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.IsInitialized"><code class="name flex">
|
||||
<span>def <span class="ident">IsInitialized</span></span>(<span>self, errors=None)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Checks if all required fields of a message are set.</p>
|
||||
<h2 id="args">Args</h2>
|
||||
<dl>
|
||||
<dt><strong><code>errors</code></strong></dt>
|
||||
<dd>A list which, if provided, will be populated with the field
|
||||
paths of all missing required fields.</dd>
|
||||
</dl>
|
||||
<h2 id="returns">Returns</h2>
|
||||
<p>True iff the specified message has all required fields set.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def IsInitialized(self, errors=None):
|
||||
"""Checks if all required fields of a message are set.
|
||||
|
||||
Args:
|
||||
errors: A list which, if provided, will be populated with the field
|
||||
paths of all missing required fields.
|
||||
|
||||
Returns:
|
||||
True iff the specified message has all required fields set.
|
||||
"""
|
||||
|
||||
# Performance is critical so we avoid HasField() and ListFields().
|
||||
|
||||
for field in required_fields:
|
||||
if (field not in self._fields or
|
||||
(field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE and
|
||||
not self._fields[field]._is_present_in_parent)):
|
||||
if errors is not None:
|
||||
errors.extend(self.FindInitializationErrors())
|
||||
return False
|
||||
|
||||
for field, value in list(self._fields.items()): # dict can change size!
|
||||
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
|
||||
if field.label == _FieldDescriptor.LABEL_REPEATED:
|
||||
if (field.message_type.has_options and
|
||||
field.message_type.GetOptions().map_entry):
|
||||
continue
|
||||
for element in value:
|
||||
if not element.IsInitialized():
|
||||
if errors is not None:
|
||||
errors.extend(self.FindInitializationErrors())
|
||||
return False
|
||||
elif value._is_present_in_parent and not value.IsInitialized():
|
||||
if errors is not None:
|
||||
errors.extend(self.FindInitializationErrors())
|
||||
return False
|
||||
|
||||
return True</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.ListFields"><code class="name flex">
|
||||
<span>def <span class="ident">ListFields</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def ListFields(self):
|
||||
all_fields = [item for item in self._fields.items() if _IsPresent(item)]
|
||||
all_fields.sort(key = lambda item: item[0].number)
|
||||
return all_fields</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.MergeFrom"><code class="name flex">
|
||||
<span>def <span class="ident">MergeFrom</span></span>(<span>self, msg)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def MergeFrom(self, msg):
|
||||
if not isinstance(msg, cls):
|
||||
raise TypeError(
|
||||
'Parameter to MergeFrom() must be instance of same class: '
|
||||
'expected %s got %s.' % (_FullyQualifiedClassName(cls),
|
||||
_FullyQualifiedClassName(msg.__class__)))
|
||||
|
||||
assert msg is not self
|
||||
self._Modified()
|
||||
|
||||
fields = self._fields
|
||||
|
||||
for field, value in msg._fields.items():
|
||||
if field.label == LABEL_REPEATED:
|
||||
field_value = fields.get(field)
|
||||
if field_value is None:
|
||||
# Construct a new object to represent this field.
|
||||
field_value = field._default_constructor(self)
|
||||
fields[field] = field_value
|
||||
field_value.MergeFrom(value)
|
||||
elif field.cpp_type == CPPTYPE_MESSAGE:
|
||||
if value._is_present_in_parent:
|
||||
field_value = fields.get(field)
|
||||
if field_value is None:
|
||||
# Construct a new object to represent this field.
|
||||
field_value = field._default_constructor(self)
|
||||
fields[field] = field_value
|
||||
field_value.MergeFrom(value)
|
||||
else:
|
||||
self._fields[field] = value
|
||||
if field.containing_oneof:
|
||||
self._UpdateOneofState(field)
|
||||
|
||||
if msg._unknown_fields:
|
||||
if not self._unknown_fields:
|
||||
self._unknown_fields = []
|
||||
self._unknown_fields.extend(msg._unknown_fields)
|
||||
# pylint: disable=protected-access
|
||||
if self._unknown_field_set is None:
|
||||
self._unknown_field_set = containers.UnknownFieldSet()
|
||||
self._unknown_field_set._extend(msg._unknown_field_set)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.MergeFromString"><code class="name flex">
|
||||
<span>def <span class="ident">MergeFromString</span></span>(<span>self, serialized)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def MergeFromString(self, serialized):
|
||||
serialized = memoryview(serialized)
|
||||
length = len(serialized)
|
||||
try:
|
||||
if self._InternalParse(serialized, 0, length) != length:
|
||||
# The only reason _InternalParse would return early is if it
|
||||
# encountered an end-group tag.
|
||||
raise message_mod.DecodeError('Unexpected end-group tag.')
|
||||
except (IndexError, TypeError):
|
||||
# Now ord(buf[p:p+1]) == ord('') gets TypeError.
|
||||
raise message_mod.DecodeError('Truncated message.')
|
||||
except struct.error as e:
|
||||
raise message_mod.DecodeError(e)
|
||||
return length # Return this for legacy reasons.</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.SerializePartialToString"><code class="name flex">
|
||||
<span>def <span class="ident">SerializePartialToString</span></span>(<span>self, **kwargs)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def SerializePartialToString(self, **kwargs):
|
||||
out = BytesIO()
|
||||
self._InternalSerialize(out.write, **kwargs)
|
||||
return out.getvalue()</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.SerializeToString"><code class="name flex">
|
||||
<span>def <span class="ident">SerializeToString</span></span>(<span>self, **kwargs)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def SerializeToString(self, **kwargs):
|
||||
# Check if the message has all of its required fields set.
|
||||
if not self.IsInitialized():
|
||||
raise message_mod.EncodeError(
|
||||
'Message %s is missing required fields: %s' % (
|
||||
self.DESCRIPTOR.full_name, ','.join(self.FindInitializationErrors())))
|
||||
return self.SerializePartialToString(**kwargs)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.SetInParent"><code class="name flex">
|
||||
<span>def <span class="ident">SetInParent</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Sets the _cached_byte_size_dirty bit to true,
|
||||
and propagates this to our listener iff this was a state change.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def Modified(self):
|
||||
"""Sets the _cached_byte_size_dirty bit to true,
|
||||
and propagates this to our listener iff this was a state change.
|
||||
"""
|
||||
|
||||
# Note: Some callers check _cached_byte_size_dirty before calling
|
||||
# _Modified() as an extra optimization. So, if this method is ever
|
||||
# changed such that it does stuff even when _cached_byte_size_dirty is
|
||||
# already true, the callers need to be updated.
|
||||
if not self._cached_byte_size_dirty:
|
||||
self._cached_byte_size_dirty = True
|
||||
self._listener_for_children.dirty = True
|
||||
self._is_present_in_parent = True
|
||||
self._listener.Modified()</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.UnknownFields"><code class="name flex">
|
||||
<span>def <span class="ident">UnknownFields</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def _UnknownFields(self):
|
||||
if self._unknown_field_set is None: # pylint: disable=protected-access
|
||||
# pylint: disable=protected-access
|
||||
self._unknown_field_set = containers.UnknownFieldSet()
|
||||
return self._unknown_field_set # pylint: disable=protected-access</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.remote_hardware_pb2.HardwareMessage.WhichOneof"><code class="name flex">
|
||||
<span>def <span class="ident">WhichOneof</span></span>(<span>self, oneof_name)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Returns the name of the currently set field inside a oneof, or None.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def WhichOneof(self, oneof_name):
|
||||
"""Returns the name of the currently set field inside a oneof, or None."""
|
||||
try:
|
||||
field = message_descriptor.oneofs_by_name[oneof_name]
|
||||
except KeyError:
|
||||
raise ValueError(
|
||||
'Protocol message has no oneof "%s" field.' % oneof_name)
|
||||
|
||||
nested_field = self._oneofs.get(field, None)
|
||||
if nested_field is not None and self.HasField(nested_field.name):
|
||||
return nested_field.name
|
||||
else:
|
||||
return None</code></pre>
|
||||
</details>
|
||||
<div class="desc"><p>Field HardwareMessage.typ</p></div>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
@@ -776,35 +241,15 @@ and propagates this to our listener iff this was a state change.</p></div>
|
||||
<ul>
|
||||
<li>
|
||||
<h4><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage" href="#meshtastic.remote_hardware_pb2.HardwareMessage">HardwareMessage</a></code></h4>
|
||||
<ul class="">
|
||||
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.ByteSize" href="#meshtastic.remote_hardware_pb2.HardwareMessage.ByteSize">ByteSize</a></code></li>
|
||||
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.Clear" href="#meshtastic.remote_hardware_pb2.HardwareMessage.Clear">Clear</a></code></li>
|
||||
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.ClearField" href="#meshtastic.remote_hardware_pb2.HardwareMessage.ClearField">ClearField</a></code></li>
|
||||
<ul class="two-column">
|
||||
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.DESCRIPTOR" href="#meshtastic.remote_hardware_pb2.HardwareMessage.DESCRIPTOR">DESCRIPTOR</a></code></li>
|
||||
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.DiscardUnknownFields" href="#meshtastic.remote_hardware_pb2.HardwareMessage.DiscardUnknownFields">DiscardUnknownFields</a></code></li>
|
||||
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.FindInitializationErrors" href="#meshtastic.remote_hardware_pb2.HardwareMessage.FindInitializationErrors">FindInitializationErrors</a></code></li>
|
||||
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.FromString" href="#meshtastic.remote_hardware_pb2.HardwareMessage.FromString">FromString</a></code></li>
|
||||
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.GPIOS_CHANGED" href="#meshtastic.remote_hardware_pb2.HardwareMessage.GPIOS_CHANGED">GPIOS_CHANGED</a></code></li>
|
||||
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.GPIO_MASK_FIELD_NUMBER" href="#meshtastic.remote_hardware_pb2.HardwareMessage.GPIO_MASK_FIELD_NUMBER">GPIO_MASK_FIELD_NUMBER</a></code></li>
|
||||
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.GPIO_VALUE_FIELD_NUMBER" href="#meshtastic.remote_hardware_pb2.HardwareMessage.GPIO_VALUE_FIELD_NUMBER">GPIO_VALUE_FIELD_NUMBER</a></code></li>
|
||||
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.HasField" href="#meshtastic.remote_hardware_pb2.HardwareMessage.HasField">HasField</a></code></li>
|
||||
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.IsInitialized" href="#meshtastic.remote_hardware_pb2.HardwareMessage.IsInitialized">IsInitialized</a></code></li>
|
||||
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.ListFields" href="#meshtastic.remote_hardware_pb2.HardwareMessage.ListFields">ListFields</a></code></li>
|
||||
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.MergeFrom" href="#meshtastic.remote_hardware_pb2.HardwareMessage.MergeFrom">MergeFrom</a></code></li>
|
||||
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.MergeFromString" href="#meshtastic.remote_hardware_pb2.HardwareMessage.MergeFromString">MergeFromString</a></code></li>
|
||||
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.READ_GPIOS" href="#meshtastic.remote_hardware_pb2.HardwareMessage.READ_GPIOS">READ_GPIOS</a></code></li>
|
||||
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.READ_GPIOS_REPLY" href="#meshtastic.remote_hardware_pb2.HardwareMessage.READ_GPIOS_REPLY">READ_GPIOS_REPLY</a></code></li>
|
||||
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.RegisterExtension" href="#meshtastic.remote_hardware_pb2.HardwareMessage.RegisterExtension">RegisterExtension</a></code></li>
|
||||
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.SerializePartialToString" href="#meshtastic.remote_hardware_pb2.HardwareMessage.SerializePartialToString">SerializePartialToString</a></code></li>
|
||||
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.SerializeToString" href="#meshtastic.remote_hardware_pb2.HardwareMessage.SerializeToString">SerializeToString</a></code></li>
|
||||
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.SetInParent" href="#meshtastic.remote_hardware_pb2.HardwareMessage.SetInParent">SetInParent</a></code></li>
|
||||
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.TYP_FIELD_NUMBER" href="#meshtastic.remote_hardware_pb2.HardwareMessage.TYP_FIELD_NUMBER">TYP_FIELD_NUMBER</a></code></li>
|
||||
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.Type" href="#meshtastic.remote_hardware_pb2.HardwareMessage.Type">Type</a></code></li>
|
||||
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.UNSET" href="#meshtastic.remote_hardware_pb2.HardwareMessage.UNSET">UNSET</a></code></li>
|
||||
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.UnknownFields" href="#meshtastic.remote_hardware_pb2.HardwareMessage.UnknownFields">UnknownFields</a></code></li>
|
||||
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.WATCH_GPIOS" href="#meshtastic.remote_hardware_pb2.HardwareMessage.WATCH_GPIOS">WATCH_GPIOS</a></code></li>
|
||||
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.WRITE_GPIOS" href="#meshtastic.remote_hardware_pb2.HardwareMessage.WRITE_GPIOS">WRITE_GPIOS</a></code></li>
|
||||
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.WhichOneof" href="#meshtastic.remote_hardware_pb2.HardwareMessage.WhichOneof">WhichOneof</a></code></li>
|
||||
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.gpio_mask" href="#meshtastic.remote_hardware_pb2.HardwareMessage.gpio_mask">gpio_mask</a></code></li>
|
||||
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.gpio_value" href="#meshtastic.remote_hardware_pb2.HardwareMessage.gpio_value">gpio_value</a></code></li>
|
||||
<li><code><a title="meshtastic.remote_hardware_pb2.HardwareMessage.typ" href="#meshtastic.remote_hardware_pb2.HardwareMessage.typ">typ</a></code></li>
|
||||
|
||||
@@ -326,16 +326,13 @@ DESCRIPTOR._options = None
|
||||
<dl>
|
||||
<dt id="meshtastic.storeforward_pb2.StoreAndForward"><code class="flex name class">
|
||||
<span>class <span class="ident">StoreAndForward</span></span>
|
||||
<span>(</span><span>**kwargs)</span>
|
||||
<span>(</span><span>*args, **kwargs)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Abstract base class for protocol messages.</p>
|
||||
<p>Protocol message classes are almost always generated by the protocol
|
||||
compiler.
|
||||
These generated types subclass Message and implement the methods
|
||||
shown below.</p></div>
|
||||
<div class="desc"><p>A ProtocolMessage</p></div>
|
||||
<h3>Ancestors</h3>
|
||||
<ul class="hlist">
|
||||
<li>google.protobuf.pyext._message.CMessage</li>
|
||||
<li>google.protobuf.message.Message</li>
|
||||
</ul>
|
||||
<h3>Class variables</h3>
|
||||
@@ -364,17 +361,9 @@ shown below.</p></div>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.storeforward_pb2.StoreAndForward.HISTORY_FIELD_NUMBER"><code class="name">var <span class="ident">HISTORY_FIELD_NUMBER</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.storeforward_pb2.StoreAndForward.History"><code class="name">var <span class="ident">History</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Abstract base class for protocol messages.</p>
|
||||
<p>Protocol message classes are almost always generated by the protocol
|
||||
compiler.
|
||||
These generated types subclass Message and implement the methods
|
||||
shown below.</p></div>
|
||||
<div class="desc"><p>A ProtocolMessage</p></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.storeforward_pb2.StoreAndForward.ROUTER_BUSY"><code class="name">var <span class="ident">ROUTER_BUSY</span></code></dt>
|
||||
<dd>
|
||||
@@ -396,584 +385,32 @@ shown below.</p></div>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.storeforward_pb2.StoreAndForward.RR_FIELD_NUMBER"><code class="name">var <span class="ident">RR_FIELD_NUMBER</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.storeforward_pb2.StoreAndForward.RequestResponse"><code class="name">var <span class="ident">RequestResponse</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.storeforward_pb2.StoreAndForward.STATS_FIELD_NUMBER"><code class="name">var <span class="ident">STATS_FIELD_NUMBER</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.storeforward_pb2.StoreAndForward.Statistics"><code class="name">var <span class="ident">Statistics</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Abstract base class for protocol messages.</p>
|
||||
<p>Protocol message classes are almost always generated by the protocol
|
||||
compiler.
|
||||
These generated types subclass Message and implement the methods
|
||||
shown below.</p></div>
|
||||
<div class="desc"><p>A ProtocolMessage</p></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.storeforward_pb2.StoreAndForward.UNSET"><code class="name">var <span class="ident">UNSET</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>Static methods</h3>
|
||||
<dl>
|
||||
<dt id="meshtastic.storeforward_pb2.StoreAndForward.FromString"><code class="name flex">
|
||||
<span>def <span class="ident">FromString</span></span>(<span>s)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def FromString(s):
|
||||
message = cls()
|
||||
message.MergeFromString(s)
|
||||
return message</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.storeforward_pb2.StoreAndForward.RegisterExtension"><code class="name flex">
|
||||
<span>def <span class="ident">RegisterExtension</span></span>(<span>extension_handle)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def RegisterExtension(extension_handle):
|
||||
extension_handle.containing_type = cls.DESCRIPTOR
|
||||
# TODO(amauryfa): Use cls.MESSAGE_FACTORY.pool when available.
|
||||
# pylint: disable=protected-access
|
||||
cls.DESCRIPTOR.file.pool._AddExtensionDescriptor(extension_handle)
|
||||
_AttachFieldHelpers(cls, extension_handle)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>Instance variables</h3>
|
||||
<dl>
|
||||
<dt id="meshtastic.storeforward_pb2.StoreAndForward.history"><code class="name">var <span class="ident">history</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Getter for history.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def getter(self):
|
||||
field_value = self._fields.get(field)
|
||||
if field_value is None:
|
||||
# Construct a new object to represent this field.
|
||||
field_value = field._default_constructor(self)
|
||||
|
||||
# Atomically check if another thread has preempted us and, if not, swap
|
||||
# in the new object we just created. If someone has preempted us, we
|
||||
# take that object and discard ours.
|
||||
# WARNING: We are relying on setdefault() being atomic. This is true
|
||||
# in CPython but we haven't investigated others. This warning appears
|
||||
# in several other locations in this file.
|
||||
field_value = self._fields.setdefault(field, field_value)
|
||||
return field_value</code></pre>
|
||||
</details>
|
||||
<div class="desc"><p>Field StoreAndForward.history</p></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.storeforward_pb2.StoreAndForward.rr"><code class="name">var <span class="ident">rr</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Getter for rr.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def getter(self):
|
||||
# TODO(protobuf-team): This may be broken since there may not be
|
||||
# default_value. Combine with has_default_value somehow.
|
||||
return self._fields.get(field, default_value)</code></pre>
|
||||
</details>
|
||||
<div class="desc"><p>Field StoreAndForward.rr</p></div>
|
||||
</dd>
|
||||
<dt id="meshtastic.storeforward_pb2.StoreAndForward.stats"><code class="name">var <span class="ident">stats</span></code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Getter for stats.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def getter(self):
|
||||
field_value = self._fields.get(field)
|
||||
if field_value is None:
|
||||
# Construct a new object to represent this field.
|
||||
field_value = field._default_constructor(self)
|
||||
|
||||
# Atomically check if another thread has preempted us and, if not, swap
|
||||
# in the new object we just created. If someone has preempted us, we
|
||||
# take that object and discard ours.
|
||||
# WARNING: We are relying on setdefault() being atomic. This is true
|
||||
# in CPython but we haven't investigated others. This warning appears
|
||||
# in several other locations in this file.
|
||||
field_value = self._fields.setdefault(field, field_value)
|
||||
return field_value</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>Methods</h3>
|
||||
<dl>
|
||||
<dt id="meshtastic.storeforward_pb2.StoreAndForward.ByteSize"><code class="name flex">
|
||||
<span>def <span class="ident">ByteSize</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def ByteSize(self):
|
||||
if not self._cached_byte_size_dirty:
|
||||
return self._cached_byte_size
|
||||
|
||||
size = 0
|
||||
descriptor = self.DESCRIPTOR
|
||||
if descriptor.GetOptions().map_entry:
|
||||
# Fields of map entry should always be serialized.
|
||||
size = descriptor.fields_by_name['key']._sizer(self.key)
|
||||
size += descriptor.fields_by_name['value']._sizer(self.value)
|
||||
else:
|
||||
for field_descriptor, field_value in self.ListFields():
|
||||
size += field_descriptor._sizer(field_value)
|
||||
for tag_bytes, value_bytes in self._unknown_fields:
|
||||
size += len(tag_bytes) + len(value_bytes)
|
||||
|
||||
self._cached_byte_size = size
|
||||
self._cached_byte_size_dirty = False
|
||||
self._listener_for_children.dirty = False
|
||||
return size</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.storeforward_pb2.StoreAndForward.Clear"><code class="name flex">
|
||||
<span>def <span class="ident">Clear</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def _Clear(self):
|
||||
# Clear fields.
|
||||
self._fields = {}
|
||||
self._unknown_fields = ()
|
||||
# pylint: disable=protected-access
|
||||
if self._unknown_field_set is not None:
|
||||
self._unknown_field_set._clear()
|
||||
self._unknown_field_set = None
|
||||
|
||||
self._oneofs = {}
|
||||
self._Modified()</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.storeforward_pb2.StoreAndForward.ClearField"><code class="name flex">
|
||||
<span>def <span class="ident">ClearField</span></span>(<span>self, field_name)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def ClearField(self, field_name):
|
||||
try:
|
||||
field = message_descriptor.fields_by_name[field_name]
|
||||
except KeyError:
|
||||
try:
|
||||
field = message_descriptor.oneofs_by_name[field_name]
|
||||
if field in self._oneofs:
|
||||
field = self._oneofs[field]
|
||||
else:
|
||||
return
|
||||
except KeyError:
|
||||
raise ValueError('Protocol message %s has no "%s" field.' %
|
||||
(message_descriptor.name, field_name))
|
||||
|
||||
if field in self._fields:
|
||||
# To match the C++ implementation, we need to invalidate iterators
|
||||
# for map fields when ClearField() happens.
|
||||
if hasattr(self._fields[field], 'InvalidateIterators'):
|
||||
self._fields[field].InvalidateIterators()
|
||||
|
||||
# Note: If the field is a sub-message, its listener will still point
|
||||
# at us. That's fine, because the worst than can happen is that it
|
||||
# will call _Modified() and invalidate our byte size. Big deal.
|
||||
del self._fields[field]
|
||||
|
||||
if self._oneofs.get(field.containing_oneof, None) is field:
|
||||
del self._oneofs[field.containing_oneof]
|
||||
|
||||
# Always call _Modified() -- even if nothing was changed, this is
|
||||
# a mutating method, and thus calling it should cause the field to become
|
||||
# present in the parent message.
|
||||
self._Modified()</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.storeforward_pb2.StoreAndForward.DiscardUnknownFields"><code class="name flex">
|
||||
<span>def <span class="ident">DiscardUnknownFields</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def _DiscardUnknownFields(self):
|
||||
self._unknown_fields = []
|
||||
self._unknown_field_set = None # pylint: disable=protected-access
|
||||
for field, value in self.ListFields():
|
||||
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
|
||||
if _IsMapField(field):
|
||||
if _IsMessageMapField(field):
|
||||
for key in value:
|
||||
value[key].DiscardUnknownFields()
|
||||
elif field.label == _FieldDescriptor.LABEL_REPEATED:
|
||||
for sub_message in value:
|
||||
sub_message.DiscardUnknownFields()
|
||||
else:
|
||||
value.DiscardUnknownFields()</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.storeforward_pb2.StoreAndForward.FindInitializationErrors"><code class="name flex">
|
||||
<span>def <span class="ident">FindInitializationErrors</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Finds required fields which are not initialized.</p>
|
||||
<h2 id="returns">Returns</h2>
|
||||
<p>A list of strings.
|
||||
Each string is a path to an uninitialized field from
|
||||
the top-level message, e.g. "foo.bar[5].baz".</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def FindInitializationErrors(self):
|
||||
"""Finds required fields which are not initialized.
|
||||
|
||||
Returns:
|
||||
A list of strings. Each string is a path to an uninitialized field from
|
||||
the top-level message, e.g. "foo.bar[5].baz".
|
||||
"""
|
||||
|
||||
errors = [] # simplify things
|
||||
|
||||
for field in required_fields:
|
||||
if not self.HasField(field.name):
|
||||
errors.append(field.name)
|
||||
|
||||
for field, value in self.ListFields():
|
||||
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
|
||||
if field.is_extension:
|
||||
name = '(%s)' % field.full_name
|
||||
else:
|
||||
name = field.name
|
||||
|
||||
if _IsMapField(field):
|
||||
if _IsMessageMapField(field):
|
||||
for key in value:
|
||||
element = value[key]
|
||||
prefix = '%s[%s].' % (name, key)
|
||||
sub_errors = element.FindInitializationErrors()
|
||||
errors += [prefix + error for error in sub_errors]
|
||||
else:
|
||||
# ScalarMaps can't have any initialization errors.
|
||||
pass
|
||||
elif field.label == _FieldDescriptor.LABEL_REPEATED:
|
||||
for i in range(len(value)):
|
||||
element = value[i]
|
||||
prefix = '%s[%d].' % (name, i)
|
||||
sub_errors = element.FindInitializationErrors()
|
||||
errors += [prefix + error for error in sub_errors]
|
||||
else:
|
||||
prefix = name + '.'
|
||||
sub_errors = value.FindInitializationErrors()
|
||||
errors += [prefix + error for error in sub_errors]
|
||||
|
||||
return errors</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.storeforward_pb2.StoreAndForward.HasField"><code class="name flex">
|
||||
<span>def <span class="ident">HasField</span></span>(<span>self, field_name)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def HasField(self, field_name):
|
||||
try:
|
||||
field = hassable_fields[field_name]
|
||||
except KeyError:
|
||||
raise ValueError(error_msg % (message_descriptor.full_name, field_name))
|
||||
|
||||
if isinstance(field, descriptor_mod.OneofDescriptor):
|
||||
try:
|
||||
return HasField(self, self._oneofs[field].name)
|
||||
except KeyError:
|
||||
return False
|
||||
else:
|
||||
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
|
||||
value = self._fields.get(field)
|
||||
return value is not None and value._is_present_in_parent
|
||||
else:
|
||||
return field in self._fields</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.storeforward_pb2.StoreAndForward.IsInitialized"><code class="name flex">
|
||||
<span>def <span class="ident">IsInitialized</span></span>(<span>self, errors=None)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Checks if all required fields of a message are set.</p>
|
||||
<h2 id="args">Args</h2>
|
||||
<dl>
|
||||
<dt><strong><code>errors</code></strong></dt>
|
||||
<dd>A list which, if provided, will be populated with the field
|
||||
paths of all missing required fields.</dd>
|
||||
</dl>
|
||||
<h2 id="returns">Returns</h2>
|
||||
<p>True iff the specified message has all required fields set.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def IsInitialized(self, errors=None):
|
||||
"""Checks if all required fields of a message are set.
|
||||
|
||||
Args:
|
||||
errors: A list which, if provided, will be populated with the field
|
||||
paths of all missing required fields.
|
||||
|
||||
Returns:
|
||||
True iff the specified message has all required fields set.
|
||||
"""
|
||||
|
||||
# Performance is critical so we avoid HasField() and ListFields().
|
||||
|
||||
for field in required_fields:
|
||||
if (field not in self._fields or
|
||||
(field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE and
|
||||
not self._fields[field]._is_present_in_parent)):
|
||||
if errors is not None:
|
||||
errors.extend(self.FindInitializationErrors())
|
||||
return False
|
||||
|
||||
for field, value in list(self._fields.items()): # dict can change size!
|
||||
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
|
||||
if field.label == _FieldDescriptor.LABEL_REPEATED:
|
||||
if (field.message_type.has_options and
|
||||
field.message_type.GetOptions().map_entry):
|
||||
continue
|
||||
for element in value:
|
||||
if not element.IsInitialized():
|
||||
if errors is not None:
|
||||
errors.extend(self.FindInitializationErrors())
|
||||
return False
|
||||
elif value._is_present_in_parent and not value.IsInitialized():
|
||||
if errors is not None:
|
||||
errors.extend(self.FindInitializationErrors())
|
||||
return False
|
||||
|
||||
return True</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.storeforward_pb2.StoreAndForward.ListFields"><code class="name flex">
|
||||
<span>def <span class="ident">ListFields</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def ListFields(self):
|
||||
all_fields = [item for item in self._fields.items() if _IsPresent(item)]
|
||||
all_fields.sort(key = lambda item: item[0].number)
|
||||
return all_fields</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.storeforward_pb2.StoreAndForward.MergeFrom"><code class="name flex">
|
||||
<span>def <span class="ident">MergeFrom</span></span>(<span>self, msg)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def MergeFrom(self, msg):
|
||||
if not isinstance(msg, cls):
|
||||
raise TypeError(
|
||||
'Parameter to MergeFrom() must be instance of same class: '
|
||||
'expected %s got %s.' % (_FullyQualifiedClassName(cls),
|
||||
_FullyQualifiedClassName(msg.__class__)))
|
||||
|
||||
assert msg is not self
|
||||
self._Modified()
|
||||
|
||||
fields = self._fields
|
||||
|
||||
for field, value in msg._fields.items():
|
||||
if field.label == LABEL_REPEATED:
|
||||
field_value = fields.get(field)
|
||||
if field_value is None:
|
||||
# Construct a new object to represent this field.
|
||||
field_value = field._default_constructor(self)
|
||||
fields[field] = field_value
|
||||
field_value.MergeFrom(value)
|
||||
elif field.cpp_type == CPPTYPE_MESSAGE:
|
||||
if value._is_present_in_parent:
|
||||
field_value = fields.get(field)
|
||||
if field_value is None:
|
||||
# Construct a new object to represent this field.
|
||||
field_value = field._default_constructor(self)
|
||||
fields[field] = field_value
|
||||
field_value.MergeFrom(value)
|
||||
else:
|
||||
self._fields[field] = value
|
||||
if field.containing_oneof:
|
||||
self._UpdateOneofState(field)
|
||||
|
||||
if msg._unknown_fields:
|
||||
if not self._unknown_fields:
|
||||
self._unknown_fields = []
|
||||
self._unknown_fields.extend(msg._unknown_fields)
|
||||
# pylint: disable=protected-access
|
||||
if self._unknown_field_set is None:
|
||||
self._unknown_field_set = containers.UnknownFieldSet()
|
||||
self._unknown_field_set._extend(msg._unknown_field_set)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.storeforward_pb2.StoreAndForward.MergeFromString"><code class="name flex">
|
||||
<span>def <span class="ident">MergeFromString</span></span>(<span>self, serialized)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def MergeFromString(self, serialized):
|
||||
serialized = memoryview(serialized)
|
||||
length = len(serialized)
|
||||
try:
|
||||
if self._InternalParse(serialized, 0, length) != length:
|
||||
# The only reason _InternalParse would return early is if it
|
||||
# encountered an end-group tag.
|
||||
raise message_mod.DecodeError('Unexpected end-group tag.')
|
||||
except (IndexError, TypeError):
|
||||
# Now ord(buf[p:p+1]) == ord('') gets TypeError.
|
||||
raise message_mod.DecodeError('Truncated message.')
|
||||
except struct.error as e:
|
||||
raise message_mod.DecodeError(e)
|
||||
return length # Return this for legacy reasons.</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.storeforward_pb2.StoreAndForward.SerializePartialToString"><code class="name flex">
|
||||
<span>def <span class="ident">SerializePartialToString</span></span>(<span>self, **kwargs)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def SerializePartialToString(self, **kwargs):
|
||||
out = BytesIO()
|
||||
self._InternalSerialize(out.write, **kwargs)
|
||||
return out.getvalue()</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.storeforward_pb2.StoreAndForward.SerializeToString"><code class="name flex">
|
||||
<span>def <span class="ident">SerializeToString</span></span>(<span>self, **kwargs)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def SerializeToString(self, **kwargs):
|
||||
# Check if the message has all of its required fields set.
|
||||
if not self.IsInitialized():
|
||||
raise message_mod.EncodeError(
|
||||
'Message %s is missing required fields: %s' % (
|
||||
self.DESCRIPTOR.full_name, ','.join(self.FindInitializationErrors())))
|
||||
return self.SerializePartialToString(**kwargs)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.storeforward_pb2.StoreAndForward.SetInParent"><code class="name flex">
|
||||
<span>def <span class="ident">SetInParent</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Sets the _cached_byte_size_dirty bit to true,
|
||||
and propagates this to our listener iff this was a state change.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def Modified(self):
|
||||
"""Sets the _cached_byte_size_dirty bit to true,
|
||||
and propagates this to our listener iff this was a state change.
|
||||
"""
|
||||
|
||||
# Note: Some callers check _cached_byte_size_dirty before calling
|
||||
# _Modified() as an extra optimization. So, if this method is ever
|
||||
# changed such that it does stuff even when _cached_byte_size_dirty is
|
||||
# already true, the callers need to be updated.
|
||||
if not self._cached_byte_size_dirty:
|
||||
self._cached_byte_size_dirty = True
|
||||
self._listener_for_children.dirty = True
|
||||
self._is_present_in_parent = True
|
||||
self._listener.Modified()</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.storeforward_pb2.StoreAndForward.UnknownFields"><code class="name flex">
|
||||
<span>def <span class="ident">UnknownFields</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def _UnknownFields(self):
|
||||
if self._unknown_field_set is None: # pylint: disable=protected-access
|
||||
# pylint: disable=protected-access
|
||||
self._unknown_field_set = containers.UnknownFieldSet()
|
||||
return self._unknown_field_set # pylint: disable=protected-access</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.storeforward_pb2.StoreAndForward.WhichOneof"><code class="name flex">
|
||||
<span>def <span class="ident">WhichOneof</span></span>(<span>self, oneof_name)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Returns the name of the currently set field inside a oneof, or None.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def WhichOneof(self, oneof_name):
|
||||
"""Returns the name of the currently set field inside a oneof, or None."""
|
||||
try:
|
||||
field = message_descriptor.oneofs_by_name[oneof_name]
|
||||
except KeyError:
|
||||
raise ValueError(
|
||||
'Protocol message has no oneof "%s" field.' % oneof_name)
|
||||
|
||||
nested_field = self._oneofs.get(field, None)
|
||||
if nested_field is not None and self.HasField(nested_field.name):
|
||||
return nested_field.name
|
||||
else:
|
||||
return None</code></pre>
|
||||
</details>
|
||||
<div class="desc"><p>Field StoreAndForward.stats</p></div>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
@@ -995,42 +432,22 @@ and propagates this to our listener iff this was a state change.</p></div>
|
||||
<ul>
|
||||
<li>
|
||||
<h4><code><a title="meshtastic.storeforward_pb2.StoreAndForward" href="#meshtastic.storeforward_pb2.StoreAndForward">StoreAndForward</a></code></h4>
|
||||
<ul class="">
|
||||
<li><code><a title="meshtastic.storeforward_pb2.StoreAndForward.ByteSize" href="#meshtastic.storeforward_pb2.StoreAndForward.ByteSize">ByteSize</a></code></li>
|
||||
<ul class="two-column">
|
||||
<li><code><a title="meshtastic.storeforward_pb2.StoreAndForward.CLIENT_ERROR" href="#meshtastic.storeforward_pb2.StoreAndForward.CLIENT_ERROR">CLIENT_ERROR</a></code></li>
|
||||
<li><code><a title="meshtastic.storeforward_pb2.StoreAndForward.CLIENT_HISTORY" href="#meshtastic.storeforward_pb2.StoreAndForward.CLIENT_HISTORY">CLIENT_HISTORY</a></code></li>
|
||||
<li><code><a title="meshtastic.storeforward_pb2.StoreAndForward.CLIENT_PING" href="#meshtastic.storeforward_pb2.StoreAndForward.CLIENT_PING">CLIENT_PING</a></code></li>
|
||||
<li><code><a title="meshtastic.storeforward_pb2.StoreAndForward.CLIENT_PONG" href="#meshtastic.storeforward_pb2.StoreAndForward.CLIENT_PONG">CLIENT_PONG</a></code></li>
|
||||
<li><code><a title="meshtastic.storeforward_pb2.StoreAndForward.CLIENT_STATS" href="#meshtastic.storeforward_pb2.StoreAndForward.CLIENT_STATS">CLIENT_STATS</a></code></li>
|
||||
<li><code><a title="meshtastic.storeforward_pb2.StoreAndForward.Clear" href="#meshtastic.storeforward_pb2.StoreAndForward.Clear">Clear</a></code></li>
|
||||
<li><code><a title="meshtastic.storeforward_pb2.StoreAndForward.ClearField" href="#meshtastic.storeforward_pb2.StoreAndForward.ClearField">ClearField</a></code></li>
|
||||
<li><code><a title="meshtastic.storeforward_pb2.StoreAndForward.DESCRIPTOR" href="#meshtastic.storeforward_pb2.StoreAndForward.DESCRIPTOR">DESCRIPTOR</a></code></li>
|
||||
<li><code><a title="meshtastic.storeforward_pb2.StoreAndForward.DiscardUnknownFields" href="#meshtastic.storeforward_pb2.StoreAndForward.DiscardUnknownFields">DiscardUnknownFields</a></code></li>
|
||||
<li><code><a title="meshtastic.storeforward_pb2.StoreAndForward.FindInitializationErrors" href="#meshtastic.storeforward_pb2.StoreAndForward.FindInitializationErrors">FindInitializationErrors</a></code></li>
|
||||
<li><code><a title="meshtastic.storeforward_pb2.StoreAndForward.FromString" href="#meshtastic.storeforward_pb2.StoreAndForward.FromString">FromString</a></code></li>
|
||||
<li><code><a title="meshtastic.storeforward_pb2.StoreAndForward.HISTORY_FIELD_NUMBER" href="#meshtastic.storeforward_pb2.StoreAndForward.HISTORY_FIELD_NUMBER">HISTORY_FIELD_NUMBER</a></code></li>
|
||||
<li><code><a title="meshtastic.storeforward_pb2.StoreAndForward.HasField" href="#meshtastic.storeforward_pb2.StoreAndForward.HasField">HasField</a></code></li>
|
||||
<li><code><a title="meshtastic.storeforward_pb2.StoreAndForward.History" href="#meshtastic.storeforward_pb2.StoreAndForward.History">History</a></code></li>
|
||||
<li><code><a title="meshtastic.storeforward_pb2.StoreAndForward.IsInitialized" href="#meshtastic.storeforward_pb2.StoreAndForward.IsInitialized">IsInitialized</a></code></li>
|
||||
<li><code><a title="meshtastic.storeforward_pb2.StoreAndForward.ListFields" href="#meshtastic.storeforward_pb2.StoreAndForward.ListFields">ListFields</a></code></li>
|
||||
<li><code><a title="meshtastic.storeforward_pb2.StoreAndForward.MergeFrom" href="#meshtastic.storeforward_pb2.StoreAndForward.MergeFrom">MergeFrom</a></code></li>
|
||||
<li><code><a title="meshtastic.storeforward_pb2.StoreAndForward.MergeFromString" href="#meshtastic.storeforward_pb2.StoreAndForward.MergeFromString">MergeFromString</a></code></li>
|
||||
<li><code><a title="meshtastic.storeforward_pb2.StoreAndForward.ROUTER_BUSY" href="#meshtastic.storeforward_pb2.StoreAndForward.ROUTER_BUSY">ROUTER_BUSY</a></code></li>
|
||||
<li><code><a title="meshtastic.storeforward_pb2.StoreAndForward.ROUTER_ERROR" href="#meshtastic.storeforward_pb2.StoreAndForward.ROUTER_ERROR">ROUTER_ERROR</a></code></li>
|
||||
<li><code><a title="meshtastic.storeforward_pb2.StoreAndForward.ROUTER_HEARTBEAT" href="#meshtastic.storeforward_pb2.StoreAndForward.ROUTER_HEARTBEAT">ROUTER_HEARTBEAT</a></code></li>
|
||||
<li><code><a title="meshtastic.storeforward_pb2.StoreAndForward.ROUTER_PING" href="#meshtastic.storeforward_pb2.StoreAndForward.ROUTER_PING">ROUTER_PING</a></code></li>
|
||||
<li><code><a title="meshtastic.storeforward_pb2.StoreAndForward.ROUTER_PONG" href="#meshtastic.storeforward_pb2.StoreAndForward.ROUTER_PONG">ROUTER_PONG</a></code></li>
|
||||
<li><code><a title="meshtastic.storeforward_pb2.StoreAndForward.RR_FIELD_NUMBER" href="#meshtastic.storeforward_pb2.StoreAndForward.RR_FIELD_NUMBER">RR_FIELD_NUMBER</a></code></li>
|
||||
<li><code><a title="meshtastic.storeforward_pb2.StoreAndForward.RegisterExtension" href="#meshtastic.storeforward_pb2.StoreAndForward.RegisterExtension">RegisterExtension</a></code></li>
|
||||
<li><code><a title="meshtastic.storeforward_pb2.StoreAndForward.RequestResponse" href="#meshtastic.storeforward_pb2.StoreAndForward.RequestResponse">RequestResponse</a></code></li>
|
||||
<li><code><a title="meshtastic.storeforward_pb2.StoreAndForward.STATS_FIELD_NUMBER" href="#meshtastic.storeforward_pb2.StoreAndForward.STATS_FIELD_NUMBER">STATS_FIELD_NUMBER</a></code></li>
|
||||
<li><code><a title="meshtastic.storeforward_pb2.StoreAndForward.SerializePartialToString" href="#meshtastic.storeforward_pb2.StoreAndForward.SerializePartialToString">SerializePartialToString</a></code></li>
|
||||
<li><code><a title="meshtastic.storeforward_pb2.StoreAndForward.SerializeToString" href="#meshtastic.storeforward_pb2.StoreAndForward.SerializeToString">SerializeToString</a></code></li>
|
||||
<li><code><a title="meshtastic.storeforward_pb2.StoreAndForward.SetInParent" href="#meshtastic.storeforward_pb2.StoreAndForward.SetInParent">SetInParent</a></code></li>
|
||||
<li><code><a title="meshtastic.storeforward_pb2.StoreAndForward.Statistics" href="#meshtastic.storeforward_pb2.StoreAndForward.Statistics">Statistics</a></code></li>
|
||||
<li><code><a title="meshtastic.storeforward_pb2.StoreAndForward.UNSET" href="#meshtastic.storeforward_pb2.StoreAndForward.UNSET">UNSET</a></code></li>
|
||||
<li><code><a title="meshtastic.storeforward_pb2.StoreAndForward.UnknownFields" href="#meshtastic.storeforward_pb2.StoreAndForward.UnknownFields">UnknownFields</a></code></li>
|
||||
<li><code><a title="meshtastic.storeforward_pb2.StoreAndForward.WhichOneof" href="#meshtastic.storeforward_pb2.StoreAndForward.WhichOneof">WhichOneof</a></code></li>
|
||||
<li><code><a title="meshtastic.storeforward_pb2.StoreAndForward.history" href="#meshtastic.storeforward_pb2.StoreAndForward.history">history</a></code></li>
|
||||
<li><code><a title="meshtastic.storeforward_pb2.StoreAndForward.rr" href="#meshtastic.storeforward_pb2.StoreAndForward.rr">rr</a></code></li>
|
||||
<li><code><a title="meshtastic.storeforward_pb2.StoreAndForward.stats" href="#meshtastic.storeforward_pb2.StoreAndForward.stats">stats</a></code></li>
|
||||
|
||||
@@ -53,7 +53,6 @@ class StreamInterface(MeshInterface):
|
||||
"""Constructor, opens a connection to self.stream
|
||||
|
||||
Keyword Arguments:
|
||||
devPath {string} -- A filepath to a device, i.e. /dev/ttyUSB0 (default: {None})
|
||||
debugOut {stream} -- If a stream is provided, any debug serial output from the
|
||||
device will be emitted to that stream. (default: {None})
|
||||
|
||||
@@ -62,15 +61,14 @@ class StreamInterface(MeshInterface):
|
||||
Exception: [description]
|
||||
"""
|
||||
|
||||
if not hasattr(self, 'stream'):
|
||||
if not hasattr(self, 'stream') and not noProto:
|
||||
raise Exception(
|
||||
"StreamInterface is now abstract (to update existing code create SerialInterface instead)")
|
||||
self._rxBuf = bytes() # empty
|
||||
self._wantExit = False
|
||||
|
||||
# FIXME, figure out why daemon=True causes reader thread to exit too early
|
||||
self._rxThread = threading.Thread(
|
||||
target=self.__reader, args=(), daemon=True)
|
||||
self._rxThread = threading.Thread(target=self.__reader, args=(), daemon=True)
|
||||
|
||||
MeshInterface.__init__(self, debugOut=debugOut, noProto=noProto)
|
||||
|
||||
@@ -122,7 +120,10 @@ class StreamInterface(MeshInterface):
|
||||
|
||||
def _readBytes(self, length):
|
||||
"""Read an array of bytes from our stream"""
|
||||
return self.stream.read(length)
|
||||
if self.stream:
|
||||
return self.stream.read(length)
|
||||
else:
|
||||
return None
|
||||
|
||||
def _sendToRadioImpl(self, toRadio):
|
||||
"""Send a ToRadio protobuf to the device"""
|
||||
@@ -131,6 +132,7 @@ class StreamInterface(MeshInterface):
|
||||
bufLen = len(b)
|
||||
# We convert into a string, because the TCP code doesn't work with byte arrays
|
||||
header = bytes([START1, START2, (bufLen >> 8) & 0xff, bufLen & 0xff])
|
||||
logging.debug(f'sending header:{header} b:{b}')
|
||||
self._writeBytes(header + b)
|
||||
|
||||
def close(self):
|
||||
@@ -145,16 +147,18 @@ class StreamInterface(MeshInterface):
|
||||
|
||||
def __reader(self):
|
||||
"""The reader thread that reads bytes from our stream"""
|
||||
logging.debug('in __reader()')
|
||||
empty = bytes()
|
||||
|
||||
try:
|
||||
while not self._wantExit:
|
||||
# logging.debug("reading character")
|
||||
logging.debug("reading character")
|
||||
b = self._readBytes(1)
|
||||
# logging.debug("In reader loop")
|
||||
# logging.debug(f"read returned {b}")
|
||||
logging.debug("In reader loop")
|
||||
#logging.debug(f"read returned {b}")
|
||||
if len(b) > 0:
|
||||
c = b[0]
|
||||
#logging.debug(f'c:{c}')
|
||||
ptr = len(self._rxBuf)
|
||||
|
||||
# Assume we want to append this byte, fixme use bytearray instead
|
||||
@@ -173,12 +177,13 @@ class StreamInterface(MeshInterface):
|
||||
if c != START2:
|
||||
self._rxBuf = empty # failed to find start2
|
||||
elif ptr >= HEADER_LEN - 1: # we've at least got a header
|
||||
# big endian length follos header
|
||||
#logging.debug('at least we received a header')
|
||||
# big endian length follows header
|
||||
packetlen = (self._rxBuf[2] << 8) + self._rxBuf[3]
|
||||
|
||||
if ptr == HEADER_LEN - 1: # we _just_ finished reading the header, validate length
|
||||
if packetlen > MAX_TO_FROM_RADIO_SIZE:
|
||||
self._rxBuf = empty # length ws out out bounds, restart
|
||||
self._rxBuf = empty # length was out out bounds, restart
|
||||
|
||||
if len(self._rxBuf) != 0 and ptr + 1 >= packetlen + HEADER_LEN:
|
||||
try:
|
||||
@@ -220,7 +225,6 @@ class StreamInterface(MeshInterface):
|
||||
<div class="desc"><p>Interface class for meshtastic devices over a stream link (serial, TCP, etc)</p>
|
||||
<p>Constructor, opens a connection to self.stream</p>
|
||||
<p>Keyword Arguments:
|
||||
devPath {string} – A filepath to a device, i.e. /dev/ttyUSB0 (default: {None})
|
||||
debugOut {stream} – If a stream is provided, any debug serial output from the
|
||||
device will be emitted to that stream. (default: {None})</p>
|
||||
<h2 id="raises">Raises</h2>
|
||||
@@ -241,7 +245,6 @@ device will be emitted to that stream. (default: {None})</p>
|
||||
"""Constructor, opens a connection to self.stream
|
||||
|
||||
Keyword Arguments:
|
||||
devPath {string} -- A filepath to a device, i.e. /dev/ttyUSB0 (default: {None})
|
||||
debugOut {stream} -- If a stream is provided, any debug serial output from the
|
||||
device will be emitted to that stream. (default: {None})
|
||||
|
||||
@@ -250,15 +253,14 @@ device will be emitted to that stream. (default: {None})</p>
|
||||
Exception: [description]
|
||||
"""
|
||||
|
||||
if not hasattr(self, 'stream'):
|
||||
if not hasattr(self, 'stream') and not noProto:
|
||||
raise Exception(
|
||||
"StreamInterface is now abstract (to update existing code create SerialInterface instead)")
|
||||
self._rxBuf = bytes() # empty
|
||||
self._wantExit = False
|
||||
|
||||
# FIXME, figure out why daemon=True causes reader thread to exit too early
|
||||
self._rxThread = threading.Thread(
|
||||
target=self.__reader, args=(), daemon=True)
|
||||
self._rxThread = threading.Thread(target=self.__reader, args=(), daemon=True)
|
||||
|
||||
MeshInterface.__init__(self, debugOut=debugOut, noProto=noProto)
|
||||
|
||||
@@ -310,7 +312,10 @@ device will be emitted to that stream. (default: {None})</p>
|
||||
|
||||
def _readBytes(self, length):
|
||||
"""Read an array of bytes from our stream"""
|
||||
return self.stream.read(length)
|
||||
if self.stream:
|
||||
return self.stream.read(length)
|
||||
else:
|
||||
return None
|
||||
|
||||
def _sendToRadioImpl(self, toRadio):
|
||||
"""Send a ToRadio protobuf to the device"""
|
||||
@@ -319,6 +324,7 @@ device will be emitted to that stream. (default: {None})</p>
|
||||
bufLen = len(b)
|
||||
# We convert into a string, because the TCP code doesn't work with byte arrays
|
||||
header = bytes([START1, START2, (bufLen >> 8) & 0xff, bufLen & 0xff])
|
||||
logging.debug(f'sending header:{header} b:{b}')
|
||||
self._writeBytes(header + b)
|
||||
|
||||
def close(self):
|
||||
@@ -333,16 +339,18 @@ device will be emitted to that stream. (default: {None})</p>
|
||||
|
||||
def __reader(self):
|
||||
"""The reader thread that reads bytes from our stream"""
|
||||
logging.debug('in __reader()')
|
||||
empty = bytes()
|
||||
|
||||
try:
|
||||
while not self._wantExit:
|
||||
# logging.debug("reading character")
|
||||
logging.debug("reading character")
|
||||
b = self._readBytes(1)
|
||||
# logging.debug("In reader loop")
|
||||
# logging.debug(f"read returned {b}")
|
||||
logging.debug("In reader loop")
|
||||
#logging.debug(f"read returned {b}")
|
||||
if len(b) > 0:
|
||||
c = b[0]
|
||||
#logging.debug(f'c:{c}')
|
||||
ptr = len(self._rxBuf)
|
||||
|
||||
# Assume we want to append this byte, fixme use bytearray instead
|
||||
@@ -361,12 +369,13 @@ device will be emitted to that stream. (default: {None})</p>
|
||||
if c != START2:
|
||||
self._rxBuf = empty # failed to find start2
|
||||
elif ptr >= HEADER_LEN - 1: # we've at least got a header
|
||||
# big endian length follos header
|
||||
#logging.debug('at least we received a header')
|
||||
# big endian length follows header
|
||||
packetlen = (self._rxBuf[2] << 8) + self._rxBuf[3]
|
||||
|
||||
if ptr == HEADER_LEN - 1: # we _just_ finished reading the header, validate length
|
||||
if packetlen > MAX_TO_FROM_RADIO_SIZE:
|
||||
self._rxBuf = empty # length ws out out bounds, restart
|
||||
self._rxBuf = empty # length was out out bounds, restart
|
||||
|
||||
if len(self._rxBuf) != 0 and ptr + 1 >= packetlen + HEADER_LEN:
|
||||
try:
|
||||
|
||||
@@ -46,18 +46,29 @@ class TCPInterface(StreamInterface):
|
||||
hostname {string} -- Hostname/IP address of the device to connect to
|
||||
"""
|
||||
|
||||
logging.debug(f"Connecting to {hostname}")
|
||||
|
||||
server_address = (hostname, portNumber)
|
||||
sock = socket.create_connection(server_address)
|
||||
|
||||
# Instead of wrapping as a stream, we use the native socket API
|
||||
# self.stream = sock.makefile('rw')
|
||||
self.stream = None
|
||||
self.socket = sock
|
||||
|
||||
StreamInterface.__init__(
|
||||
self, debugOut=debugOut, noProto=noProto, connectNow=connectNow)
|
||||
self.hostname = hostname
|
||||
self.portNumber = portNumber
|
||||
|
||||
if connectNow:
|
||||
logging.debug(f"Connecting to {hostname}")
|
||||
server_address = (hostname, portNumber)
|
||||
sock = socket.create_connection(server_address)
|
||||
self.socket = sock
|
||||
else:
|
||||
self.socket = None
|
||||
|
||||
StreamInterface.__init__(self, debugOut=debugOut, noProto=noProto,
|
||||
connectNow=connectNow)
|
||||
|
||||
def myConnect(self):
|
||||
"""Connect to socket"""
|
||||
server_address = (self.hostname, self.portNumber)
|
||||
sock = socket.create_connection(server_address)
|
||||
self.socket = sock
|
||||
|
||||
def close(self):
|
||||
"""Close a connection to the device"""
|
||||
@@ -115,18 +126,29 @@ hostname {string} – Hostname/IP address of the device to connect to</p></d
|
||||
hostname {string} -- Hostname/IP address of the device to connect to
|
||||
"""
|
||||
|
||||
logging.debug(f"Connecting to {hostname}")
|
||||
|
||||
server_address = (hostname, portNumber)
|
||||
sock = socket.create_connection(server_address)
|
||||
|
||||
# Instead of wrapping as a stream, we use the native socket API
|
||||
# self.stream = sock.makefile('rw')
|
||||
self.stream = None
|
||||
self.socket = sock
|
||||
|
||||
StreamInterface.__init__(
|
||||
self, debugOut=debugOut, noProto=noProto, connectNow=connectNow)
|
||||
self.hostname = hostname
|
||||
self.portNumber = portNumber
|
||||
|
||||
if connectNow:
|
||||
logging.debug(f"Connecting to {hostname}")
|
||||
server_address = (hostname, portNumber)
|
||||
sock = socket.create_connection(server_address)
|
||||
self.socket = sock
|
||||
else:
|
||||
self.socket = None
|
||||
|
||||
StreamInterface.__init__(self, debugOut=debugOut, noProto=noProto,
|
||||
connectNow=connectNow)
|
||||
|
||||
def myConnect(self):
|
||||
"""Connect to socket"""
|
||||
server_address = (self.hostname, self.portNumber)
|
||||
sock = socket.create_connection(server_address)
|
||||
self.socket = sock
|
||||
|
||||
def close(self):
|
||||
"""Close a connection to the device"""
|
||||
@@ -155,6 +177,25 @@ hostname {string} – Hostname/IP address of the device to connect to</p></d
|
||||
<li><a title="meshtastic.stream_interface.StreamInterface" href="stream_interface.html#meshtastic.stream_interface.StreamInterface">StreamInterface</a></li>
|
||||
<li><a title="meshtastic.mesh_interface.MeshInterface" href="mesh_interface.html#meshtastic.mesh_interface.MeshInterface">MeshInterface</a></li>
|
||||
</ul>
|
||||
<h3>Methods</h3>
|
||||
<dl>
|
||||
<dt id="meshtastic.tcp_interface.TCPInterface.myConnect"><code class="name flex">
|
||||
<span>def <span class="ident">myConnect</span></span>(<span>self)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Connect to socket</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def myConnect(self):
|
||||
"""Connect to socket"""
|
||||
server_address = (self.hostname, self.portNumber)
|
||||
sock = socket.create_connection(server_address)
|
||||
self.socket = sock</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>Inherited members</h3>
|
||||
<ul class="hlist">
|
||||
<li><code><b><a title="meshtastic.stream_interface.StreamInterface" href="stream_interface.html#meshtastic.stream_interface.StreamInterface">StreamInterface</a></b></code>:
|
||||
@@ -194,6 +235,9 @@ hostname {string} – Hostname/IP address of the device to connect to</p></d
|
||||
<ul>
|
||||
<li>
|
||||
<h4><code><a title="meshtastic.tcp_interface.TCPInterface" href="#meshtastic.tcp_interface.TCPInterface">TCPInterface</a></code></h4>
|
||||
<ul class="">
|
||||
<li><code><a title="meshtastic.tcp_interface.TCPInterface.myConnect" href="#meshtastic.tcp_interface.TCPInterface.myConnect">myConnect</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
@@ -31,9 +31,12 @@
|
||||
|
||||
import argparse
|
||||
|
||||
from unittest.mock import MagicMock
|
||||
import pytest
|
||||
|
||||
from meshtastic.__main__ import Globals
|
||||
from ..mesh_interface import MeshInterface
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def reset_globals():
|
||||
@@ -41,7 +44,50 @@ def reset_globals():
|
||||
parser = None
|
||||
parser = argparse.ArgumentParser()
|
||||
Globals.getInstance().reset()
|
||||
Globals.getInstance().set_parser(parser)</code></pre>
|
||||
Globals.getInstance().set_parser(parser)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def iface_with_nodes():
|
||||
"""Fixture to setup some nodes."""
|
||||
nodesById = {
|
||||
'!9388f81c': {
|
||||
'num': 2475227164,
|
||||
'user': {
|
||||
'id': '!9388f81c',
|
||||
'longName': 'Unknown f81c',
|
||||
'shortName': '?1C',
|
||||
'macaddr': 'RBeTiPgc',
|
||||
'hwModel': 'TBEAM'
|
||||
},
|
||||
'position': {},
|
||||
'lastHeard': 1640204888
|
||||
}
|
||||
}
|
||||
|
||||
nodesByNum = {
|
||||
2475227164: {
|
||||
'num': 2475227164,
|
||||
'user': {
|
||||
'id': '!9388f81c',
|
||||
'longName': 'Unknown f81c',
|
||||
'shortName': '?1C',
|
||||
'macaddr': 'RBeTiPgc',
|
||||
'hwModel': 'TBEAM'
|
||||
},
|
||||
'position': {
|
||||
'time': 1640206266
|
||||
},
|
||||
'lastHeard': 1640206266
|
||||
}
|
||||
}
|
||||
iface = MeshInterface(noProto=True)
|
||||
iface.nodes = nodesById
|
||||
iface.nodesByNum = nodesByNum
|
||||
myInfo = MagicMock()
|
||||
iface.myInfo = myInfo
|
||||
iface.myInfo.my_node_num = 2475227164
|
||||
return iface</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
@@ -51,6 +97,58 @@ def reset_globals():
|
||||
<section>
|
||||
<h2 class="section-title" id="header-functions">Functions</h2>
|
||||
<dl>
|
||||
<dt id="meshtastic.tests.conftest.iface_with_nodes"><code class="name flex">
|
||||
<span>def <span class="ident">iface_with_nodes</span></span>(<span>)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Fixture to setup some nodes.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">@pytest.fixture
|
||||
def iface_with_nodes():
|
||||
"""Fixture to setup some nodes."""
|
||||
nodesById = {
|
||||
'!9388f81c': {
|
||||
'num': 2475227164,
|
||||
'user': {
|
||||
'id': '!9388f81c',
|
||||
'longName': 'Unknown f81c',
|
||||
'shortName': '?1C',
|
||||
'macaddr': 'RBeTiPgc',
|
||||
'hwModel': 'TBEAM'
|
||||
},
|
||||
'position': {},
|
||||
'lastHeard': 1640204888
|
||||
}
|
||||
}
|
||||
|
||||
nodesByNum = {
|
||||
2475227164: {
|
||||
'num': 2475227164,
|
||||
'user': {
|
||||
'id': '!9388f81c',
|
||||
'longName': 'Unknown f81c',
|
||||
'shortName': '?1C',
|
||||
'macaddr': 'RBeTiPgc',
|
||||
'hwModel': 'TBEAM'
|
||||
},
|
||||
'position': {
|
||||
'time': 1640206266
|
||||
},
|
||||
'lastHeard': 1640206266
|
||||
}
|
||||
}
|
||||
iface = MeshInterface(noProto=True)
|
||||
iface.nodes = nodesById
|
||||
iface.nodesByNum = nodesByNum
|
||||
myInfo = MagicMock()
|
||||
iface.myInfo = myInfo
|
||||
iface.myInfo.my_node_num = 2475227164
|
||||
return iface</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.tests.conftest.reset_globals"><code class="name flex">
|
||||
<span>def <span class="ident">reset_globals</span></span>(<span>)</span>
|
||||
</code></dt>
|
||||
@@ -87,6 +185,7 @@ def reset_globals():
|
||||
</li>
|
||||
<li><h3><a href="#header-functions">Functions</a></h3>
|
||||
<ul class="">
|
||||
<li><code><a title="meshtastic.tests.conftest.iface_with_nodes" href="#meshtastic.tests.conftest.iface_with_nodes">iface_with_nodes</a></code></li>
|
||||
<li><code><a title="meshtastic.tests.conftest.reset_globals" href="#meshtastic.tests.conftest.reset_globals">reset_globals</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
@@ -34,6 +34,12 @@
|
||||
<dd>
|
||||
<div class="desc"><p>Meshtastic unit tests for ble_interface.py</p></div>
|
||||
</dd>
|
||||
<dt><code class="name"><a title="meshtastic.tests.test_examples" href="test_examples.html">meshtastic.tests.test_examples</a></code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Meshtastic test that the examples run as expected.
|
||||
We assume you have a python virtual environment in current directory.
|
||||
If not, you need to run: …</p></div>
|
||||
</dd>
|
||||
<dt><code class="name"><a title="meshtastic.tests.test_globals" href="test_globals.html">meshtastic.tests.test_globals</a></code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Meshtastic unit tests for globals.py</p></div>
|
||||
@@ -54,6 +60,10 @@
|
||||
<dd>
|
||||
<div class="desc"><p>Meshtastic unit tests for node.py</p></div>
|
||||
</dd>
|
||||
<dt><code class="name"><a title="meshtastic.tests.test_remote_hardware" href="test_remote_hardware.html">meshtastic.tests.test_remote_hardware</a></code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Meshtastic unit tests for remote_hardware.py</p></div>
|
||||
</dd>
|
||||
<dt><code class="name"><a title="meshtastic.tests.test_serial_interface" href="test_serial_interface.html">meshtastic.tests.test_serial_interface</a></code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Meshtastic unit tests for serial_interface.py</p></div>
|
||||
@@ -106,11 +116,13 @@
|
||||
<ul>
|
||||
<li><code><a title="meshtastic.tests.conftest" href="conftest.html">meshtastic.tests.conftest</a></code></li>
|
||||
<li><code><a title="meshtastic.tests.test_ble_interface" href="test_ble_interface.html">meshtastic.tests.test_ble_interface</a></code></li>
|
||||
<li><code><a title="meshtastic.tests.test_examples" href="test_examples.html">meshtastic.tests.test_examples</a></code></li>
|
||||
<li><code><a title="meshtastic.tests.test_globals" href="test_globals.html">meshtastic.tests.test_globals</a></code></li>
|
||||
<li><code><a title="meshtastic.tests.test_int" href="test_int.html">meshtastic.tests.test_int</a></code></li>
|
||||
<li><code><a title="meshtastic.tests.test_main" href="test_main.html">meshtastic.tests.test_main</a></code></li>
|
||||
<li><code><a title="meshtastic.tests.test_mesh_interface" href="test_mesh_interface.html">meshtastic.tests.test_mesh_interface</a></code></li>
|
||||
<li><code><a title="meshtastic.tests.test_node" href="test_node.html">meshtastic.tests.test_node</a></code></li>
|
||||
<li><code><a title="meshtastic.tests.test_remote_hardware" href="test_remote_hardware.html">meshtastic.tests.test_remote_hardware</a></code></li>
|
||||
<li><code><a title="meshtastic.tests.test_serial_interface" href="test_serial_interface.html">meshtastic.tests.test_serial_interface</a></code></li>
|
||||
<li><code><a title="meshtastic.tests.test_smoke1" href="test_smoke1.html">meshtastic.tests.test_smoke1</a></code></li>
|
||||
<li><code><a title="meshtastic.tests.test_smoke2" href="test_smoke2.html">meshtastic.tests.test_smoke2</a></code></li>
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
|
||||
<meta name="generator" content="pdoc 0.10.0" />
|
||||
<title>meshtastic.tests.test_examples API documentation</title>
|
||||
<meta name="description" content="Meshtastic test that the examples run as expected.
|
||||
We assume you have a python virtual environment in current directory.
|
||||
If not, you need to run: …" />
|
||||
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
|
||||
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
|
||||
<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
|
||||
<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
|
||||
<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
|
||||
<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
|
||||
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
|
||||
<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<article id="content">
|
||||
<header>
|
||||
<h1 class="title">Module <code>meshtastic.tests.test_examples</code></h1>
|
||||
</header>
|
||||
<section id="section-intro">
|
||||
<p>Meshtastic test that the examples run as expected.
|
||||
We assume you have a python virtual environment in current directory.
|
||||
If not, you need to run: "python3 -m venv venv", "source venv/bin/activate", "pip install ."</p>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">"""Meshtastic test that the examples run as expected.
|
||||
We assume you have a python virtual environment in current directory.
|
||||
If not, you need to run: "python3 -m venv venv", "source venv/bin/activate", "pip install ."
|
||||
"""
|
||||
import subprocess
|
||||
|
||||
import pytest
|
||||
|
||||
@pytest.mark.examples
|
||||
def test_examples_hello_world_serial_no_arg():
|
||||
"""Test hello_world_serial without any args"""
|
||||
return_value, _ = subprocess.getstatusoutput('source venv/bin/activate; python3 examples/hello_world_serial.py')
|
||||
assert return_value == 3
|
||||
|
||||
|
||||
@pytest.mark.examples
|
||||
def test_examples_hello_world_serial_with_arg(capsys):
|
||||
"""Test hello_world_serial with arg"""
|
||||
return_value, _ = subprocess.getstatusoutput('source venv/bin/activate; python3 examples/hello_world_serial.py hello')
|
||||
assert return_value == 1
|
||||
_, err = capsys.readouterr()
|
||||
assert err == ''
|
||||
# TODO: Why does this not work?
|
||||
# assert out == 'Warning: No Meshtastic devices detected.'</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-functions">Functions</h2>
|
||||
<dl>
|
||||
<dt id="meshtastic.tests.test_examples.test_examples_hello_world_serial_no_arg"><code class="name flex">
|
||||
<span>def <span class="ident">test_examples_hello_world_serial_no_arg</span></span>(<span>)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Test hello_world_serial without any args</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">@pytest.mark.examples
|
||||
def test_examples_hello_world_serial_no_arg():
|
||||
"""Test hello_world_serial without any args"""
|
||||
return_value, _ = subprocess.getstatusoutput('source venv/bin/activate; python3 examples/hello_world_serial.py')
|
||||
assert return_value == 3</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.tests.test_examples.test_examples_hello_world_serial_with_arg"><code class="name flex">
|
||||
<span>def <span class="ident">test_examples_hello_world_serial_with_arg</span></span>(<span>capsys)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Test hello_world_serial with arg</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">@pytest.mark.examples
|
||||
def test_examples_hello_world_serial_with_arg(capsys):
|
||||
"""Test hello_world_serial with arg"""
|
||||
return_value, _ = subprocess.getstatusoutput('source venv/bin/activate; python3 examples/hello_world_serial.py hello')
|
||||
assert return_value == 1
|
||||
_, err = capsys.readouterr()
|
||||
assert err == ''
|
||||
# TODO: Why does this not work?
|
||||
# assert out == 'Warning: No Meshtastic devices detected.'</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
</article>
|
||||
<nav id="sidebar">
|
||||
<h1>Index</h1>
|
||||
<div class="toc">
|
||||
<ul></ul>
|
||||
</div>
|
||||
<ul id="index">
|
||||
<li><h3>Super-module</h3>
|
||||
<ul>
|
||||
<li><code><a title="meshtastic.tests" href="index.html">meshtastic.tests</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-functions">Functions</a></h3>
|
||||
<ul class="">
|
||||
<li><code><a title="meshtastic.tests.test_examples.test_examples_hello_world_serial_no_arg" href="#meshtastic.tests.test_examples.test_examples_hello_world_serial_no_arg">test_examples_hello_world_serial_no_arg</a></code></li>
|
||||
<li><code><a title="meshtastic.tests.test_examples.test_examples_hello_world_serial_with_arg" href="#meshtastic.tests.test_examples.test_examples_hello_world_serial_with_arg">test_examples_hello_world_serial_with_arg</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</main>
|
||||
<footer id="footer">
|
||||
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
+2026
-705
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,304 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
|
||||
<meta name="generator" content="pdoc 0.10.0" />
|
||||
<title>meshtastic.tests.test_remote_hardware API documentation</title>
|
||||
<meta name="description" content="Meshtastic unit tests for remote_hardware.py" />
|
||||
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
|
||||
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
|
||||
<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
|
||||
<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
|
||||
<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
|
||||
<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
|
||||
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
|
||||
<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<article id="content">
|
||||
<header>
|
||||
<h1 class="title">Module <code>meshtastic.tests.test_remote_hardware</code></h1>
|
||||
</header>
|
||||
<section id="section-intro">
|
||||
<p>Meshtastic unit tests for remote_hardware.py</p>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">"""Meshtastic unit tests for remote_hardware.py"""
|
||||
|
||||
import logging
|
||||
import re
|
||||
|
||||
from unittest.mock import patch, MagicMock
|
||||
import pytest
|
||||
|
||||
from ..remote_hardware import RemoteHardwareClient, onGPIOreceive
|
||||
from ..serial_interface import SerialInterface
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_RemoteHardwareClient():
|
||||
"""Test that we can instantiate a RemoteHardwareClient instance"""
|
||||
iface = MagicMock(autospec=SerialInterface)
|
||||
rhw = RemoteHardwareClient(iface)
|
||||
assert rhw.iface == iface
|
||||
iface.close()
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_onGPIOreceive(capsys):
|
||||
"""Test onGPIOreceive"""
|
||||
iface = MagicMock(autospec=SerialInterface)
|
||||
packet = {'decoded': {'remotehw': {'typ': 'foo', 'gpioValue': '4096' }}}
|
||||
onGPIOreceive(packet, iface)
|
||||
out, err = capsys.readouterr()
|
||||
assert re.search(r'Received RemoteHardware', out)
|
||||
assert err == ''
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_RemoteHardwareClient_no_gpio_channel(capsys):
|
||||
"""Test that we can instantiate a RemoteHardwareClient instance but there is no channel named channel 'gpio'"""
|
||||
iface = MagicMock(autospec=SerialInterface)
|
||||
with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
|
||||
mo.localNode.getChannelByName.return_value = None
|
||||
with pytest.raises(SystemExit) as pytest_wrapped_e:
|
||||
RemoteHardwareClient(mo)
|
||||
assert pytest_wrapped_e.type == SystemExit
|
||||
assert pytest_wrapped_e.value.code == 1
|
||||
out, err = capsys.readouterr()
|
||||
assert re.search(r'Warning: No channel named', out)
|
||||
assert err == ""
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_readGPIOs(caplog):
|
||||
"""Test readGPIOs"""
|
||||
iface = MagicMock(autospec=SerialInterface)
|
||||
rhw = RemoteHardwareClient(iface)
|
||||
with caplog.at_level(logging.DEBUG):
|
||||
rhw.readGPIOs('0x10', 123)
|
||||
assert re.search(r'readGPIOs', caplog.text, re.MULTILINE)
|
||||
iface.close()
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_writeGPIOs(caplog):
|
||||
"""Test writeGPIOs"""
|
||||
iface = MagicMock(autospec=SerialInterface)
|
||||
rhw = RemoteHardwareClient(iface)
|
||||
with caplog.at_level(logging.DEBUG):
|
||||
rhw.writeGPIOs('0x10', 123, 1)
|
||||
assert re.search(r'writeGPIOs', caplog.text, re.MULTILINE)
|
||||
iface.close()
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_watchGPIOs(caplog):
|
||||
"""Test watchGPIOs"""
|
||||
iface = MagicMock(autospec=SerialInterface)
|
||||
rhw = RemoteHardwareClient(iface)
|
||||
with caplog.at_level(logging.DEBUG):
|
||||
rhw.watchGPIOs('0x10', 123)
|
||||
assert re.search(r'watchGPIOs', caplog.text, re.MULTILINE)
|
||||
iface.close()
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_sendHardware_no_nodeid():
|
||||
"""Test sending no nodeid to _sendHardware()"""
|
||||
iface = MagicMock(autospec=SerialInterface)
|
||||
with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
|
||||
with pytest.raises(SystemExit) as pytest_wrapped_e:
|
||||
rhw = RemoteHardwareClient(mo)
|
||||
rhw._sendHardware(None, None)
|
||||
assert pytest_wrapped_e.type == SystemExit</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-functions">Functions</h2>
|
||||
<dl>
|
||||
<dt id="meshtastic.tests.test_remote_hardware.test_RemoteHardwareClient"><code class="name flex">
|
||||
<span>def <span class="ident">test_RemoteHardwareClient</span></span>(<span>)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Test that we can instantiate a RemoteHardwareClient instance</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">@pytest.mark.unit
|
||||
def test_RemoteHardwareClient():
|
||||
"""Test that we can instantiate a RemoteHardwareClient instance"""
|
||||
iface = MagicMock(autospec=SerialInterface)
|
||||
rhw = RemoteHardwareClient(iface)
|
||||
assert rhw.iface == iface
|
||||
iface.close()</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.tests.test_remote_hardware.test_RemoteHardwareClient_no_gpio_channel"><code class="name flex">
|
||||
<span>def <span class="ident">test_RemoteHardwareClient_no_gpio_channel</span></span>(<span>capsys)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Test that we can instantiate a RemoteHardwareClient instance but there is no channel named channel 'gpio'</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">@pytest.mark.unit
|
||||
def test_RemoteHardwareClient_no_gpio_channel(capsys):
|
||||
"""Test that we can instantiate a RemoteHardwareClient instance but there is no channel named channel 'gpio'"""
|
||||
iface = MagicMock(autospec=SerialInterface)
|
||||
with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
|
||||
mo.localNode.getChannelByName.return_value = None
|
||||
with pytest.raises(SystemExit) as pytest_wrapped_e:
|
||||
RemoteHardwareClient(mo)
|
||||
assert pytest_wrapped_e.type == SystemExit
|
||||
assert pytest_wrapped_e.value.code == 1
|
||||
out, err = capsys.readouterr()
|
||||
assert re.search(r'Warning: No channel named', out)
|
||||
assert err == ""</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.tests.test_remote_hardware.test_onGPIOreceive"><code class="name flex">
|
||||
<span>def <span class="ident">test_onGPIOreceive</span></span>(<span>capsys)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Test onGPIOreceive</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">@pytest.mark.unit
|
||||
def test_onGPIOreceive(capsys):
|
||||
"""Test onGPIOreceive"""
|
||||
iface = MagicMock(autospec=SerialInterface)
|
||||
packet = {'decoded': {'remotehw': {'typ': 'foo', 'gpioValue': '4096' }}}
|
||||
onGPIOreceive(packet, iface)
|
||||
out, err = capsys.readouterr()
|
||||
assert re.search(r'Received RemoteHardware', out)
|
||||
assert err == ''</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.tests.test_remote_hardware.test_readGPIOs"><code class="name flex">
|
||||
<span>def <span class="ident">test_readGPIOs</span></span>(<span>caplog)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Test readGPIOs</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">@pytest.mark.unit
|
||||
def test_readGPIOs(caplog):
|
||||
"""Test readGPIOs"""
|
||||
iface = MagicMock(autospec=SerialInterface)
|
||||
rhw = RemoteHardwareClient(iface)
|
||||
with caplog.at_level(logging.DEBUG):
|
||||
rhw.readGPIOs('0x10', 123)
|
||||
assert re.search(r'readGPIOs', caplog.text, re.MULTILINE)
|
||||
iface.close()</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.tests.test_remote_hardware.test_sendHardware_no_nodeid"><code class="name flex">
|
||||
<span>def <span class="ident">test_sendHardware_no_nodeid</span></span>(<span>)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Test sending no nodeid to _sendHardware()</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">@pytest.mark.unit
|
||||
def test_sendHardware_no_nodeid():
|
||||
"""Test sending no nodeid to _sendHardware()"""
|
||||
iface = MagicMock(autospec=SerialInterface)
|
||||
with patch('meshtastic.serial_interface.SerialInterface', return_value=iface) as mo:
|
||||
with pytest.raises(SystemExit) as pytest_wrapped_e:
|
||||
rhw = RemoteHardwareClient(mo)
|
||||
rhw._sendHardware(None, None)
|
||||
assert pytest_wrapped_e.type == SystemExit</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.tests.test_remote_hardware.test_watchGPIOs"><code class="name flex">
|
||||
<span>def <span class="ident">test_watchGPIOs</span></span>(<span>caplog)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Test watchGPIOs</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">@pytest.mark.unit
|
||||
def test_watchGPIOs(caplog):
|
||||
"""Test watchGPIOs"""
|
||||
iface = MagicMock(autospec=SerialInterface)
|
||||
rhw = RemoteHardwareClient(iface)
|
||||
with caplog.at_level(logging.DEBUG):
|
||||
rhw.watchGPIOs('0x10', 123)
|
||||
assert re.search(r'watchGPIOs', caplog.text, re.MULTILINE)
|
||||
iface.close()</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.tests.test_remote_hardware.test_writeGPIOs"><code class="name flex">
|
||||
<span>def <span class="ident">test_writeGPIOs</span></span>(<span>caplog)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Test writeGPIOs</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">@pytest.mark.unit
|
||||
def test_writeGPIOs(caplog):
|
||||
"""Test writeGPIOs"""
|
||||
iface = MagicMock(autospec=SerialInterface)
|
||||
rhw = RemoteHardwareClient(iface)
|
||||
with caplog.at_level(logging.DEBUG):
|
||||
rhw.writeGPIOs('0x10', 123, 1)
|
||||
assert re.search(r'writeGPIOs', caplog.text, re.MULTILINE)
|
||||
iface.close()</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
</article>
|
||||
<nav id="sidebar">
|
||||
<h1>Index</h1>
|
||||
<div class="toc">
|
||||
<ul></ul>
|
||||
</div>
|
||||
<ul id="index">
|
||||
<li><h3>Super-module</h3>
|
||||
<ul>
|
||||
<li><code><a title="meshtastic.tests" href="index.html">meshtastic.tests</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-functions">Functions</a></h3>
|
||||
<ul class="">
|
||||
<li><code><a title="meshtastic.tests.test_remote_hardware.test_RemoteHardwareClient" href="#meshtastic.tests.test_remote_hardware.test_RemoteHardwareClient">test_RemoteHardwareClient</a></code></li>
|
||||
<li><code><a title="meshtastic.tests.test_remote_hardware.test_RemoteHardwareClient_no_gpio_channel" href="#meshtastic.tests.test_remote_hardware.test_RemoteHardwareClient_no_gpio_channel">test_RemoteHardwareClient_no_gpio_channel</a></code></li>
|
||||
<li><code><a title="meshtastic.tests.test_remote_hardware.test_onGPIOreceive" href="#meshtastic.tests.test_remote_hardware.test_onGPIOreceive">test_onGPIOreceive</a></code></li>
|
||||
<li><code><a title="meshtastic.tests.test_remote_hardware.test_readGPIOs" href="#meshtastic.tests.test_remote_hardware.test_readGPIOs">test_readGPIOs</a></code></li>
|
||||
<li><code><a title="meshtastic.tests.test_remote_hardware.test_sendHardware_no_nodeid" href="#meshtastic.tests.test_remote_hardware.test_sendHardware_no_nodeid">test_sendHardware_no_nodeid</a></code></li>
|
||||
<li><code><a title="meshtastic.tests.test_remote_hardware.test_watchGPIOs" href="#meshtastic.tests.test_remote_hardware.test_watchGPIOs">test_watchGPIOs</a></code></li>
|
||||
<li><code><a title="meshtastic.tests.test_remote_hardware.test_writeGPIOs" href="#meshtastic.tests.test_remote_hardware.test_writeGPIOs">test_writeGPIOs</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</main>
|
||||
<footer id="footer">
|
||||
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
@@ -133,7 +133,7 @@ def test_smoke1_debug():
|
||||
"""Test --debug"""
|
||||
return_value, out = subprocess.getstatusoutput('meshtastic --info --debug')
|
||||
assert re.search(r'^Owner', out, re.MULTILINE)
|
||||
assert re.search(r'^DEBUG:root', out, re.MULTILINE)
|
||||
assert re.search(r'^DEBUG file', out, re.MULTILINE)
|
||||
assert return_value == 0
|
||||
|
||||
|
||||
@@ -296,11 +296,11 @@ def test_smoke1_ch_values():
|
||||
"""
|
||||
exp = {
|
||||
'--ch-longslow': 'Bw125Cr48Sf4096',
|
||||
# TODO: not sure why these fail thru tests, but ok manually
|
||||
#'--ch-longfast': 'Bw31_25Cr48Sf512',
|
||||
#'--ch-mediumslow': 'Bw250Cr46Sf2048',
|
||||
#'--ch-mediumfast': 'Bw250Cr47Sf1024',
|
||||
# TODO '--ch-shortslow': '?',
|
||||
'--ch-longfast': 'Bw31_25Cr48Sf512',
|
||||
'--ch-mediumslow': 'Bw250Cr46Sf2048',
|
||||
'--ch-mediumfast': 'Bw250Cr47Sf1024',
|
||||
# for some reason, this value does not show any modemConfig
|
||||
'--ch-shortslow': '{ "psk',
|
||||
'--ch-shortfast': 'Bw500Cr45Sf128'
|
||||
}
|
||||
|
||||
@@ -1106,11 +1106,11 @@ def test_smoke1_ch_values():
|
||||
"""
|
||||
exp = {
|
||||
'--ch-longslow': 'Bw125Cr48Sf4096',
|
||||
# TODO: not sure why these fail thru tests, but ok manually
|
||||
#'--ch-longfast': 'Bw31_25Cr48Sf512',
|
||||
#'--ch-mediumslow': 'Bw250Cr46Sf2048',
|
||||
#'--ch-mediumfast': 'Bw250Cr47Sf1024',
|
||||
# TODO '--ch-shortslow': '?',
|
||||
'--ch-longfast': 'Bw31_25Cr48Sf512',
|
||||
'--ch-mediumslow': 'Bw250Cr46Sf2048',
|
||||
'--ch-mediumfast': 'Bw250Cr47Sf1024',
|
||||
# for some reason, this value does not show any modemConfig
|
||||
'--ch-shortslow': '{ "psk',
|
||||
'--ch-shortfast': 'Bw500Cr45Sf128'
|
||||
}
|
||||
|
||||
@@ -1172,7 +1172,7 @@ def test_smoke1_debug():
|
||||
"""Test --debug"""
|
||||
return_value, out = subprocess.getstatusoutput('meshtastic --info --debug')
|
||||
assert re.search(r'^Owner', out, re.MULTILINE)
|
||||
assert re.search(r'^DEBUG:root', out, re.MULTILINE)
|
||||
assert re.search(r'^DEBUG file', out, re.MULTILINE)
|
||||
assert return_value == 0</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
@@ -1819,4 +1819,4 @@ def test_smoke1_test_with_arg_but_no_hardware():
|
||||
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
@@ -29,7 +29,10 @@
|
||||
</summary>
|
||||
<pre><code class="python">"""Meshtastic unit tests for stream_interface.py"""
|
||||
|
||||
import logging
|
||||
import re
|
||||
|
||||
from unittest.mock import MagicMock
|
||||
import pytest
|
||||
|
||||
from ..stream_interface import StreamInterface
|
||||
@@ -37,10 +40,74 @@ from ..stream_interface import StreamInterface
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_StreamInterface():
|
||||
"""Test that we can instantiate a StreamInterface"""
|
||||
"""Test that we cannot instantiate a StreamInterface based on noProto"""
|
||||
with pytest.raises(Exception) as pytest_wrapped_e:
|
||||
StreamInterface(noProto=True)
|
||||
assert pytest_wrapped_e.type == Exception</code></pre>
|
||||
StreamInterface()
|
||||
assert pytest_wrapped_e.type == Exception
|
||||
|
||||
|
||||
# Note: This takes a bit, so moving from unit to slow
|
||||
@pytest.mark.unitslow
|
||||
def test_StreamInterface_with_noProto(caplog, reset_globals):
|
||||
"""Test that we can instantiate a StreamInterface based on nonProto
|
||||
and we can read/write bytes from a mocked stream
|
||||
"""
|
||||
stream = MagicMock()
|
||||
test_data = b'hello'
|
||||
stream.read.return_value = test_data
|
||||
with caplog.at_level(logging.DEBUG):
|
||||
iface = StreamInterface(noProto=True, connectNow=False)
|
||||
iface.stream = stream
|
||||
iface._writeBytes(test_data)
|
||||
data = iface._readBytes(len(test_data))
|
||||
assert data == test_data
|
||||
|
||||
|
||||
# Note: This takes a bit, so moving from unit to slow
|
||||
# Tip: If you want to see the print output, run with '-s' flag:
|
||||
# pytest -s meshtastic/tests/test_stream_interface.py::test_sendToRadioImpl
|
||||
@pytest.mark.unitslow
|
||||
def test_sendToRadioImpl(caplog, reset_globals):
|
||||
"""Test _sendToRadioImpl()"""
|
||||
|
||||
# def add_header(b):
|
||||
# """Add header stuffs for radio"""
|
||||
# bufLen = len(b)
|
||||
# header = bytes([START1, START2, (bufLen >> 8) & 0xff, bufLen & 0xff])
|
||||
# return header + b
|
||||
|
||||
# captured raw bytes of a Heltec2.1 radio with 2 channels (primary and a secondary channel named "gpio")
|
||||
raw_1_my_info = b'\x1a,\x08\xdc\x8c\xd5\xc5\x02\x18\r2\x0e1.2.49.5354c49P\x15]\xe1%\x17Eh\xe0\xa7\x12p\xe8\x9d\x01x\x08\x90\x01\x01'
|
||||
raw_2_node_info = b'"9\x08\xdc\x8c\xd5\xc5\x02\x12(\n\t!28b5465c\x12\x0cUnknown 465c\x1a\x03?5C"\x06$o(\xb5F\\0\n\x1a\x02 1%M<\xc6a'
|
||||
# pylint: disable=C0301
|
||||
raw_3_node_info = b'"C\x08\xa4\x8c\xd5\xc5\x02\x12(\n\t!28b54624\x12\x0cUnknown 4624\x1a\x03?24"\x06$o(\xb5F$0\n\x1a\x07 5MH<\xc6a%G<\xc6a=\x00\x00\xc0@'
|
||||
raw_4_complete = b'@\xcf\xe5\xd1\x8c\x0e'
|
||||
# pylint: disable=C0301
|
||||
raw_5_prefs = b'Z6\r\\F\xb5(\x15\\F\xb5("\x1c\x08\x06\x12\x13*\x11\n\x0f0\x84\x07P\xac\x02\x88\x01\x01\xb0\t#\xb8\t\x015]$\xddk5\xd5\x7f!b=M<\xc6aP\x03`F'
|
||||
# pylint: disable=C0301
|
||||
raw_6_channel0 = b'Z.\r\\F\xb5(\x15\\F\xb5("\x14\x08\x06\x12\x0b:\t\x12\x05\x18\x01"\x01\x01\x18\x015^$\xddk5\xd6\x7f!b=M<\xc6aP\x03`F'
|
||||
# pylint: disable=C0301
|
||||
raw_7_channel1 = b'ZS\r\\F\xb5(\x15\\F\xb5("9\x08\x06\x120:.\x08\x01\x12(" \xb4&\xb3\xc7\x06\xd8\xe39%\xba\xa5\xee\x8eH\x06\xf6\xf4H\xe8\xd5\xc1[ao\xb5Y\\\xb4"\xafmi*\x04gpio\x18\x025_$\xddk5\xd7\x7f!b=M<\xc6aP\x03`F'
|
||||
raw_8_channel2 = b'Z)\r\\F\xb5(\x15\\F\xb5("\x0f\x08\x06\x12\x06:\x04\x08\x02\x12\x005`$\xddk5\xd8\x7f!b=M<\xc6aP\x03`F'
|
||||
raw_blank = b''
|
||||
|
||||
test_data = b'hello'
|
||||
stream = MagicMock()
|
||||
#stream.read.return_value = add_header(test_data)
|
||||
stream.read.side_effect = [ raw_1_my_info, raw_2_node_info, raw_3_node_info, raw_4_complete,
|
||||
raw_5_prefs, raw_6_channel0, raw_7_channel1, raw_8_channel2,
|
||||
raw_blank, raw_blank]
|
||||
toRadio = MagicMock()
|
||||
toRadio.SerializeToString.return_value = test_data
|
||||
with caplog.at_level(logging.DEBUG):
|
||||
iface = StreamInterface(noProto=True, connectNow=False)
|
||||
iface.stream = stream
|
||||
iface.connect()
|
||||
iface._sendToRadioImpl(toRadio)
|
||||
assert re.search(r'Sending: ', caplog.text, re.MULTILINE)
|
||||
assert re.search(r'reading character', caplog.text, re.MULTILINE)
|
||||
assert re.search(r'In reader loop', caplog.text, re.MULTILINE)
|
||||
print(caplog.text)</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
@@ -54,19 +121,98 @@ def test_StreamInterface():
|
||||
<span>def <span class="ident">test_StreamInterface</span></span>(<span>)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Test that we can instantiate a StreamInterface</p></div>
|
||||
<div class="desc"><p>Test that we cannot instantiate a StreamInterface based on noProto</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">@pytest.mark.unit
|
||||
def test_StreamInterface():
|
||||
"""Test that we can instantiate a StreamInterface"""
|
||||
"""Test that we cannot instantiate a StreamInterface based on noProto"""
|
||||
with pytest.raises(Exception) as pytest_wrapped_e:
|
||||
StreamInterface(noProto=True)
|
||||
StreamInterface()
|
||||
assert pytest_wrapped_e.type == Exception</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.tests.test_stream_interface.test_StreamInterface_with_noProto"><code class="name flex">
|
||||
<span>def <span class="ident">test_StreamInterface_with_noProto</span></span>(<span>caplog, reset_globals)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Test that we can instantiate a StreamInterface based on nonProto
|
||||
and we can read/write bytes from a mocked stream</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">@pytest.mark.unitslow
|
||||
def test_StreamInterface_with_noProto(caplog, reset_globals):
|
||||
"""Test that we can instantiate a StreamInterface based on nonProto
|
||||
and we can read/write bytes from a mocked stream
|
||||
"""
|
||||
stream = MagicMock()
|
||||
test_data = b'hello'
|
||||
stream.read.return_value = test_data
|
||||
with caplog.at_level(logging.DEBUG):
|
||||
iface = StreamInterface(noProto=True, connectNow=False)
|
||||
iface.stream = stream
|
||||
iface._writeBytes(test_data)
|
||||
data = iface._readBytes(len(test_data))
|
||||
assert data == test_data</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.tests.test_stream_interface.test_sendToRadioImpl"><code class="name flex">
|
||||
<span>def <span class="ident">test_sendToRadioImpl</span></span>(<span>caplog, reset_globals)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Test _sendToRadioImpl()</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">@pytest.mark.unitslow
|
||||
def test_sendToRadioImpl(caplog, reset_globals):
|
||||
"""Test _sendToRadioImpl()"""
|
||||
|
||||
# def add_header(b):
|
||||
# """Add header stuffs for radio"""
|
||||
# bufLen = len(b)
|
||||
# header = bytes([START1, START2, (bufLen >> 8) & 0xff, bufLen & 0xff])
|
||||
# return header + b
|
||||
|
||||
# captured raw bytes of a Heltec2.1 radio with 2 channels (primary and a secondary channel named "gpio")
|
||||
raw_1_my_info = b'\x1a,\x08\xdc\x8c\xd5\xc5\x02\x18\r2\x0e1.2.49.5354c49P\x15]\xe1%\x17Eh\xe0\xa7\x12p\xe8\x9d\x01x\x08\x90\x01\x01'
|
||||
raw_2_node_info = b'"9\x08\xdc\x8c\xd5\xc5\x02\x12(\n\t!28b5465c\x12\x0cUnknown 465c\x1a\x03?5C"\x06$o(\xb5F\\0\n\x1a\x02 1%M<\xc6a'
|
||||
# pylint: disable=C0301
|
||||
raw_3_node_info = b'"C\x08\xa4\x8c\xd5\xc5\x02\x12(\n\t!28b54624\x12\x0cUnknown 4624\x1a\x03?24"\x06$o(\xb5F$0\n\x1a\x07 5MH<\xc6a%G<\xc6a=\x00\x00\xc0@'
|
||||
raw_4_complete = b'@\xcf\xe5\xd1\x8c\x0e'
|
||||
# pylint: disable=C0301
|
||||
raw_5_prefs = b'Z6\r\\F\xb5(\x15\\F\xb5("\x1c\x08\x06\x12\x13*\x11\n\x0f0\x84\x07P\xac\x02\x88\x01\x01\xb0\t#\xb8\t\x015]$\xddk5\xd5\x7f!b=M<\xc6aP\x03`F'
|
||||
# pylint: disable=C0301
|
||||
raw_6_channel0 = b'Z.\r\\F\xb5(\x15\\F\xb5("\x14\x08\x06\x12\x0b:\t\x12\x05\x18\x01"\x01\x01\x18\x015^$\xddk5\xd6\x7f!b=M<\xc6aP\x03`F'
|
||||
# pylint: disable=C0301
|
||||
raw_7_channel1 = b'ZS\r\\F\xb5(\x15\\F\xb5("9\x08\x06\x120:.\x08\x01\x12(" \xb4&\xb3\xc7\x06\xd8\xe39%\xba\xa5\xee\x8eH\x06\xf6\xf4H\xe8\xd5\xc1[ao\xb5Y\\\xb4"\xafmi*\x04gpio\x18\x025_$\xddk5\xd7\x7f!b=M<\xc6aP\x03`F'
|
||||
raw_8_channel2 = b'Z)\r\\F\xb5(\x15\\F\xb5("\x0f\x08\x06\x12\x06:\x04\x08\x02\x12\x005`$\xddk5\xd8\x7f!b=M<\xc6aP\x03`F'
|
||||
raw_blank = b''
|
||||
|
||||
test_data = b'hello'
|
||||
stream = MagicMock()
|
||||
#stream.read.return_value = add_header(test_data)
|
||||
stream.read.side_effect = [ raw_1_my_info, raw_2_node_info, raw_3_node_info, raw_4_complete,
|
||||
raw_5_prefs, raw_6_channel0, raw_7_channel1, raw_8_channel2,
|
||||
raw_blank, raw_blank]
|
||||
toRadio = MagicMock()
|
||||
toRadio.SerializeToString.return_value = test_data
|
||||
with caplog.at_level(logging.DEBUG):
|
||||
iface = StreamInterface(noProto=True, connectNow=False)
|
||||
iface.stream = stream
|
||||
iface.connect()
|
||||
iface._sendToRadioImpl(toRadio)
|
||||
assert re.search(r'Sending: ', caplog.text, re.MULTILINE)
|
||||
assert re.search(r'reading character', caplog.text, re.MULTILINE)
|
||||
assert re.search(r'In reader loop', caplog.text, re.MULTILINE)
|
||||
print(caplog.text)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
</section>
|
||||
<section>
|
||||
@@ -86,6 +232,8 @@ def test_StreamInterface():
|
||||
<li><h3><a href="#header-functions">Functions</a></h3>
|
||||
<ul class="">
|
||||
<li><code><a title="meshtastic.tests.test_stream_interface.test_StreamInterface" href="#meshtastic.tests.test_stream_interface.test_StreamInterface">test_StreamInterface</a></code></li>
|
||||
<li><code><a title="meshtastic.tests.test_stream_interface.test_StreamInterface_with_noProto" href="#meshtastic.tests.test_stream_interface.test_StreamInterface_with_noProto">test_StreamInterface_with_noProto</a></code></li>
|
||||
<li><code><a title="meshtastic.tests.test_stream_interface.test_sendToRadioImpl" href="#meshtastic.tests.test_stream_interface.test_sendToRadioImpl">test_sendToRadioImpl</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@@ -30,10 +30,13 @@
|
||||
<pre><code class="python">"""Meshtastic unit tests for util.py"""
|
||||
|
||||
import re
|
||||
import logging
|
||||
|
||||
import pytest
|
||||
|
||||
from meshtastic.util import fixme, stripnl, pskToString, our_exit, support_info, genPSK256, fromStr, fromPSK
|
||||
from meshtastic.util import (fixme, stripnl, pskToString, our_exit,
|
||||
support_info, genPSK256, fromStr, fromPSK,
|
||||
quoteBooleans, catchAndIgnore)
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
@@ -64,6 +67,16 @@ def test_fromStr():
|
||||
assert fromStr('abc') == 'abc'
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_quoteBooleans():
|
||||
"""Test quoteBooleans"""
|
||||
assert quoteBooleans('') == ''
|
||||
assert quoteBooleans('foo') == 'foo'
|
||||
assert quoteBooleans('true') == 'true'
|
||||
assert quoteBooleans('false') == 'false'
|
||||
assert quoteBooleans(': true') == ": 'true'"
|
||||
assert quoteBooleans(': false') == ": 'false'"
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_fromPSK():
|
||||
"""Test fromPSK"""
|
||||
@@ -139,7 +152,7 @@ def test_our_exit_non_zero_return_value():
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_fixme():
|
||||
"""Test fixme"""
|
||||
"""Test fixme()"""
|
||||
with pytest.raises(Exception) as pytest_wrapped_e:
|
||||
fixme("some exception")
|
||||
assert pytest_wrapped_e.type == Exception
|
||||
@@ -154,7 +167,17 @@ def test_support_info(capsys):
|
||||
assert re.search(r'Platform', out, re.MULTILINE)
|
||||
assert re.search(r'Machine', out, re.MULTILINE)
|
||||
assert re.search(r'Executable', out, re.MULTILINE)
|
||||
assert err == ''</code></pre>
|
||||
assert err == ''
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_catchAndIgnore(caplog):
|
||||
"""Test catchAndIgnore() does not actually throw an exception, but just logs"""
|
||||
def some_closure():
|
||||
raise Exception('foo')
|
||||
with caplog.at_level(logging.DEBUG):
|
||||
catchAndIgnore("something", some_closure)
|
||||
assert re.search(r'Exception thrown in something', caplog.text, re.MULTILINE)</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
@@ -164,18 +187,37 @@ def test_support_info(capsys):
|
||||
<section>
|
||||
<h2 class="section-title" id="header-functions">Functions</h2>
|
||||
<dl>
|
||||
<dt id="meshtastic.tests.test_util.test_catchAndIgnore"><code class="name flex">
|
||||
<span>def <span class="ident">test_catchAndIgnore</span></span>(<span>caplog)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Test catchAndIgnore() does not actually throw an exception, but just logs</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">@pytest.mark.unit
|
||||
def test_catchAndIgnore(caplog):
|
||||
"""Test catchAndIgnore() does not actually throw an exception, but just logs"""
|
||||
def some_closure():
|
||||
raise Exception('foo')
|
||||
with caplog.at_level(logging.DEBUG):
|
||||
catchAndIgnore("something", some_closure)
|
||||
assert re.search(r'Exception thrown in something', caplog.text, re.MULTILINE)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.tests.test_util.test_fixme"><code class="name flex">
|
||||
<span>def <span class="ident">test_fixme</span></span>(<span>)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Test fixme</p></div>
|
||||
<div class="desc"><p>Test fixme()</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">@pytest.mark.unit
|
||||
def test_fixme():
|
||||
"""Test fixme"""
|
||||
"""Test fixme()"""
|
||||
with pytest.raises(Exception) as pytest_wrapped_e:
|
||||
fixme("some exception")
|
||||
assert pytest_wrapped_e.type == Exception</code></pre>
|
||||
@@ -372,6 +414,26 @@ def test_pskToString_string():
|
||||
assert pskToString('hunter123') == 'secret'</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.tests.test_util.test_quoteBooleans"><code class="name flex">
|
||||
<span>def <span class="ident">test_quoteBooleans</span></span>(<span>)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Test quoteBooleans</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">@pytest.mark.unit
|
||||
def test_quoteBooleans():
|
||||
"""Test quoteBooleans"""
|
||||
assert quoteBooleans('') == ''
|
||||
assert quoteBooleans('foo') == 'foo'
|
||||
assert quoteBooleans('true') == 'true'
|
||||
assert quoteBooleans('false') == 'false'
|
||||
assert quoteBooleans(': true') == ": 'true'"
|
||||
assert quoteBooleans(': false') == ": 'false'"</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.tests.test_util.test_stripnl"><code class="name flex">
|
||||
<span>def <span class="ident">test_stripnl</span></span>(<span>)</span>
|
||||
</code></dt>
|
||||
@@ -429,6 +491,7 @@ def test_support_info(capsys):
|
||||
</li>
|
||||
<li><h3><a href="#header-functions">Functions</a></h3>
|
||||
<ul class="">
|
||||
<li><code><a title="meshtastic.tests.test_util.test_catchAndIgnore" href="#meshtastic.tests.test_util.test_catchAndIgnore">test_catchAndIgnore</a></code></li>
|
||||
<li><code><a title="meshtastic.tests.test_util.test_fixme" href="#meshtastic.tests.test_util.test_fixme">test_fixme</a></code></li>
|
||||
<li><code><a title="meshtastic.tests.test_util.test_fromPSK" href="#meshtastic.tests.test_util.test_fromPSK">test_fromPSK</a></code></li>
|
||||
<li><code><a title="meshtastic.tests.test_util.test_fromStr" href="#meshtastic.tests.test_util.test_fromStr">test_fromStr</a></code></li>
|
||||
@@ -441,6 +504,7 @@ def test_support_info(capsys):
|
||||
<li><code><a title="meshtastic.tests.test_util.test_pskToString_one_byte_zero_value" href="#meshtastic.tests.test_util.test_pskToString_one_byte_zero_value">test_pskToString_one_byte_zero_value</a></code></li>
|
||||
<li><code><a title="meshtastic.tests.test_util.test_pskToString_simple" href="#meshtastic.tests.test_util.test_pskToString_simple">test_pskToString_simple</a></code></li>
|
||||
<li><code><a title="meshtastic.tests.test_util.test_pskToString_string" href="#meshtastic.tests.test_util.test_pskToString_string">test_pskToString_string</a></code></li>
|
||||
<li><code><a title="meshtastic.tests.test_util.test_quoteBooleans" href="#meshtastic.tests.test_util.test_quoteBooleans">test_quoteBooleans</a></code></li>
|
||||
<li><code><a title="meshtastic.tests.test_util.test_stripnl" href="#meshtastic.tests.test_util.test_stripnl">test_stripnl</a></code></li>
|
||||
<li><code><a title="meshtastic.tests.test_util.test_support_info" href="#meshtastic.tests.test_util.test_support_info">test_support_info</a></code></li>
|
||||
</ul>
|
||||
|
||||
@@ -45,6 +45,14 @@ import pkg_resources
|
||||
blacklistVids = dict.fromkeys([0x1366])
|
||||
|
||||
|
||||
def quoteBooleans(a_string):
|
||||
"""Quote booleans
|
||||
given a string that contains ": true", replace with ": 'true'" (or false)
|
||||
"""
|
||||
tmp = a_string.replace(": true", ": 'true'")
|
||||
tmp = tmp.replace(": false", ": 'false'")
|
||||
return tmp
|
||||
|
||||
def genPSK256():
|
||||
"""Generate a random preshared key"""
|
||||
return os.urandom(32)
|
||||
@@ -123,7 +131,7 @@ def fixme(message):
|
||||
|
||||
|
||||
def catchAndIgnore(reason, closure):
|
||||
"""Call a closure but if it throws an excpetion print it and continue"""
|
||||
"""Call a closure but if it throws an exception print it and continue"""
|
||||
try:
|
||||
closure()
|
||||
except BaseException as ex:
|
||||
@@ -235,13 +243,13 @@ def support_info():
|
||||
<span>def <span class="ident">catchAndIgnore</span></span>(<span>reason, closure)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Call a closure but if it throws an excpetion print it and continue</p></div>
|
||||
<div class="desc"><p>Call a closure but if it throws an exception print it and continue</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def catchAndIgnore(reason, closure):
|
||||
"""Call a closure but if it throws an excpetion print it and continue"""
|
||||
"""Call a closure but if it throws an exception print it and continue"""
|
||||
try:
|
||||
closure()
|
||||
except BaseException as ex:
|
||||
@@ -413,6 +421,25 @@ return_value defaults to 1 (non-successful)</p></div>
|
||||
return "secret"</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.util.quoteBooleans"><code class="name flex">
|
||||
<span>def <span class="ident">quoteBooleans</span></span>(<span>a_string)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Quote booleans
|
||||
given a string that contains ": true", replace with ": 'true'" (or false)</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def quoteBooleans(a_string):
|
||||
"""Quote booleans
|
||||
given a string that contains ": true", replace with ": 'true'" (or false)
|
||||
"""
|
||||
tmp = a_string.replace(": true", ": 'true'")
|
||||
tmp = tmp.replace(": false", ": 'false'")
|
||||
return tmp</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="meshtastic.util.stripnl"><code class="name flex">
|
||||
<span>def <span class="ident">stripnl</span></span>(<span>s)</span>
|
||||
</code></dt>
|
||||
@@ -626,6 +653,7 @@ return_value defaults to 1 (non-successful)</p></div>
|
||||
<li><code><a title="meshtastic.util.genPSK256" href="#meshtastic.util.genPSK256">genPSK256</a></code></li>
|
||||
<li><code><a title="meshtastic.util.our_exit" href="#meshtastic.util.our_exit">our_exit</a></code></li>
|
||||
<li><code><a title="meshtastic.util.pskToString" href="#meshtastic.util.pskToString">pskToString</a></code></li>
|
||||
<li><code><a title="meshtastic.util.quoteBooleans" href="#meshtastic.util.quoteBooleans">quoteBooleans</a></code></li>
|
||||
<li><code><a title="meshtastic.util.stripnl" href="#meshtastic.util.stripnl">stripnl</a></code></li>
|
||||
<li><code><a title="meshtastic.util.support_info" href="#meshtastic.util.support_info">support_info</a></code></li>
|
||||
</ul>
|
||||
|
||||
@@ -37,6 +37,7 @@ unicode scripts they can be different.
|
||||
# Example Usage
|
||||
```
|
||||
import meshtastic
|
||||
import meshtastic.serial_interface
|
||||
from pubsub import pub
|
||||
|
||||
def onReceive(packet, interface): # called when a packet arrives
|
||||
@@ -49,7 +50,7 @@ def onConnection(interface, topic=pub.AUTO_TOPIC): # called when we (re)connect
|
||||
pub.subscribe(onReceive, "meshtastic.receive")
|
||||
pub.subscribe(onConnection, "meshtastic.connection.established")
|
||||
# By default will try to find a meshtastic device, otherwise provide a device path like /dev/ttyUSB0
|
||||
interface = meshtastic.SerialInterface()
|
||||
interface = meshtastic.serial_interface.SerialInterface()
|
||||
|
||||
```
|
||||
|
||||
@@ -80,23 +81,23 @@ from .util import fixme, catchAndIgnore, stripnl, DeferredExecution, Timeout
|
||||
from .node import Node
|
||||
from . import mesh_pb2, portnums_pb2, apponly_pb2, admin_pb2, environmental_measurement_pb2, remote_hardware_pb2, channel_pb2, radioconfig_pb2, util
|
||||
|
||||
# Note: To follow PEP224, comments should be after the module variable.
|
||||
|
||||
"""A special ID that means the local node"""
|
||||
LOCAL_ADDR = "^local"
|
||||
"""A special ID that means the local node"""
|
||||
|
||||
# if using 8 bit nodenums this will be shortend on the target
|
||||
BROADCAST_NUM = 0xffffffff
|
||||
"""if using 8 bit nodenums this will be shortend on the target"""
|
||||
|
||||
"""A special ID that means broadcast"""
|
||||
BROADCAST_ADDR = "^all"
|
||||
"""A special ID that means broadcast"""
|
||||
|
||||
|
||||
OUR_APP_VERSION = 20200
|
||||
"""The numeric buildnumber (shared with android apps) specifying the
|
||||
level of device code we are guaranteed to understand
|
||||
|
||||
format is Mmmss (where M is 1+the numeric major number. i.e. 20120 means 1.1.20
|
||||
"""
|
||||
OUR_APP_VERSION = 20200
|
||||
|
||||
publishingThread = DeferredExecution("publishing")
|
||||
|
||||
|
||||
@@ -18,8 +18,8 @@ from . import portnums_pb2, channel_pb2, radioconfig_pb2
|
||||
from .globals import Globals
|
||||
|
||||
|
||||
"""We only import the tunnel code if we are on a platform that can run it. """
|
||||
have_tunnel = platform.system() == 'Linux'
|
||||
"""We only import the tunnel code if we are on a platform that can run it. """
|
||||
|
||||
def onReceive(packet, interface):
|
||||
"""Callback invoked when a packet arrives"""
|
||||
|
||||
Reference in new issue
Block a user